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 SXEmacs
7 SXEmacs is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 SXEmacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
21 /* Synched up with: FSF 19.30. */
23 /* This file has been Mule-ized except as noted. */
30 #include "ui/insdel.h"
31 #include "ui/keymap.h"
34 Lisp_Object Vinternal_doc_file_name;
35 Lisp_Object Vinternal_doc_fd;
37 Lisp_Object QSsubstitute, Qdefvar;
40 extern unsigned int dump_id;
43 /* Work out what source file a function or variable came from, taking the
44 information from the documentation file. */
46 static Lisp_Object extract_object_file_name (int fd, EMACS_INT doc_pos,
47 SBufbyte *name_nonreloc,
48 Lisp_Object name_reloc,
49 int standard_doc_file)
51 Bufbyte buf[DOC_MAX_FILENAME_LENGTH+1];
52 Bufbyte *buffer = buf;
53 int buffer_size = sizeof (buf) - 1, space_left;
55 REGISTER Bufbyte *p = buffer;
56 Lisp_Object return_me;
57 EMACS_INT position, seenS = 0;
59 position = doc_pos > buffer_size ?
60 doc_pos - buffer_size : 0;
62 if (0 > lseek (fd, position, 0)) {
64 name_reloc = build_string (name_nonreloc);
65 return_me = list3 (build_string
66 ("Position out of range in doc string file"),
67 name_reloc, make_int (position));
71 space_left = buffer_size - (p - buffer);
72 while (space_left > 0) {
75 nread = read (fd, p, space_left);
79 ("Read error on documentation file"));
89 space_left = buffer_size - (p - buffer);
92 /* First, search backward for the "\037S" that marks the beginning
93 of the file name, then search forward from that to the newline or
94 to the end of the buffer. */
100 if ('\037' == *from) {
102 /* Got a file name; adjust `from' to point
103 to it, break out of the loop. */
109 seenS = ('S' == *from);
113 /* We've scanned back to the beginning of the buffer without
114 hitting the file name. Either the file name plus the
115 symbol name is longer than DOC_MAX_FILENAME_LENGTH--which
116 shouldn't happen, because it'll trigger an assertion
117 failure in make-docfile, the DOC file is corrupt, or it
118 was produced by a version of make-docfile that doesn't
119 store the file name with the symbol name and
121 return_me = list1 (build_string
122 ("Object file name not stored in doc file"));
127 /* Search for the end of the file name. */
129 if ('\n' == *to || '\037' == *to) {
134 /* Don't require the file name to end in a newline. */
135 return_me = make_string (from, to - from);
142 /* Read and return doc string from open file descriptor FD
143 at position POSITION. Does not close the file. Returns
144 string; or if error, returns a cons holding the error
145 data to pass to Fsignal. NAME_NONRELOC and NAME_RELOC
146 are only used for the error messages. */
149 unparesseuxify_doc_string(int fd, EMACS_INT position,
150 char *name_nonreloc, Lisp_Object name_reloc)
152 char buf[512 * 8 + 1];
154 int buffer_size = sizeof(buf)-1;
156 REGISTER char *p = buffer;
157 Lisp_Object return_me;
159 if (0 > lseek(fd, position, 0)) {
161 name_reloc = build_string(name_nonreloc);
162 return_me = list3(build_string
163 ("Position out of range in doc string file"),
164 name_reloc, make_int(position));
168 /* Read the doc string into a buffer.
169 Use the fixed buffer BUF if it is big enough; otherwise allocate one.
170 We store the buffer in use in BUFFER and its size in BUFFER_SIZE. */
173 int space_left = buffer_size - (p - buffer);
176 /* Switch to a bigger buffer if we need one. */
177 if (space_left == 0) {
178 char *old_buffer = buffer;
181 buffer = (char*)xmalloc_atomic(buffer_size + 1);
182 memcpy(buffer, old_buffer, p - old_buffer);
184 char *foo = xrealloc(buffer, buffer_size + 1);
187 p += buffer - old_buffer;
188 space_left = buffer_size - (p - buffer);
191 /* Don't read too much at one go. */
192 if (space_left > 1024 * 8)
193 space_left = 1024 * 8;
194 nread = read(fd, p, space_left);
196 return_me = list1(build_string
197 ("Read error on documentation file"));
204 char *p1 = strchr(p, '\037'); /* End of doc string marker */
214 /* Scan the text and remove quoting with ^A (char code 1).
215 ^A^A becomes ^A, ^A0 becomes a null char, and ^A_ becomes a ^_. */
218 if (*from != 1 /*^A */ )
235 return_me = list2(build_string
236 ("Invalid data in documentation file -- ^A followed by weird code"),
243 /* #### mrb: following STILL completely broken */
244 return_me = make_ext_string(buffer, to - buffer, Qbinary);
247 if (buffer != buf) /* We must have allocated buffer above */
252 #define string_join(dest, s1, s2) \
253 memcpy ((void *) dest, (void *) XSTRING_DATA (s1), XSTRING_LENGTH (s1)); \
254 memcpy ((void *) ((Bufbyte *) dest + XSTRING_LENGTH (s1)), \
255 (void *) XSTRING_DATA (s2), XSTRING_LENGTH (s2)); \
256 dest[XSTRING_LENGTH (s1) + XSTRING_LENGTH (s2)] = '\0'
258 /* Extract a doc string from a file. FILEPOS says where to get it.
259 (This could actually be byte code instructions/constants instead
261 If it is an integer, use that position in the standard DOC file.
262 If it is (FILE . INTEGER), use FILE as the file name
263 and INTEGER as the position in that file.
264 But if INTEGER is negative, make it positive.
265 (A negative integer is used for user variables, so we can distinguish
266 them without actually fetching the doc string.) */
269 get_doc_string(Lisp_Object filepos)
271 /* !!#### This function has not been Mule-ized */
272 REGISTER int fd = -1;
273 REGISTER char *name_nonreloc = 0;
275 Lisp_Object file, tem;
276 Lisp_Object name_reloc = Qnil;
279 file = Vinternal_doc_file_name;
280 position = XINT(filepos);
281 if ( INTP(Vinternal_doc_fd) )
282 fd = XINT(Vinternal_doc_fd);
285 } else if (CONSP(filepos) && INTP(XCDR(filepos))) {
286 file = XCAR(filepos);
287 position = XINT(XCDR(filepos));
289 position = -position;
299 /* Put the file name in NAME as a C string.
300 If it is relative, combine it with Vdoc_directory. */
302 tem = Ffile_name_absolute_p(file);
305 /* XEmacs: Move this check here. OK if called during loadup to
306 load byte code instructions. */
307 if (!STRINGP(Vdoc_directory))
310 minsize = XSTRING_LENGTH(Vdoc_directory);
311 /* sizeof ("./") == 3 */
315 (char *)alloca(minsize + XSTRING_LENGTH(file) + 8);
316 string_join(name_nonreloc, Vdoc_directory, file);
320 ofd = open(name_nonreloc ? name_nonreloc :
321 (char *)XSTRING_DATA(name_reloc), O_RDONLY | OPEN_BINARY, 0);
323 Vinternal_doc_fd = make_int(ofd);
329 /* sizeof ("./") == 3 */
331 (char *)alloca(3 + XSTRING_LENGTH(file) + 8);
332 /* Preparing to dump; DOC file is probably not installed.
333 So check in ../lib-src. */
334 strcpy(name_nonreloc, "./");
335 strcat(name_nonreloc, (char *)XSTRING_DATA(file));
337 fd = open(name_nonreloc, O_RDONLY | OPEN_BINARY, 0);
339 #endif /* CANNOT_DUMP */
342 error("Cannot open doc string file \"%s\"",
343 name_nonreloc ? name_nonreloc :
344 (char *)XSTRING_DATA(name_reloc));
348 unparesseuxify_doc_string(fd, position, name_nonreloc, name_reloc);
349 if (!INTP(Vinternal_doc_fd) || (fd != XINT(Vinternal_doc_fd))) {
350 Vinternal_doc_fd = make_int(-2);
357 signal_error(Qerror, tem);
362 /* Get a string from position FILEPOS and pass it through the Lisp reader.
363 We use this for fetching the bytecode string and constants vector
364 of a compiled function from the .elc file. */
366 Lisp_Object read_doc_string(Lisp_Object filepos)
368 Lisp_Object string = get_doc_string(filepos);
370 if (!STRINGP(string))
371 signal_simple_error("loading bytecode failed to return string",
373 return Fread(string);
376 static Lisp_Object get_object_file_name (Lisp_Object filepos) {
377 REGISTER int fd = -1;
378 REGISTER SBufbyte *name_nonreloc = 0;
380 Lisp_Object file, tem;
381 Lisp_Object name_reloc = Qnil;
382 int standard_doc_file = 0;
384 if (INTP (filepos)) {
385 file = Vinternal_doc_file_name;
386 standard_doc_file = 1;
387 position = XINT (filepos);
388 if ( INTP(Vinternal_doc_fd) )
389 fd = XINT(Vinternal_doc_fd);
392 } else if (CONSP (filepos) && INTP (XCDR (filepos))) {
393 file = XCAR (filepos);
394 position = XINT (XCDR (filepos));
396 position = - position;
402 /* Put the file name in NAME as a C string.
403 If it is relative, combine it with Vdoc_directory. */
405 tem = Ffile_name_absolute_p (file);
408 /* XEmacs: Move this check here. OK if called during loadup to
409 load byte code instructions. */
410 if (!STRINGP (Vdoc_directory))
413 minsize = XSTRING_LENGTH (Vdoc_directory);
414 /* sizeof ("../lib-src/") == 12 */
417 name_nonreloc = alloca_array (SBufbyte,
419 XSTRING_LENGTH (file) + 8);
420 string_join (name_nonreloc, Vdoc_directory, file);
421 } else name_reloc = file;
427 /* sizeof ("../lib-src/") == 12 */
429 = alloca_array (SBufbyte,
430 12 + XSTRING_LENGTH (file) + 8);
431 /* Preparing to dump; DOC file is probably not
432 installed. So check in ../lib-src. */
434 strcpy (name_nonreloc, "../lib-src/");
435 strcat (name_nonreloc, (char *)XSTRING_DATA (file));
437 fd = open (name_nonreloc, O_RDONLY | OPEN_BINARY, 0);
440 ofd = open (name_nonreloc ? name_nonreloc :
441 (char *)XSTRING_DATA (name_reloc),
442 O_RDONLY | OPEN_BINARY, 0);
445 Vinternal_doc_fd = make_int (ofd);
449 report_file_error ("Cannot open doc string file",
451 build_string (name_nonreloc) :
455 tem = extract_object_file_name (fd, position, name_nonreloc, name_reloc,
457 if (!INTP(Vinternal_doc_fd) || (fd != XINT(Vinternal_doc_fd))) {
458 Vinternal_doc_fd = make_int(-2);
464 signal_error (Qinvalid_byte_code, tem);
471 weird_doc(Lisp_Object sym, const char *weirdness, const char *type, int pos)
473 if (!strcmp(weirdness, GETTEXT("duplicate")))
475 message("Note: Strange doc (%s) for %s %s @ %d",
476 weirdness, type, string_data(XSYMBOL(sym)->name), pos);
479 DEFUN ("built-in-symbol-file", Fbuilt_in_symbol_file, 1, 2, 0, /*
480 Return the C source file built-in symbol SYM comes from.
481 Don't use this. Use the more general `symbol-file' (q.v.) instead.
483 If TYPE is nil or omitted, any kind of definition is acceptable.
484 If TYPE is `defun', then function, subr, special form or macro definitions
486 If TYPE is `defvar', then variable definitions are acceptable.
490 /* This function can GC */
492 Lisp_Object filename = Qnil;
494 if (EQ(Ffboundp(symbol), Qt) && (EQ(type, Qnil) || EQ(type, Qdefun))) {
495 fun = Findirect_function (symbol);
497 if (SUBRP (fun) || (CONSP(fun) && (EQ (Qmacro, Fcar_safe (fun)))
498 && (fun = Fcdr_safe (fun), SUBRP (fun)))) {
499 if (XSUBR (fun)->doc == 0)
502 if ((EMACS_INT) XSUBR (fun)->doc >= 0) {
505 "No file info available for function",
506 GETTEXT("function"), 0);
509 filename = get_object_file_name
517 if (COMPILED_FUNCTIONP (fun)
518 || (CONSP(fun) && (EQ (Qmacro, Fcar_safe (fun)))
519 && (fun = Fcdr_safe (fun),
520 COMPILED_FUNCTIONP (fun)))) {
522 Lisp_Compiled_Function *f = XCOMPILED_FUNCTION (fun);
524 if (! (f->flags.documentationp))
526 tem = compiled_function_documentation (f);
527 if (NATNUMP (tem) || CONSP (tem)) {
528 filename = get_object_file_name (tem);
534 if (EQ(Fboundp(symbol), Qt) && (EQ(type, Qnil) || EQ(type, Qdefvar))) {
535 Lisp_Object doc_offset
536 = Fget (symbol, Qvariable_documentation, Qnil);
538 if (!NILP(doc_offset)) {
539 if (INTP(doc_offset)) {
540 filename = get_object_file_name
541 (XINT (doc_offset) > 0 ? doc_offset
542 : make_int (- XINT (doc_offset)));
543 } else if (CONSP(doc_offset)) {
544 filename = get_object_file_name(doc_offset);
552 DEFUN("documentation", Fdocumentation, 1, 2, 0, /*
553 Return the documentation string of FUNCTION.
554 Unless a non-nil second argument RAW is given, the
555 string is passed through `substitute-command-keys'.
559 /* This function can GC */
563 fun = Findirect_function(function);
566 if (XSUBR(fun)->doc == 0)
568 if ((EMACS_INT) XSUBR(fun)->doc >= 0)
569 doc = build_string(XSUBR(fun)->doc);
572 get_doc_string(make_int
573 (-(EMACS_INT) XSUBR(fun)->doc));
574 } else if (COMPILED_FUNCTIONP(fun)) {
576 Lisp_Compiled_Function *f = XCOMPILED_FUNCTION(fun);
577 if (!(f->flags.documentationp))
579 tem = compiled_function_documentation(f);
582 else if (NATNUMP(tem) || CONSP(tem))
583 doc = get_doc_string(tem);
586 } else if (KEYMAPP(fun))
588 build_translated_string
589 ("Prefix command (definition is a keymap of subcommands).");
590 else if (STRINGP(fun) || VECTORP(fun))
591 return build_translated_string("Keyboard macro.");
592 else if (CONSP(fun)) {
593 Lisp_Object funcar = Fcar(fun);
595 if (!SYMBOLP(funcar))
596 return Fsignal(Qinvalid_function, list1(fun));
597 else if (EQ(funcar, Qlambda)
598 || EQ(funcar, Qautoload)) {
599 Lisp_Object tem, tem1;
600 tem1 = Fcdr(Fcdr(fun));
604 /* Handle a doc reference--but these never come last
605 in the function body, so reject them if they are last. */
606 else if ((NATNUMP(tem) || CONSP(tem))
607 && !NILP(XCDR(tem1)))
608 doc = get_doc_string(tem);
611 } else if (EQ(funcar, Qmacro))
612 return Fdocumentation(Fcdr(fun), raw);
617 return Fsignal(Qinvalid_function, list1(fun));
623 Lisp_Object domain = Qnil;
624 if (COMPILED_FUNCTIONP(fun))
626 compiled_function_domain(XCOMPILED_FUNCTION(fun));
630 doc = Fdgettext(domain, doc);
634 doc = Fsubstitute_command_keys(doc);
640 DEFUN("documentation-property", Fdocumentation_property, 2, 3, 0, /*
641 Return the documentation string that is SYMBOL's PROP property.
642 This is like `get', but it can refer to strings stored in the
643 `doc-directory/DOC' file; and if the value is a string, it is passed
644 through `substitute-command-keys'. A non-nil third argument avoids this
649 /* This function can GC */
650 REGISTER Lisp_Object doc = Qnil;
652 REGISTER Lisp_Object domain;
658 doc = Fget(symbol, prop, Qnil);
661 get_doc_string(XINT(doc) > 0 ? doc : make_int(-XINT(doc)));
663 doc = get_doc_string(doc);
666 domain = Fget(symbol, Qvariable_domain, Qnil);
670 doc = Fdgettext(domain, doc);
673 if (NILP(raw) && STRINGP(doc))
674 doc = Fsubstitute_command_keys(doc);
680 DEFUN("Snarf-documentation", Fsnarf_documentation, 1, 1, 0, /*
681 Used during Emacs initialization, before dumping runnable Emacs,
682 to find pointers to doc strings stored in `.../lib-src/DOC' and
683 record them in function definitions.
684 One arg, FILENAME, a string which does not include a directory.
685 The file is written to `../lib-src', and later found in `exec-directory'
686 when doc strings are referred to in the dumped Emacs.
690 /* !!#### This function has not been Mule-ized */
695 REGISTER char *p, *end;
696 Lisp_Object sym, fun, tem;
701 error("Snarf-documentation can only be called in an undumped "
705 CHECK_STRING(filename);
708 if (!NILP(Vdoc_directory)) {
709 int alloca_sz = XSTRING_LENGTH(filename)
710 + XSTRING_LENGTH(Vdoc_directory) + 1 + 9;
712 CHECK_STRING(Vdoc_directory);
713 name = (char *)alloca(alloca_sz);
714 prt = snprintf(name, alloca_sz, "%s%s",
715 (char*)XSTRING_DATA(Vdoc_directory),
716 (char*)XSTRING_DATA(filename));
717 assert(prt>=0 && prt < alloca_sz);
719 #endif /* CANNOT_DUMP */
721 int alloca_sz = 2 + XSTRING_LENGTH(filename) + 3 + 9 + 1;
723 name = (char *)alloca(alloca_sz);
724 prt = snprintf(name, alloca_sz, "./%s",
725 (char*)XSTRING_DATA(filename));
726 assert(prt >= 0 && prt < alloca_sz);
729 fd = open(name, O_RDONLY | OPEN_BINARY, 0);
731 report_file_error("Opening doc string file",
732 Fcons(build_string(name), Qnil));
733 Vinternal_doc_file_name = filename;
739 read(fd, &buf[filled], sizeof buf - 1 - filled);
745 end = buf + (filled < 512 ? filled : filled - 128);
746 while (p != end && *p != '\037')
748 /* p points to ^_Ffunctionname\n or ^_Vvarname\n. */
750 end = strchr(p, '\n');
752 report_file_error("Bad format in file",
753 Fcons(build_string(name), Qnil));
758 oblookup(Vobarray, (Bufbyte *) p + 2, end - p - 2);
761 make_int(pos + end + 1 - buf);
762 /* Attach a docstring to a variable */
764 /* Install file-position as variable-documentation property
765 and make it negative for a user-variable
766 (doc starts with a `*'). */
768 Fget(sym, Qvariable_documentation,
772 GETTEXT("duplicate"),
775 /* In the case of duplicate doc file entries, always
776 take the later one. But if the doc is not an int
777 (a string, say) leave it alone. */
781 Fput(sym, Qvariable_documentation,
783 ? make_int(-XINT(offset))
786 /* Attach a docstring to a function.
787 The type determines where the docstring is stored. */
788 else if (p[1] == 'F') {
789 fun = indirect_function(sym, 0);
791 if (CONSP(fun) && EQ(XCAR(fun), Qmacro))
795 /* May have been #if'ed out or something */
802 } else if (SUBRP(fun)) {
803 /* Lisp_Subrs have a slot for it. */
804 if (XSUBR(fun)->doc) {
814 (char *)(-XINT(offset));
815 } else if (CONSP(fun)) {
816 /* If it's a lisp form, stick it in the form. */
819 || EQ(tem, Qautoload)) {
820 tem = Fcdr(Fcdr(fun));
840 /* In the case of duplicate doc file entries,
841 always take the later one. But if the doc
842 is not an int (a string, say) leave it
849 } else if (!CONSP(tem)) {
858 /* DOC string is a string not integer 0 */
862 ("!INTP(XCAR(tem))"),
872 ("not lambda or autoload"),
878 } else if (COMPILED_FUNCTIONP(fun)) {
879 /* Compiled-Function objects sometimes have
881 Lisp_Compiled_Function *f =
882 XCOMPILED_FUNCTION(fun);
884 /* This compiled-function object must have a
885 slot for the docstring, since we've found a
886 docstring for it. Unless there were multiple
887 definitions of it, and the latter one didn't
888 have any doc, which is a legal if slightly
889 bogus situation, so don't blow up. */
891 if (!(f->flags.documentationp)) {
901 compiled_function_documentation
910 /* In the case of duplicate doc file entries,
911 always take the later one. But if the doc is
912 not an int (a string, say) leave it alone. */
916 set_compiled_function_documentation
920 /* Otherwise the function is undefined or
921 otherwise weird. Ignore it. */
931 error("DOC file invalid at position %d",
941 memmove(buf, end, filled);
947 #if 1 /* Don't warn about functions whose doc was lost because they were
948 wrapped by advice-freeze.el... */
949 static int kludgily_ignore_lost_doc_p(Lisp_Object sym)
951 # define kludge_prefix "ad-Orig-"
952 Lisp_String *name = XSYMBOL(sym)->name;
953 return (string_length(name) > (Bytecount) (sizeof(kludge_prefix)) &&
954 !strncmp((char *)string_data(name), kludge_prefix,
955 sizeof(kludge_prefix) - 1));
956 # undef kludge_prefix
959 # define kludgily_ignore_lost_doc_p(sym) 0
962 static int verify_doc_mapper(Lisp_Object sym, void *arg)
964 Lisp_Object closure = *(Lisp_Object *) arg;
966 if (!NILP(Ffboundp(sym))) {
968 Lisp_Object fun = XSYMBOL(sym)->function;
969 if (CONSP(fun) && EQ(XCAR(fun), Qmacro))
973 doc = (EMACS_INT) XSUBR(fun)->doc;
974 else if (SYMBOLP(fun))
976 else if (KEYMAPP(fun))
978 else if (CONSP(fun)) {
979 Lisp_Object tem = XCAR(fun);
980 if (EQ(tem, Qlambda) || EQ(tem, Qautoload)) {
982 tem = Fcdr(Fcdr(fun));
983 if (CONSP(tem) && INTP(XCAR(tem)))
984 doc = XINT(XCAR(tem));
986 } else if (COMPILED_FUNCTIONP(fun)) {
987 Lisp_Compiled_Function *f = XCOMPILED_FUNCTION(fun);
988 if (!(f->flags.documentationp))
992 compiled_function_documentation(f);
998 if (doc == 0 && !kludgily_ignore_lost_doc_p(sym)) {
999 message("Warning: doc lost for function %s.",
1000 string_data(XSYMBOL(sym)->name));
1004 if (!NILP(Fboundp(sym))) {
1005 Lisp_Object doc = Fget(sym, Qvariable_documentation, Qnil);
1007 message("Warning: doc lost for variable %s.",
1008 string_data(XSYMBOL(sym)->name));
1012 return 0; /* Never stop */
1015 DEFUN("Verify-documentation", Fverify_documentation, 0, 0, 0, /*
1016 Used to make sure everything went well with Snarf-documentation.
1017 Writes to stderr if not.
1021 Lisp_Object closure = Fcons(Qnil, Qnil);
1022 struct gcpro gcpro1;
1024 map_obarray(Vobarray, verify_doc_mapper, &closure);
1025 if (!NILP(Fcdr(closure)))
1027 "This is usually because some files were preloaded by loaddefs.el or\n"
1028 "site-load.el, but were not passed to make-docfile by Makefile.\n");
1030 return NILP(Fcdr(closure)) ? Qt : Qnil;
1033 DEFUN("substitute-command-keys", Fsubstitute_command_keys, 1, 1, 0, /*
1034 Substitute key descriptions for command names in STRING.
1035 Return a new string which is STRING with substrings of the form \\=\\[COMMAND]
1036 replaced by either: a keystroke sequence that will invoke COMMAND,
1037 or "M-x COMMAND" if COMMAND is not on any keys.
1038 Substrings of the form \\=\\{MAPVAR} are replaced by summaries
1039 \(made by `describe-bindings') of the value of MAPVAR, taken as a keymap.
1040 Substrings of the form \\=\\<MAPVAR> specify to use the value of MAPVAR
1041 as the keymap for future \\=\\[COMMAND] substrings.
1042 \\=\\= quotes the following character and is discarded;
1043 thus, \\=\\=\\=\\= puts \\=\\= into the output, and \\=\\=\\=\\[ puts \\=\\[ into the output.
1047 /* This function can GC */
1050 REGISTER Bufbyte *strdata;
1051 REGISTER Bufbyte *bufp;
1052 Bytecount strlength;
1056 Lisp_Object tem = Qnil;
1057 Lisp_Object keymap = Qnil;
1058 Lisp_Object name = Qnil;
1061 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
1066 CHECK_STRING(string);
1067 GCPRO4(string, tem, keymap, name);
1069 /* There is the possibility that the string is not destined for a
1070 translating stream, and it could be argued that we should do the
1071 same thing here as in Fformat(), but there are very few times
1072 when this will be the case and many calls to this function
1073 would have to have `gettext' calls added. (I18N3) */
1074 string = LISP_GETTEXT(string);
1076 /* KEYMAP is either nil (which means search all the active keymaps)
1077 or a specified local map (which means search just that and the
1078 global map). If non-nil, it might come from Voverriding_local_map,
1079 or from a \\<mapname> construct in STRING itself.. */
1081 /* This is really weird and garbagey. If keymap is nil and there's
1082 an overriding-local-map, `where-is-internal' will correctly note
1083 this, so there's no reason to do it here. Maybe FSFmacs
1084 `where-is-internal' is broken. */
1086 keymap = current_kboard->Voverriding_terminal_local_map;
1088 keymap = Voverriding_local_map;
1092 strlength = XSTRING_LENGTH(string);
1093 bsize = 1 + strlength;
1094 buf = (Bufbyte*)xmalloc_atomic(bsize);
1097 /* Have to reset strdata every time GC might be called */
1098 strdata = XSTRING_DATA(string);
1099 for (idx = 0; idx < strlength;) {
1100 Bufbyte *strp = strdata + idx;
1102 if (strp[0] != '\\') {
1103 /* just copy other chars */
1104 /* As it happens, this will work with Mule even if the
1105 character quoted is multi-byte; the remaining multi-byte
1106 characters will just be copied by this loop. */
1112 /* just copy unknown escape sequences */
1118 /* \= quotes the next character; thus, to put in
1119 \[ without its special meaning, use \=\[. */
1120 /* As it happens, this will work with Mule even
1121 if the character quoted is multi-byte; the
1122 remaining multi-byte characters will just be
1123 copied by this loop. */
1131 idx += 2; /* skip \[ */
1135 while ((idx < strlength)
1140 length = strp - start;
1143 tem = Fintern(make_string(start, length), Qnil);
1144 tem = Fwhere_is_internal(
1145 tem, keymap, Qt, Qnil, Qnil);
1148 /* Disregard menu bar bindings; it is
1149 positively annoying to mention them
1150 when there's no menu bar, and it
1151 isn't terribly useful even when there
1154 firstkey = Faref(tem, Qzero);
1155 if (EQ(firstkey, Qmenu_bar))
1161 /* but not on any keys */
1162 new = xrealloc(buf, bsize += 4);
1165 memcpy(bufp, "M-x ", 4);
1168 } else { /* function is on a key */
1169 tem = Fkey_description(tem);
1175 Lisp_Object buffer =
1176 Fget_buffer_create(QSsubstitute);
1177 struct buffer *buf_ = XBUFFER(buffer);
1179 Fbuffer_disable_undo(buffer);
1180 Ferase_buffer(buffer);
1182 /* \{foo} is replaced with a summary of keymap
1183 (symbol-value foo). \<foo> just sets the
1184 keymap used for \[cmd]. */
1186 idx += 2; /* skip \{ or \< */
1190 while ((idx < strlength)
1191 && *strp != '}' && *strp != '>') {
1195 length = strp - start;
1196 idx++; /* skip } or > */
1198 /* Get the value of the keymap in TEM,
1199 or nil if undefined. Do this while
1200 still in the user's current buffer in
1201 case it is a local variable. */
1203 make_string(start, length), Qnil);
1204 tem = Fboundp(name);
1206 tem = Fsymbol_value(name);
1208 tem = get_keymap(tem, 0, 1);
1213 buffer_insert_c_string(
1214 buf_, "(uses keymap \"");
1215 buffer_insert_lisp_string(
1216 buf_, Fsymbol_name(name));
1217 buffer_insert_c_string(
1218 buf_, "\", which is not "
1219 "currently defined) ");
1221 if (start[-1] == '<') {
1224 } else if (start[-1] == '<') {
1228 tem, 1, Qnil, Qnil, 0, buffer);
1230 tem = make_string_from_buffer(
1231 buf_, BUF_BEG(buf_),
1232 BUF_Z(buf_) - BUF_BEG(buf_));
1233 Ferase_buffer(buffer);
1238 start = XSTRING_DATA(tem);
1239 length = XSTRING_LENGTH(tem);
1242 new = (Bufbyte *)xrealloc(buf, bsize);
1245 memcpy(bufp, start, length);
1248 /* Reset STRDATA in case gc relocated it. */
1249 strdata = XSTRING_DATA(string);
1256 /* don't bother if nothing substituted */
1257 tem = make_string(buf, bufp - buf);
1266 /************************************************************************/
1267 /* initialization */
1268 /************************************************************************/
1270 void syms_of_doc(void)
1272 DEFSUBR(Fdocumentation);
1273 DEFSUBR(Fdocumentation_property);
1274 DEFSUBR(Fsnarf_documentation);
1275 DEFSUBR(Fverify_documentation);
1276 DEFSUBR(Fsubstitute_command_keys);
1277 DEFSUBR(Fbuilt_in_symbol_file);
1279 DEFSYMBOL (Qdefvar);
1282 void vars_of_doc(void)
1284 DEFVAR_LISP("internal-doc-file-name", &Vinternal_doc_file_name /*
1285 Name of file containing documentation strings of built-in symbols.
1287 Vinternal_doc_file_name = Qnil;
1289 /* We don't really want this accessible from lisp... */
1290 Vinternal_doc_fd = make_int(-2);
1292 QSsubstitute = build_string(" *substitute*");
1293 staticpro(&QSsubstitute);