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 oblookup(Vobarray, (Bufbyte *) p + 2, end - p - 2);
755 make_int(pos + end + 1 - buf);
756 /* Attach a docstring to a variable */
758 /* Install file-position as variable-documentation property
759 and make it negative for a user-variable
760 (doc starts with a `*'). */
762 Fget(sym, Qvariable_documentation,
766 GETTEXT("duplicate"),
769 /* In the case of duplicate doc file entries, always
770 take the later one. But if the doc is not an int
771 (a string, say) leave it alone. */
775 Fput(sym, Qvariable_documentation,
777 ? make_int(-XINT(offset))
780 /* Attach a docstring to a function.
781 The type determines where the docstring is stored. */
782 else if (p[1] == 'F') {
783 fun = indirect_function(sym, 0);
785 if (CONSP(fun) && EQ(XCAR(fun), Qmacro))
789 /* May have been #if'ed out or something */
796 } else if (SUBRP(fun)) {
797 /* Lisp_Subrs have a slot for it. */
798 if (XSUBR(fun)->doc) {
808 (char *)(-XINT(offset));
809 } else if (CONSP(fun)) {
810 /* If it's a lisp form, stick it in the form. */
813 || EQ(tem, Qautoload)) {
814 tem = Fcdr(Fcdr(fun));
834 /* In the case of duplicate doc file entries,
835 always take the later one. But if the doc
836 is not an int (a string, say) leave it
843 } else if (!CONSP(tem)) {
852 /* DOC string is a string not integer 0 */
856 ("!INTP(XCAR(tem))"),
866 ("not lambda or autoload"),
872 } else if (COMPILED_FUNCTIONP(fun)) {
873 /* Compiled-Function objects sometimes have
875 Lisp_Compiled_Function *f =
876 XCOMPILED_FUNCTION(fun);
878 /* This compiled-function object must have a
879 slot for the docstring, since we've found a
880 docstring for it. Unless there were multiple
881 definitions of it, and the latter one didn't
882 have any doc, which is a legal if slightly
883 bogus situation, so don't blow up. */
885 if (!(f->flags.documentationp)) {
895 compiled_function_documentation
904 /* In the case of duplicate doc file entries,
905 always take the later one. But if the doc is
906 not an int (a string, say) leave it alone. */
910 set_compiled_function_documentation
914 /* Otherwise the function is undefined or
915 otherwise weird. Ignore it. */
925 error("DOC file invalid at position %d",
935 memmove(buf, end, filled);
941 #if 1 /* Don't warn about functions whose doc was lost because they were
942 wrapped by advice-freeze.el... */
943 static int kludgily_ignore_lost_doc_p(Lisp_Object sym)
945 # define kludge_prefix "ad-Orig-"
946 Lisp_String *name = XSYMBOL(sym)->name;
947 return (string_length(name) > (Bytecount) (sizeof(kludge_prefix)) &&
948 !strncmp((char *)string_data(name), kludge_prefix,
949 sizeof(kludge_prefix) - 1));
950 # undef kludge_prefix
953 # define kludgily_ignore_lost_doc_p(sym) 0
956 static int verify_doc_mapper(Lisp_Object sym, void *arg)
958 Lisp_Object closure = *(Lisp_Object *) arg;
960 if (!NILP(Ffboundp(sym))) {
962 Lisp_Object fun = XSYMBOL(sym)->function;
963 if (CONSP(fun) && EQ(XCAR(fun), Qmacro))
967 doc = (EMACS_INT) XSUBR(fun)->doc;
968 else if (SYMBOLP(fun))
970 else if (KEYMAPP(fun))
972 else if (CONSP(fun)) {
973 Lisp_Object tem = XCAR(fun);
974 if (EQ(tem, Qlambda) || EQ(tem, Qautoload)) {
976 tem = Fcdr(Fcdr(fun));
977 if (CONSP(tem) && INTP(XCAR(tem)))
978 doc = XINT(XCAR(tem));
980 } else if (COMPILED_FUNCTIONP(fun)) {
981 Lisp_Compiled_Function *f = XCOMPILED_FUNCTION(fun);
982 if (!(f->flags.documentationp))
986 compiled_function_documentation(f);
992 if (doc == 0 && !kludgily_ignore_lost_doc_p(sym)) {
993 message("Warning: doc lost for function %s.",
994 string_data(XSYMBOL(sym)->name));
998 if (!NILP(Fboundp(sym))) {
999 Lisp_Object doc = Fget(sym, Qvariable_documentation, Qnil);
1001 message("Warning: doc lost for variable %s.",
1002 string_data(XSYMBOL(sym)->name));
1006 return 0; /* Never stop */
1009 DEFUN("Verify-documentation", Fverify_documentation, 0, 0, 0, /*
1010 Used to make sure everything went well with Snarf-documentation.
1011 Writes to stderr if not.
1015 Lisp_Object closure = Fcons(Qnil, Qnil);
1016 struct gcpro gcpro1;
1018 map_obarray(Vobarray, verify_doc_mapper, &closure);
1019 if (!NILP(Fcdr(closure)))
1021 "This is usually because some files were preloaded by loaddefs.el or\n"
1022 "site-load.el, but were not passed to make-docfile by Makefile.\n");
1024 return NILP(Fcdr(closure)) ? Qt : Qnil;
1027 DEFUN("substitute-command-keys", Fsubstitute_command_keys, 1, 1, 0, /*
1028 Substitute key descriptions for command names in STRING.
1029 Return a new string which is STRING with substrings of the form \\=\\[COMMAND]
1030 replaced by either: a keystroke sequence that will invoke COMMAND,
1031 or "M-x COMMAND" if COMMAND is not on any keys.
1032 Substrings of the form \\=\\{MAPVAR} are replaced by summaries
1033 \(made by `describe-bindings') of the value of MAPVAR, taken as a keymap.
1034 Substrings of the form \\=\\<MAPVAR> specify to use the value of MAPVAR
1035 as the keymap for future \\=\\[COMMAND] substrings.
1036 \\=\\= quotes the following character and is discarded;
1037 thus, \\=\\=\\=\\= puts \\=\\= into the output, and \\=\\=\\=\\[ puts \\=\\[ into the output.
1041 /* This function can GC */
1044 REGISTER Bufbyte *strdata;
1045 REGISTER Bufbyte *bufp;
1046 Bytecount strlength;
1050 Lisp_Object tem = Qnil;
1051 Lisp_Object keymap = Qnil;
1052 Lisp_Object name = Qnil;
1055 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
1060 CHECK_STRING(string);
1061 GCPRO4(string, tem, keymap, name);
1063 /* There is the possibility that the string is not destined for a
1064 translating stream, and it could be argued that we should do the
1065 same thing here as in Fformat(), but there are very few times
1066 when this will be the case and many calls to this function
1067 would have to have `gettext' calls added. (I18N3) */
1068 string = LISP_GETTEXT(string);
1070 /* KEYMAP is either nil (which means search all the active keymaps)
1071 or a specified local map (which means search just that and the
1072 global map). If non-nil, it might come from Voverriding_local_map,
1073 or from a \\<mapname> construct in STRING itself.. */
1075 /* This is really weird and garbagey. If keymap is nil and there's
1076 an overriding-local-map, `where-is-internal' will correctly note
1077 this, so there's no reason to do it here. Maybe FSFmacs
1078 `where-is-internal' is broken. */
1080 keymap = current_kboard->Voverriding_terminal_local_map;
1082 keymap = Voverriding_local_map;
1086 strlength = XSTRING_LENGTH(string);
1087 bsize = 1 + strlength;
1088 buf = (Bufbyte*)xmalloc_atomic(bsize);
1091 /* Have to reset strdata every time GC might be called */
1092 strdata = XSTRING_DATA(string);
1093 for (idx = 0; idx < strlength;) {
1094 Bufbyte *strp = strdata + idx;
1096 if (strp[0] != '\\') {
1097 /* just copy other chars */
1098 /* As it happens, this will work with Mule even if the
1099 character quoted is multi-byte; the remaining multi-byte
1100 characters will just be copied by this loop. */
1106 /* just copy unknown escape sequences */
1112 /* \= quotes the next character; thus, to put in
1113 \[ without its special meaning, use \=\[. */
1114 /* As it happens, this will work with Mule even
1115 if the character quoted is multi-byte; the
1116 remaining multi-byte characters will just be
1117 copied by this loop. */
1125 idx += 2; /* skip \[ */
1129 while ((idx < strlength)
1134 length = strp - start;
1137 tem = Fintern(make_string(start, length), Qnil);
1138 tem = Fwhere_is_internal(
1139 tem, keymap, Qt, Qnil, Qnil);
1142 /* Disregard menu bar bindings; it is
1143 positively annoying to mention them
1144 when there's no menu bar, and it
1145 isn't terribly useful even when there
1148 firstkey = Faref(tem, Qzero);
1149 if (EQ(firstkey, Qmenu_bar))
1155 /* but not on any keys */
1156 new = xrealloc(buf, bsize += 4);
1159 memcpy(bufp, "M-x ", 4);
1162 } else { /* function is on a key */
1163 tem = Fkey_description(tem);
1169 Lisp_Object buffer =
1170 Fget_buffer_create(QSsubstitute);
1171 struct buffer *buf_ = XBUFFER(buffer);
1173 Fbuffer_disable_undo(buffer);
1174 Ferase_buffer(buffer);
1176 /* \{foo} is replaced with a summary of keymap
1177 (symbol-value foo). \<foo> just sets the
1178 keymap used for \[cmd]. */
1180 idx += 2; /* skip \{ or \< */
1184 while ((idx < strlength)
1185 && *strp != '}' && *strp != '>') {
1189 length = strp - start;
1190 idx++; /* skip } or > */
1192 /* Get the value of the keymap in TEM,
1193 or nil if undefined. Do this while
1194 still in the user's current buffer in
1195 case it is a local variable. */
1197 make_string(start, length), Qnil);
1198 tem = Fboundp(name);
1200 tem = Fsymbol_value(name);
1202 tem = get_keymap(tem, 0, 1);
1207 buffer_insert_c_string(
1208 buf_, "(uses keymap \"");
1209 buffer_insert_lisp_string(
1210 buf_, Fsymbol_name(name));
1211 buffer_insert_c_string(
1212 buf_, "\", which is not "
1213 "currently defined) ");
1215 if (start[-1] == '<') {
1218 } else if (start[-1] == '<') {
1222 tem, 1, Qnil, Qnil, 0, buffer);
1224 tem = make_string_from_buffer(
1225 buf_, BUF_BEG(buf_),
1226 BUF_Z(buf_) - BUF_BEG(buf_));
1227 Ferase_buffer(buffer);
1232 start = XSTRING_DATA(tem);
1233 length = XSTRING_LENGTH(tem);
1236 new = (Bufbyte *)xrealloc(buf, bsize);
1239 memcpy(bufp, start, length);
1242 /* Reset STRDATA in case gc relocated it. */
1243 strdata = XSTRING_DATA(string);
1250 /* don't bother if nothing substituted */
1251 tem = make_string(buf, bufp - buf);
1260 /************************************************************************/
1261 /* initialization */
1262 /************************************************************************/
1264 void syms_of_doc(void)
1266 DEFSUBR(Fdocumentation);
1267 DEFSUBR(Fdocumentation_property);
1268 DEFSUBR(Fsnarf_documentation);
1269 DEFSUBR(Fverify_documentation);
1270 DEFSUBR(Fsubstitute_command_keys);
1271 DEFSUBR(Fbuilt_in_symbol_file);
1273 DEFSYMBOL (Qdefvar);
1276 void vars_of_doc(void)
1278 DEFVAR_LISP("internal-doc-file-name", &Vinternal_doc_file_name /*
1279 Name of file containing documentation strings of built-in symbols.
1281 Vinternal_doc_file_name = Qnil;
1283 /* We don't really want this accessible from lisp... */
1284 Vinternal_doc_fd = make_int(-2);
1286 QSsubstitute = build_string(" *substitute*");
1287 staticpro(&QSsubstitute);