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 * 32 + 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;
711 CHECK_STRING(Vdoc_directory);
712 name = (char *)alloca(alloca_sz);
713 snprintf(name, alloca_sz, "%s%s",
714 (char*)XSTRING_DATA(Vdoc_directory),
715 (char*)XSTRING_DATA(filename))
717 #endif /* CANNOT_DUMP */
719 int alloca_sz = 2 + XSTRING_LENGTH(filename) + 3 + 9 + 1;
720 name = (char *)alloca(alloca_sz);
721 snprintf(name, alloca_sz, "./%s",
722 (char*)XSTRING_DATA(filename));
725 fd = open(name, O_RDONLY | OPEN_BINARY, 0);
727 report_file_error("Opening doc string file",
728 Fcons(build_string(name), Qnil));
729 Vinternal_doc_file_name = filename;
735 read(fd, &buf[filled], sizeof buf - 1 - filled);
741 end = buf + (filled < 512 ? filled : filled - 128);
742 while (p != end && *p != '\037')
744 /* p points to ^_Ffunctionname\n or ^_Vvarname\n. */
746 end = strchr(p, '\n');
748 oblookup(Vobarray, (Bufbyte *) p + 2, end - p - 2);
751 make_int(pos + end + 1 - buf);
752 /* Attach a docstring to a variable */
754 /* Install file-position as variable-documentation property
755 and make it negative for a user-variable
756 (doc starts with a `*'). */
758 Fget(sym, Qvariable_documentation,
762 GETTEXT("duplicate"),
765 /* In the case of duplicate doc file entries, always
766 take the later one. But if the doc is not an int
767 (a string, say) leave it alone. */
771 Fput(sym, Qvariable_documentation,
773 ? make_int(-XINT(offset))
776 /* Attach a docstring to a function.
777 The type determines where the docstring is stored. */
778 else if (p[1] == 'F') {
779 fun = indirect_function(sym, 0);
781 if (CONSP(fun) && EQ(XCAR(fun), Qmacro))
785 /* May have been #if'ed out or something */
792 } else if (SUBRP(fun)) {
793 /* Lisp_Subrs have a slot for it. */
794 if (XSUBR(fun)->doc) {
804 (char *)(-XINT(offset));
805 } else if (CONSP(fun)) {
806 /* If it's a lisp form, stick it in the form. */
809 || EQ(tem, Qautoload)) {
810 tem = Fcdr(Fcdr(fun));
830 /* In the case of duplicate doc file entries,
831 always take the later one. But if the doc
832 is not an int (a string, say) leave it
839 } else if (!CONSP(tem)) {
848 /* DOC string is a string not integer 0 */
852 ("!INTP(XCAR(tem))"),
862 ("not lambda or autoload"),
868 } else if (COMPILED_FUNCTIONP(fun)) {
869 /* Compiled-Function objects sometimes have
871 Lisp_Compiled_Function *f =
872 XCOMPILED_FUNCTION(fun);
874 /* This compiled-function object must have a
875 slot for the docstring, since we've found a
876 docstring for it. Unless there were multiple
877 definitions of it, and the latter one didn't
878 have any doc, which is a legal if slightly
879 bogus situation, so don't blow up. */
881 if (!(f->flags.documentationp)) {
891 compiled_function_documentation
900 /* In the case of duplicate doc file entries,
901 always take the later one. But if the doc is
902 not an int (a string, say) leave it alone. */
906 set_compiled_function_documentation
910 /* Otherwise the function is undefined or
911 otherwise weird. Ignore it. */
921 error("DOC file invalid at position %d",
931 memmove(buf, end, filled);
937 #if 1 /* Don't warn about functions whose doc was lost because they were
938 wrapped by advice-freeze.el... */
939 static int kludgily_ignore_lost_doc_p(Lisp_Object sym)
941 # define kludge_prefix "ad-Orig-"
942 Lisp_String *name = XSYMBOL(sym)->name;
943 return (string_length(name) > (Bytecount) (sizeof(kludge_prefix)) &&
944 !strncmp((char *)string_data(name), kludge_prefix,
945 sizeof(kludge_prefix) - 1));
946 # undef kludge_prefix
949 # define kludgily_ignore_lost_doc_p(sym) 0
952 static int verify_doc_mapper(Lisp_Object sym, void *arg)
954 Lisp_Object closure = *(Lisp_Object *) arg;
956 if (!NILP(Ffboundp(sym))) {
958 Lisp_Object fun = XSYMBOL(sym)->function;
959 if (CONSP(fun) && EQ(XCAR(fun), Qmacro))
963 doc = (EMACS_INT) XSUBR(fun)->doc;
964 else if (SYMBOLP(fun))
966 else if (KEYMAPP(fun))
968 else if (CONSP(fun)) {
969 Lisp_Object tem = XCAR(fun);
970 if (EQ(tem, Qlambda) || EQ(tem, Qautoload)) {
972 tem = Fcdr(Fcdr(fun));
973 if (CONSP(tem) && INTP(XCAR(tem)))
974 doc = XINT(XCAR(tem));
976 } else if (COMPILED_FUNCTIONP(fun)) {
977 Lisp_Compiled_Function *f = XCOMPILED_FUNCTION(fun);
978 if (!(f->flags.documentationp))
982 compiled_function_documentation(f);
988 if (doc == 0 && !kludgily_ignore_lost_doc_p(sym)) {
989 message("Warning: doc lost for function %s.",
990 string_data(XSYMBOL(sym)->name));
994 if (!NILP(Fboundp(sym))) {
995 Lisp_Object doc = Fget(sym, Qvariable_documentation, Qnil);
997 message("Warning: doc lost for variable %s.",
998 string_data(XSYMBOL(sym)->name));
1002 return 0; /* Never stop */
1005 DEFUN("Verify-documentation", Fverify_documentation, 0, 0, 0, /*
1006 Used to make sure everything went well with Snarf-documentation.
1007 Writes to stderr if not.
1011 Lisp_Object closure = Fcons(Qnil, Qnil);
1012 struct gcpro gcpro1;
1014 map_obarray(Vobarray, verify_doc_mapper, &closure);
1015 if (!NILP(Fcdr(closure)))
1017 "This is usually because some files were preloaded by loaddefs.el or\n"
1018 "site-load.el, but were not passed to make-docfile by Makefile.\n");
1020 return NILP(Fcdr(closure)) ? Qt : Qnil;
1023 DEFUN("substitute-command-keys", Fsubstitute_command_keys, 1, 1, 0, /*
1024 Substitute key descriptions for command names in STRING.
1025 Return a new string which is STRING with substrings of the form \\=\\[COMMAND]
1026 replaced by either: a keystroke sequence that will invoke COMMAND,
1027 or "M-x COMMAND" if COMMAND is not on any keys.
1028 Substrings of the form \\=\\{MAPVAR} are replaced by summaries
1029 \(made by `describe-bindings') of the value of MAPVAR, taken as a keymap.
1030 Substrings of the form \\=\\<MAPVAR> specify to use the value of MAPVAR
1031 as the keymap for future \\=\\[COMMAND] substrings.
1032 \\=\\= quotes the following character and is discarded;
1033 thus, \\=\\=\\=\\= puts \\=\\= into the output, and \\=\\=\\=\\[ puts \\=\\[ into the output.
1037 /* This function can GC */
1040 REGISTER Bufbyte *strdata;
1041 REGISTER Bufbyte *bufp;
1042 Bytecount strlength;
1046 Lisp_Object tem = Qnil;
1047 Lisp_Object keymap = Qnil;
1048 Lisp_Object name = Qnil;
1051 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
1056 CHECK_STRING(string);
1057 GCPRO4(string, tem, keymap, name);
1059 /* There is the possibility that the string is not destined for a
1060 translating stream, and it could be argued that we should do the
1061 same thing here as in Fformat(), but there are very few times
1062 when this will be the case and many calls to this function
1063 would have to have `gettext' calls added. (I18N3) */
1064 string = LISP_GETTEXT(string);
1066 /* KEYMAP is either nil (which means search all the active keymaps)
1067 or a specified local map (which means search just that and the
1068 global map). If non-nil, it might come from Voverriding_local_map,
1069 or from a \\<mapname> construct in STRING itself.. */
1071 /* This is really weird and garbagey. If keymap is nil and there's
1072 an overriding-local-map, `where-is-internal' will correctly note
1073 this, so there's no reason to do it here. Maybe FSFmacs
1074 `where-is-internal' is broken. */
1076 keymap = current_kboard->Voverriding_terminal_local_map;
1078 keymap = Voverriding_local_map;
1082 strlength = XSTRING_LENGTH(string);
1083 bsize = 1 + strlength;
1084 buf = (Bufbyte*)xmalloc_atomic(bsize);
1087 /* Have to reset strdata every time GC might be called */
1088 strdata = XSTRING_DATA(string);
1089 for (idx = 0; idx < strlength;) {
1090 Bufbyte *strp = strdata + idx;
1092 if (strp[0] != '\\') {
1093 /* just copy other chars */
1094 /* As it happens, this will work with Mule even if the
1095 character quoted is multi-byte; the remaining multi-byte
1096 characters will just be copied by this loop. */
1102 /* just copy unknown escape sequences */
1108 /* \= quotes the next character; thus, to put in
1109 \[ without its special meaning, use \=\[. */
1110 /* As it happens, this will work with Mule even
1111 if the character quoted is multi-byte; the
1112 remaining multi-byte characters will just be
1113 copied by this loop. */
1121 idx += 2; /* skip \[ */
1125 while ((idx < strlength)
1130 length = strp - start;
1133 tem = Fintern(make_string(start, length), Qnil);
1134 tem = Fwhere_is_internal(
1135 tem, keymap, Qt, Qnil, Qnil);
1138 /* Disregard menu bar bindings; it is
1139 positively annoying to mention them
1140 when there's no menu bar, and it
1141 isn't terribly useful even when there
1144 firstkey = Faref(tem, Qzero);
1145 if (EQ(firstkey, Qmenu_bar))
1151 /* but not on any keys */
1152 new = xrealloc(buf, bsize += 4);
1155 memcpy(bufp, "M-x ", 4);
1158 } else { /* function is on a key */
1159 tem = Fkey_description(tem);
1165 Lisp_Object buffer =
1166 Fget_buffer_create(QSsubstitute);
1167 struct buffer *buf_ = XBUFFER(buffer);
1169 Fbuffer_disable_undo(buffer);
1170 Ferase_buffer(buffer);
1172 /* \{foo} is replaced with a summary of keymap
1173 (symbol-value foo). \<foo> just sets the
1174 keymap used for \[cmd]. */
1176 idx += 2; /* skip \{ or \< */
1180 while ((idx < strlength)
1181 && *strp != '}' && *strp != '>') {
1185 length = strp - start;
1186 idx++; /* skip } or > */
1188 /* Get the value of the keymap in TEM,
1189 or nil if undefined. Do this while
1190 still in the user's current buffer in
1191 case it is a local variable. */
1193 make_string(start, length), Qnil);
1194 tem = Fboundp(name);
1196 tem = Fsymbol_value(name);
1198 tem = get_keymap(tem, 0, 1);
1203 buffer_insert_c_string(
1204 buf_, "(uses keymap \"");
1205 buffer_insert_lisp_string(
1206 buf_, Fsymbol_name(name));
1207 buffer_insert_c_string(
1208 buf_, "\", which is not "
1209 "currently defined) ");
1211 if (start[-1] == '<') {
1214 } else if (start[-1] == '<') {
1218 tem, 1, Qnil, Qnil, 0, buffer);
1220 tem = make_string_from_buffer(
1221 buf_, BUF_BEG(buf_),
1222 BUF_Z(buf_) - BUF_BEG(buf_));
1223 Ferase_buffer(buffer);
1228 start = XSTRING_DATA(tem);
1229 length = XSTRING_LENGTH(tem);
1232 new = (Bufbyte *)xrealloc(buf, bsize);
1235 memcpy(bufp, start, length);
1238 /* Reset STRDATA in case gc relocated it. */
1239 strdata = XSTRING_DATA(string);
1246 /* don't bother if nothing substituted */
1247 tem = make_string(buf, bufp - buf);
1256 /************************************************************************/
1257 /* initialization */
1258 /************************************************************************/
1260 void syms_of_doc(void)
1262 DEFSUBR(Fdocumentation);
1263 DEFSUBR(Fdocumentation_property);
1264 DEFSUBR(Fsnarf_documentation);
1265 DEFSUBR(Fverify_documentation);
1266 DEFSUBR(Fsubstitute_command_keys);
1267 DEFSUBR(Fbuilt_in_symbol_file);
1269 DEFSYMBOL (Qdefvar);
1272 void vars_of_doc(void)
1274 DEFVAR_LISP("internal-doc-file-name", &Vinternal_doc_file_name /*
1275 Name of file containing documentation strings of built-in symbols.
1277 Vinternal_doc_file_name = Qnil;
1279 /* We don't really want this accessible from lisp... */
1280 Vinternal_doc_fd = make_int(-2);
1282 QSsubstitute = build_string(" *substitute*");
1283 staticpro(&QSsubstitute);