use guile conses
[bpt/emacs.git] / src / doc.c
CommitLineData
c6045832 1/* Record indices of function doc strings stored in a file.
05920a43 2
2241d76e 3Copyright (C) 1985-1986, 1993-1995, 1997-2014 Free Software Foundation, Inc.
c6045832
JB
4
5This file is part of GNU Emacs.
6
9ec0b715 7GNU Emacs is free software: you can redistribute it and/or modify
c6045832 8it under the terms of the GNU General Public License as published by
9ec0b715
GM
9the Free Software Foundation, either version 3 of the License, or
10(at your option) any later version.
c6045832
JB
11
12GNU Emacs is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
9ec0b715 18along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
c6045832
JB
19
20
18160b98 21#include <config.h>
c6045832 22
b648c163 23#include <errno.h>
c6045832 24#include <sys/types.h>
57618ecf 25#include <sys/file.h> /* Must be after sys/types.h for USG. */
c6045832 26#include <fcntl.h>
29beb080 27#include <unistd.h>
29beb080 28
620f13b0
PE
29#include <c-ctype.h>
30
c6045832 31#include "lisp.h"
e5560ff7 32#include "character.h"
c6045832 33#include "buffer.h"
665d3046 34#include "keyboard.h"
8feddab4 35#include "keymap.h"
c6045832 36
9191c8ae
GM
37Lisp_Object Qfunction_documentation;
38
912e8480
RS
39/* Buffer used for reading from documentation file. */
40static char *get_doc_string_buffer;
3d0c92a2 41static ptrdiff_t get_doc_string_buffer_size;
912e8480 42
32caae30
RS
43static unsigned char *read_bytecode_pointer;
44
57618ecf 45/* `readchar' in lread.c calls back here to fetch the next byte.
32caae30
RS
46 If UNREADFLAG is 1, we unread a byte. */
47
48int
a08d4ba7 49read_bytecode_char (bool unreadflag)
32caae30
RS
50{
51 if (unreadflag)
52 {
53 read_bytecode_pointer--;
54 return 0;
55 }
56 return *read_bytecode_pointer++;
57}
58
700ea809 59/* Extract a doc string from a file. FILEPOS says where to get it.
6e911150 60 If it is an integer, use that position in the standard DOC file.
700ea809 61 If it is (FILE . INTEGER), use FILE as the file name
0c00bc70
RS
62 and INTEGER as the position in that file.
63 But if INTEGER is negative, make it positive.
64 (A negative integer is used for user variables, so we can distinguish
ba29c3c9
RS
65 them without actually fetching the doc string.)
66
a154a4ef
SM
67 If the location does not point to the beginning of a docstring
68 (e.g. because the file has been modified and the location is stale),
69 return nil.
70
a08d4ba7 71 If UNIBYTE, always make a unibyte string.
e96179b3 72
a08d4ba7 73 If DEFINITION, assume this is for reading
f1df0d67
RS
74 a dynamic function definition; convert the bytestring
75 and the constants vector with appropriate byte handling,
76 and return a cons cell. */
700ea809 77
0c3debbc 78Lisp_Object
a08d4ba7 79get_doc_string (Lisp_Object filepos, bool unibyte, bool definition)
778d47c7 80{
a08d4ba7
PE
81 char *from, *to, *name, *p, *p1;
82 int fd;
d311d28c
PE
83 ptrdiff_t minsize;
84 int offset;
85 EMACS_INT position;
71376d4b 86 Lisp_Object file, tem, pos;
a8cd4836 87 ptrdiff_t count;
d311d28c 88 USE_SAFE_ALLOCA;
778d47c7 89
700ea809
RS
90 if (INTEGERP (filepos))
91 {
92 file = Vdoc_file_name;
71376d4b 93 pos = filepos;
700ea809
RS
94 }
95 else if (CONSP (filepos))
96 {
03699b14 97 file = XCAR (filepos);
71376d4b 98 pos = XCDR (filepos);
700ea809
RS
99 }
100 else
778d47c7
RS
101 return Qnil;
102
71376d4b 103 position = eabs (XINT (pos));
87afdd65 104
700ea809
RS
105 if (!STRINGP (Vdoc_directory))
106 return Qnil;
107
108 if (!STRINGP (file))
109 return Qnil;
177c0ea7 110
700ea809
RS
111 /* Put the file name in NAME as a C string.
112 If it is relative, combine it with Vdoc_directory. */
113
114 tem = Ffile_name_absolute_p (file);
8fe012c4 115 file = ENCODE_FILE (file);
700ea809
RS
116 if (NILP (tem))
117 {
8fe012c4
SM
118 Lisp_Object docdir = ENCODE_FILE (Vdoc_directory);
119 minsize = SCHARS (docdir);
700ea809
RS
120 /* sizeof ("../etc/") == 8 */
121 if (minsize < 8)
122 minsize = 8;
98c6f1e3 123 name = SAFE_ALLOCA (minsize + SCHARS (file) + 8);
8fe012c4 124 strcpy (name, SSDATA (docdir));
42a5b22f 125 strcat (name, SSDATA (file));
700ea809
RS
126 }
127 else
128 {
51b59d79 129 name = SSDATA (file);
700ea809 130 }
c6045832 131
68c45bf0 132 fd = emacs_open (name, O_RDONLY, 0);
c6045832 133 if (fd < 0)
778d47c7
RS
134 {
135#ifndef CANNOT_DUMP
136 if (!NILP (Vpurify_flag))
137 {
138 /* Preparing to dump; DOC file is probably not installed.
8fe012c4 139 So check in ../etc. */
778d47c7 140 strcpy (name, "../etc/");
42a5b22f 141 strcat (name, SSDATA (file));
778d47c7 142
68c45bf0 143 fd = emacs_open (name, O_RDONLY, 0);
778d47c7
RS
144 }
145#endif
778d47c7 146 if (fd < 0)
a8cd4836
PE
147 {
148 SAFE_FREE ();
149 return concat3 (build_string ("Cannot open doc string file \""),
150 file, build_string ("\"\n"));
151 }
778d47c7 152 }
a8cd4836
PE
153 count = SPECPDL_INDEX ();
154 record_unwind_protect_int (close_file_unwind, fd);
778d47c7 155
0fded513 156 /* Seek only to beginning of disk block. */
a154a4ef
SM
157 /* Make sure we read at least 1024 bytes before `position'
158 so we can check the leading text for consistency. */
159 offset = min (position, max (1024, position % (8 * 1024)));
d311d28c
PE
160 if (TYPE_MAXIMUM (off_t) < position
161 || lseek (fd, position - offset, 0) < 0)
a8cd4836
PE
162 error ("Position %"pI"d out of range in doc string file \"%s\"",
163 position, name);
d311d28c 164
912e8480
RS
165 /* Read the doc string into get_doc_string_buffer.
166 P points beyond the data just read. */
0fded513 167
912e8480 168 p = get_doc_string_buffer;
700ea809 169 while (1)
c6045832 170 {
d31850da 171 ptrdiff_t space_left = (get_doc_string_buffer_size - 1
84c9ce05 172 - (p - get_doc_string_buffer));
700ea809
RS
173 int nread;
174
0fded513 175 /* Allocate or grow the buffer if we need to. */
d31850da 176 if (space_left <= 0)
700ea809 177 {
3d0c92a2 178 ptrdiff_t in_buffer = p - get_doc_string_buffer;
75a65c7e
SM
179 get_doc_string_buffer
180 = xpalloc (get_doc_string_buffer, &get_doc_string_buffer_size,
181 16 * 1024, -1, 1);
912e8480 182 p = get_doc_string_buffer + in_buffer;
d31850da 183 space_left = (get_doc_string_buffer_size - 1
912e8480 184 - (p - get_doc_string_buffer));
700ea809
RS
185 }
186
0fded513
RS
187 /* Read a disk block at a time.
188 If we read the same block last time, maybe skip this? */
700ea809
RS
189 if (space_left > 1024 * 8)
190 space_left = 1024 * 8;
68c45bf0 191 nread = emacs_read (fd, p, space_left);
700ea809 192 if (nread < 0)
a8cd4836 193 report_file_error ("Read error on documentation file", file);
700ea809
RS
194 p[nread] = 0;
195 if (!nread)
c6045832 196 break;
912e8480 197 if (p == get_doc_string_buffer)
8966b757 198 p1 = strchr (p + offset, '\037');
0fded513 199 else
8966b757 200 p1 = strchr (p, '\037');
c6045832
JB
201 if (p1)
202 {
203 *p1 = 0;
204 p = p1;
205 break;
206 }
700ea809 207 p += nread;
c6045832 208 }
a8cd4836
PE
209 unbind_to (count, Qnil);
210 SAFE_FREE ();
700ea809 211
a154a4ef
SM
212 /* Sanity checking. */
213 if (CONSP (filepos))
214 {
215 int test = 1;
759fd763
SM
216 /* A dynamic docstring should be either at the very beginning of a "#@
217 comment" or right after a dynamic docstring delimiter (in case we
218 pack several such docstrings within the same comment). */
219 if (get_doc_string_buffer[offset - test] != '\037')
220 {
221 if (get_doc_string_buffer[offset - test++] != ' ')
222 return Qnil;
223 while (get_doc_string_buffer[offset - test] >= '0'
224 && get_doc_string_buffer[offset - test] <= '9')
225 test++;
226 if (get_doc_string_buffer[offset - test++] != '@'
227 || get_doc_string_buffer[offset - test] != '#')
228 return Qnil;
229 }
a154a4ef
SM
230 }
231 else
232 {
233 int test = 1;
234 if (get_doc_string_buffer[offset - test++] != '\n')
235 return Qnil;
236 while (get_doc_string_buffer[offset - test] > ' ')
237 test++;
238 if (get_doc_string_buffer[offset - test] != '\037')
239 return Qnil;
240 }
241
700ea809
RS
242 /* Scan the text and perform quoting with ^A (char code 1).
243 ^A^A becomes ^A, ^A0 becomes a null char, and ^A_ becomes a ^_. */
912e8480
RS
244 from = get_doc_string_buffer + offset;
245 to = get_doc_string_buffer + offset;
700ea809
RS
246 while (from != p)
247 {
248 if (*from == 1)
249 {
250 int c;
251
252 from++;
253 c = *from++;
254 if (c == 1)
255 *to++ = c;
256 else if (c == '0')
257 *to++ = 0;
258 else if (c == '_')
259 *to++ = 037;
260 else
684a03ef
PE
261 {
262 unsigned char uc = c;
263 error ("\
762b15be 264Invalid data in documentation file -- %c followed by code %03o",
684a03ef
PE
265 1, uc);
266 }
700ea809
RS
267 }
268 else
269 *to++ = *from++;
270 }
271
32caae30
RS
272 /* If DEFINITION, read from this buffer
273 the same way we would read bytes from a file. */
f1df0d67
RS
274 if (definition)
275 {
9eee99eb 276 read_bytecode_pointer = (unsigned char *) get_doc_string_buffer + offset;
32caae30 277 return Fread (Qlambda);
f1df0d67
RS
278 }
279
e96179b3
RS
280 if (unibyte)
281 return make_unibyte_string (get_doc_string_buffer + offset,
282 to - (get_doc_string_buffer + offset));
283 else
fb2fdea7 284 {
198a7a97 285 /* The data determines whether the string is multibyte. */
75a65c7e
SM
286 ptrdiff_t nchars
287 = multibyte_chars_in_text (((unsigned char *) get_doc_string_buffer
288 + offset),
289 to - (get_doc_string_buffer + offset));
fb2fdea7
RS
290 return make_string_from_bytes (get_doc_string_buffer + offset,
291 nchars,
292 to - (get_doc_string_buffer + offset));
293 }
700ea809
RS
294}
295
296/* Get a string from position FILEPOS and pass it through the Lisp reader.
297 We use this for fetching the bytecode string and constants vector
298 of a compiled function from the .elc file. */
299
300Lisp_Object
971de7fb 301read_doc_string (Lisp_Object filepos)
700ea809 302{
e96179b3 303 return get_doc_string (filepos, 0, 1);
c6045832
JB
304}
305
a08d4ba7 306static bool
971de7fb 307reread_doc_file (Lisp_Object file)
a154a4ef 308{
13d7dc77 309#if 0
a154a4ef
SM
310 Lisp_Object reply, prompt[3];
311 struct gcpro gcpro1;
312 GCPRO1 (file);
313 prompt[0] = build_string ("File ");
314 prompt[1] = NILP (file) ? Vdoc_file_name : file;
13d7dc77 315 prompt[2] = build_string (" is out of sync. Reload? ");
a154a4ef
SM
316 reply = Fy_or_n_p (Fconcat (3, prompt));
317 UNGCPRO;
318 if (NILP (reply))
e5aa79fa 319 return 0;
13d7dc77 320#endif
a154a4ef
SM
321
322 if (NILP (file))
323 Fsnarf_documentation (Vdoc_file_name);
324 else
325 Fload (file, Qt, Qt, Qt, Qnil);
e5aa79fa
SM
326
327 return 1;
a154a4ef
SM
328}
329
ee04dc54 330DEFUN ("documentation", Fdocumentation, Sdocumentation, 1, 2, 0,
335c5470
PJ
331 doc: /* Return the documentation string of FUNCTION.
332Unless a non-nil second argument RAW is given, the
333string is passed through `substitute-command-keys'. */)
5842a27b 334 (Lisp_Object function, Lisp_Object raw)
c6045832
JB
335{
336 Lisp_Object fun;
337 Lisp_Object funcar;
a415e694 338 Lisp_Object doc;
a08d4ba7 339 bool try_reload = 1;
e5aa79fa
SM
340
341 documentation:
c6045832 342
8d17fe0b 343 doc = Qnil;
177c0ea7 344
f8aff4c6
JB
345 if (SYMBOLP (function))
346 {
347 Lisp_Object tem = Fget (function, Qfunction_documentation);
348 if (!NILP (tem))
349 return Fdocumentation_property (function, Qfunction_documentation,
350 raw);
351 }
352
a7f96a35 353 fun = Findirect_function (function, Qnil);
57618ecf
SM
354 if (CONSP (fun) && EQ (XCAR (fun), Qmacro))
355 fun = XCDR (fun);
5b5f6883 356 if (SUBRP (fun))
c6045832 357 {
9191c8ae
GM
358 if (XSUBR (fun)->doc == 0)
359 return Qnil;
8f41de3a
PE
360 /* FIXME: This is not portable, as it assumes that string
361 pointers have the top bit clear. */
d01a7826 362 else if ((intptr_t) XSUBR (fun)->doc >= 0)
ee04dc54 363 doc = build_string (XSUBR (fun)->doc);
c6045832 364 else
d01a7826 365 doc = make_number ((intptr_t) XSUBR (fun)->doc);
5b5f6883
KH
366 }
367 else if (COMPILEDP (fun))
368 {
87afdd65 369 if ((ASIZE (fun) & PSEUDOVECTOR_SIZE_MASK) <= COMPILED_DOC_STRING)
c6045832 370 return Qnil;
ee04dc54 371 else
a415e694
PE
372 {
373 Lisp_Object tem = AREF (fun, COMPILED_DOC_STRING);
374 if (STRINGP (tem))
375 doc = tem;
376 else if (NATNUMP (tem) || CONSP (tem))
377 doc = tem;
378 else
379 return Qnil;
380 }
5b5f6883
KH
381 }
382 else if (STRINGP (fun) || VECTORP (fun))
383 {
c6045832 384 return build_string ("Keyboard macro.");
5b5f6883
KH
385 }
386 else if (CONSP (fun))
387 {
7d7bbefd 388 funcar = XCAR (fun);
e6d12642 389 if (!SYMBOLP (funcar))
2f0a47f9 390 xsignal1 (Qinvalid_function, fun);
502ddf23 391 else if (EQ (funcar, Qkeymap))
a3cec380 392 return build_string ("Prefix command (definition is a keymap associating keystrokes with commands).");
502ddf23 393 else if (EQ (funcar, Qlambda)
23aba0ea 394 || (EQ (funcar, Qclosure) && (fun = XCDR (fun), 1))
502ddf23 395 || EQ (funcar, Qautoload))
c6045832 396 {
a415e694
PE
397 Lisp_Object tem1 = Fcdr (Fcdr (fun));
398 Lisp_Object tem = Fcar (tem1);
e6d12642 399 if (STRINGP (tem))
ee04dc54 400 doc = tem;
ae44f7a4
RS
401 /* Handle a doc reference--but these never come last
402 in the function body, so reject them if they are last. */
87afdd65
SM
403 else if ((NATNUMP (tem) || (CONSP (tem) && INTEGERP (XCDR (tem))))
404 && !NILP (XCDR (tem1)))
405 doc = tem;
ee04dc54
RM
406 else
407 return Qnil;
c6045832 408 }
5b5f6883
KH
409 else
410 goto oops;
411 }
412 else
413 {
414 oops:
2f0a47f9 415 xsignal1 (Qinvalid_function, fun);
c6045832 416 }
ee04dc54 417
e5aa79fa
SM
418 /* If DOC is 0, it's typically because of a dumped file missing
419 from the DOC file (bug in src/Makefile.in). */
71cdb109
SM
420 if (EQ (doc, make_number (0)))
421 doc = Qnil;
68d8a8e1 422 if (INTEGERP (doc) || CONSP (doc))
a154a4ef
SM
423 {
424 Lisp_Object tem;
425 tem = get_doc_string (doc, 0, 0);
e5aa79fa 426 if (NILP (tem) && try_reload)
a154a4ef
SM
427 {
428 /* The file is newer, we need to reset the pointers. */
429 struct gcpro gcpro1, gcpro2;
430 GCPRO2 (function, raw);
e5aa79fa 431 try_reload = reread_doc_file (Fcar_safe (doc));
a154a4ef 432 UNGCPRO;
e5aa79fa
SM
433 if (try_reload)
434 {
435 try_reload = 0;
436 goto documentation;
437 }
a154a4ef
SM
438 }
439 else
440 doc = tem;
441 }
87afdd65 442
956ace37 443 if (NILP (raw))
441d75e5 444 doc = Fsubstitute_command_keys (doc);
ee04dc54 445 return doc;
c6045832
JB
446}
447
f6ee1260
GM
448DEFUN ("documentation-property", Fdocumentation_property,
449 Sdocumentation_property, 2, 3, 0,
335c5470
PJ
450 doc: /* Return the documentation string that is SYMBOL's PROP property.
451Third argument RAW omitted or nil means pass the result through
452`substitute-command-keys' if it is a string.
453
454This differs from `get' in that it can refer to strings stored in the
455`etc/DOC' file; and that it evaluates documentation properties that
456aren't strings. */)
5842a27b 457 (Lisp_Object symbol, Lisp_Object prop, Lisp_Object raw)
c6045832 458{
a08d4ba7 459 bool try_reload = 1;
2f0b74ea 460 Lisp_Object tem;
c6045832 461
e5aa79fa 462 documentation_property:
177c0ea7 463
4acb738e 464 tem = Fget (symbol, prop);
44766095 465 if (EQ (tem, make_number (0)))
71cdb109 466 tem = Qnil;
68d8a8e1 467 if (INTEGERP (tem) || (CONSP (tem) && INTEGERP (XCDR (tem))))
a154a4ef
SM
468 {
469 Lisp_Object doc = tem;
470 tem = get_doc_string (tem, 0, 0);
e5aa79fa 471 if (NILP (tem) && try_reload)
a154a4ef
SM
472 {
473 /* The file is newer, we need to reset the pointers. */
474 struct gcpro gcpro1, gcpro2, gcpro3;
475 GCPRO3 (symbol, prop, raw);
e5aa79fa 476 try_reload = reread_doc_file (Fcar_safe (doc));
a154a4ef 477 UNGCPRO;
e5aa79fa
SM
478 if (try_reload)
479 {
480 try_reload = 0;
481 goto documentation_property;
482 }
a154a4ef
SM
483 }
484 }
f6ee1260
GM
485 else if (!STRINGP (tem))
486 /* Feval protects its argument. */
a0ee6f27 487 tem = Feval (tem, Qnil);
177c0ea7 488
e6d12642 489 if (NILP (raw) && STRINGP (tem))
bbd7d5d3 490 tem = Fsubstitute_command_keys (tem);
992d176e 491 return tem;
c6045832
JB
492}
493\f
283e1184
JB
494/* Scanning the DOC files and placing docstring offsets into functions. */
495
496static void
6e6c82a4 497store_function_docstring (Lisp_Object obj, ptrdiff_t offset)
283e1184 498{
1449fa1d
CY
499 /* Don't use indirect_function here, or defaliases will apply their
500 docstrings to the base functions (Bug#2603). */
c644523b 501 Lisp_Object fun = SYMBOLP (obj) ? XSYMBOL (obj)->function : obj;
283e1184
JB
502
503 /* The type determines where the docstring is stored. */
504
505 /* Lisp_Subrs have a slot for it. */
e6d12642 506 if (SUBRP (fun))
b08a63cc
PE
507 {
508 intptr_t negative_offset = - offset;
509 XSUBR (fun)->doc = (char *) negative_offset;
510 }
283e1184
JB
511
512 /* If it's a lisp form, stick it in the form. */
513 else if (CONSP (fun))
514 {
515 Lisp_Object tem;
516
03699b14 517 tem = XCAR (fun);
23aba0ea
SM
518 if (EQ (tem, Qlambda) || EQ (tem, Qautoload)
519 || (EQ (tem, Qclosure) && (fun = XCDR (fun), 1)))
283e1184
JB
520 {
521 tem = Fcdr (Fcdr (fun));
03699b14 522 if (CONSP (tem) && INTEGERP (XCAR (tem)))
57618ecf
SM
523 /* FIXME: This modifies typically pure hash-cons'd data, so its
524 correctness is quite delicate. */
d6d23852 525 XSETCAR (tem, make_number (offset));
283e1184
JB
526 }
527 else if (EQ (tem, Qmacro))
03699b14 528 store_function_docstring (XCDR (fun), offset);
283e1184
JB
529 }
530
531 /* Bytecode objects sometimes have slots for it. */
e6d12642 532 else if (COMPILEDP (fun))
283e1184
JB
533 {
534 /* This bytecode object must have a slot for the
535 docstring, since we've found a docstring for it. */
87afdd65 536 if ((ASIZE (fun) & PSEUDOVECTOR_SIZE_MASK) > COMPILED_DOC_STRING)
3ae565b3 537 ASET (fun, COMPILED_DOC_STRING, make_number (offset));
049fac7c
SM
538 else
539 message ("No docstring slot for %s",
0df098bf 540 SYMBOLP (obj) ? SSDATA (SYMBOL_NAME (obj)) : "<anonymous>");
283e1184
JB
541 }
542}
543
544
c6045832 545DEFUN ("Snarf-documentation", Fsnarf_documentation, Ssnarf_documentation,
335c5470 546 1, 1, 0,
f4e25f94
RS
547 doc: /* Used during Emacs initialization to scan the `etc/DOC...' file.
548This searches the `etc/DOC...' file for doc strings and
549records them in function and variable definitions.
550The function takes one argument, FILENAME, a string;
551it specifies the file name (without a directory) of the DOC file.
552That file is found in `../etc' now; later, when the dumped Emacs is run,
98b6690a 553the same file name is found in the `doc-directory'. */)
5842a27b 554 (Lisp_Object filename)
c6045832
JB
555{
556 int fd;
557 char buf[1024 + 1];
a08d4ba7
PE
558 int filled;
559 EMACS_INT pos;
24109c98 560 Lisp_Object sym;
a08d4ba7
PE
561 char *p, *name;
562 bool skip_file = 0;
a8cd4836 563 ptrdiff_t count;
2241d76e
GM
564 /* Preloaded defcustoms using custom-initialize-delay are added to
565 this list, but kept unbound. See http://debbugs.gnu.org/11565 */
566 Lisp_Object delayed_init =
567 find_symbol_value (intern ("custom-delayed-init-variables"));
568
569 if (EQ (delayed_init, Qunbound)) delayed_init = Qnil;
c6045832 570
b7826503 571 CHECK_STRING (filename);
c6045832 572
a154a4ef 573 if
c6045832 574#ifndef CANNOT_DUMP
a154a4ef 575 (!NILP (Vpurify_flag))
c6045832 576#else /* CANNOT_DUMP */
a154a4ef 577 (0)
c6045832 578#endif /* CANNOT_DUMP */
a154a4ef 579 {
38182d90 580 name = alloca (SCHARS (filename) + 14);
a154a4ef
SM
581 strcpy (name, "../etc/");
582 }
583 else
584 {
585 CHECK_STRING (Vdoc_directory);
38182d90 586 name = alloca (SCHARS (filename) + SCHARS (Vdoc_directory) + 1);
42a5b22f 587 strcpy (name, SSDATA (Vdoc_directory));
a154a4ef 588 }
42a5b22f 589 strcat (name, SSDATA (filename)); /*** Add this line ***/
c6045832 590
d87a9ab8
JD
591 /* Vbuild_files is nil when temacs is run, and non-nil after that. */
592 if (NILP (Vbuild_files))
c2418359
PE
593 {
594 static char const *const buildobj[] =
595 {
596 #include "buildobj.h"
597 };
faa52174 598 int i = ARRAYELTS (buildobj);
c2418359
PE
599 while (0 <= --i)
600 Vbuild_files = Fcons (build_string (buildobj[i]), Vbuild_files);
601 Vbuild_files = Fpurecopy (Vbuild_files);
602 }
d87a9ab8 603
68c45bf0 604 fd = emacs_open (name, O_RDONLY, 0);
c6045832 605 if (fd < 0)
b648c163
PE
606 {
607 int open_errno = errno;
608 report_file_errno ("Opening doc string file", build_string (name),
609 open_errno);
610 }
a8cd4836
PE
611 count = SPECPDL_INDEX ();
612 record_unwind_protect_int (close_file_unwind, fd);
c6045832
JB
613 Vdoc_file_name = filename;
614 filled = 0;
615 pos = 0;
616 while (1)
617 {
a415e694 618 register char *end;
c6045832 619 if (filled < 512)
68c45bf0 620 filled += emacs_read (fd, &buf[filled], sizeof buf - 1 - filled);
c6045832
JB
621 if (!filled)
622 break;
623
624 buf[filled] = 0;
c6045832 625 end = buf + (filled < 512 ? filled : filled - 128);
a84b7c53 626 p = memchr (buf, '\037', end - buf);
983b8302 627 /* p points to ^_Ffunctionname\n or ^_Vvarname\n or ^_Sfilename\n. */
a84b7c53 628 if (p)
c6045832 629 {
8966b757 630 end = strchr (p, '\n');
d87a9ab8
JD
631
632 /* See if this is a file name, and if it is a file in build-files. */
983b8302 633 if (p[1] == 'S')
d87a9ab8 634 {
983b8302
J
635 skip_file = 0;
636 if (end - p > 4 && end[-2] == '.'
637 && (end[-1] == 'o' || end[-1] == 'c'))
638 {
d311d28c 639 ptrdiff_t len = end - p - 2;
983b8302 640 char *fromfile = alloca (len + 1);
e99a530f 641 memcpy (fromfile, &p[2], len);
983b8302
J
642 fromfile[len] = 0;
643 if (fromfile[len-1] == 'c')
644 fromfile[len-1] = 'o';
645
646 skip_file = NILP (Fmember (build_string (fromfile),
647 Vbuild_files));
648 }
d87a9ab8
JD
649 }
650
141199d1 651 sym = oblookup (Vobarray, p + 2,
9eee99eb
PE
652 multibyte_chars_in_text ((unsigned char *) p + 2,
653 end - p - 2),
141199d1 654 end - p - 2);
11fb4bdb
SM
655 /* Check skip_file so that when a function is defined several
656 times in different files (typically, once in xterm, once in
657 w32term, ...), we only pay attention to the one that
658 matters. */
d87a9ab8 659 if (! skip_file && SYMBOLP (sym))
c6045832
JB
660 {
661 /* Attach a docstring to a variable? */
662 if (p[1] == 'V')
663 {
664 /* Install file-position as variable-documentation property
665 and make it negative for a user-variable
666 (doc starts with a `*'). */
2241d76e
GM
667 if (!NILP (Fboundp (sym))
668 || !NILP (Fmemq (sym, delayed_init)))
05920a43
GM
669 Fput (sym, Qvariable_documentation,
670 make_number ((pos + end + 1 - buf)
671 * (end[1] == '*' ? -1 : 1)));
c6045832
JB
672 }
673
283e1184 674 /* Attach a docstring to a function? */
c6045832 675 else if (p[1] == 'F')
05920a43
GM
676 {
677 if (!NILP (Ffboundp (sym)))
678 store_function_docstring (sym, pos + end + 1 - buf);
679 }
6b61353c
KH
680 else if (p[1] == 'S')
681 ; /* Just a source file name boundary marker. Ignore it. */
682
283e1184 683 else
c2982e87 684 error ("DOC file invalid at position %"pI"d", pos);
c6045832
JB
685 }
686 }
687 pos += end - buf;
688 filled -= end - buf;
840b985a 689 memmove (buf, end, filled);
c6045832 690 }
a8cd4836 691 return unbind_to (count, Qnil);
c6045832
JB
692}
693\f
a7ca3326 694DEFUN ("substitute-command-keys", Fsubstitute_command_keys,
335c5470
PJ
695 Ssubstitute_command_keys, 1, 1, 0,
696 doc: /* Substitute key descriptions for command names in STRING.
353c87f6
CY
697Each substring of the form \\=\\[COMMAND] is replaced by either a
698keystroke sequence that invokes COMMAND, or "M-x COMMAND" if COMMAND
699is not on any keys.
700
701Each substring of the form \\=\\{MAPVAR} is replaced by a summary of
702the value of MAPVAR as a keymap. This summary is similar to the one
703produced by `describe-bindings'. The summary ends in two newlines
704\(used by the helper function `help-make-xrefs' to find the end of the
705summary).
706
707Each substring of the form \\=\\<MAPVAR> specifies the use of MAPVAR
335c5470
PJ
708as the keymap for future \\=\\[COMMAND] substrings.
709\\=\\= quotes the following character and is discarded;
c698360f
KS
710thus, \\=\\=\\=\\= puts \\=\\= into the output, and \\=\\=\\=\\[ puts \\=\\[ into the output.
711
353c87f6 712Return the original STRING if no substitutions are made.
049fac7c 713Otherwise, return a new string. */)
5842a27b 714 (Lisp_Object string)
c6045832 715{
9eee99eb 716 char *buf;
a08d4ba7
PE
717 bool changed = 0;
718 unsigned char *strp;
719 char *bufp;
3d0c92a2
PE
720 ptrdiff_t idx;
721 ptrdiff_t bsize;
665d3046 722 Lisp_Object tem;
c6045832
JB
723 Lisp_Object keymap;
724 unsigned char *start;
3d0c92a2 725 ptrdiff_t length, length_byte;
665d3046
JB
726 Lisp_Object name;
727 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
a08d4ba7 728 bool multibyte;
3d0c92a2 729 ptrdiff_t nchars;
c6045832 730
4acb738e 731 if (NILP (string))
c6045832
JB
732 return Qnil;
733
b7826503 734 CHECK_STRING (string);
665d3046
JB
735 tem = Qnil;
736 keymap = Qnil;
737 name = Qnil;
4acb738e 738 GCPRO4 (string, tem, keymap, name);
c6045832 739
141199d1
RS
740 multibyte = STRING_MULTIBYTE (string);
741 nchars = 0;
742
9a425dcb
RS
743 /* KEYMAP is either nil (which means search all the active keymaps)
744 or a specified local map (which means search just that and the
745 global map). If non-nil, it might come from Voverriding_local_map,
4acb738e 746 or from a \\<mapname> construct in STRING itself.. */
bfa3acd6 747 keymap = Voverriding_local_map;
c6045832 748
d5db4077 749 bsize = SBYTES (string);
c1ade6f7 750 bufp = buf = xmalloc_atomic (bsize);
c6045832 751
8a7bde3e 752 strp = SDATA (string);
d5db4077 753 while (strp < SDATA (string) + SBYTES (string))
c6045832
JB
754 {
755 if (strp[0] == '\\' && strp[1] == '=')
756 {
757 /* \= quotes the next character;
758 thus, to put in \[ without its special meaning, use \=\[. */
759 changed = 1;
141199d1
RS
760 strp += 2;
761 if (multibyte)
762 {
763 int len;
141199d1 764
62a6e103 765 STRING_CHAR_AND_LENGTH (strp, len);
141199d1
RS
766 if (len == 1)
767 *bufp = *strp;
768 else
72af86bd 769 memcpy (bufp, strp, len);
141199d1
RS
770 strp += len;
771 bufp += len;
772 nchars++;
773 }
774 else
775 *bufp++ = *strp++, nchars++;
c6045832
JB
776 }
777 else if (strp[0] == '\\' && strp[1] == '[')
778 {
3d0c92a2 779 ptrdiff_t start_idx;
a08d4ba7 780 bool follow_remap = 1;
b6c53774 781
c6045832
JB
782 changed = 1;
783 strp += 2; /* skip \[ */
784 start = strp;
d5db4077 785 start_idx = start - SDATA (string);
c6045832 786
8a7bde3e 787 while ((strp - SDATA (string)
d5db4077 788 < SBYTES (string))
c6045832
JB
789 && *strp != ']')
790 strp++;
141199d1
RS
791 length_byte = strp - start;
792
c6045832
JB
793 strp++; /* skip ] */
794
795 /* Save STRP in IDX. */
8a7bde3e 796 idx = strp - SDATA (string);
9eee99eb 797 name = Fintern (make_string ((char *) start, length_byte), Qnil);
11f9d6e1 798
a1d3a188 799 do_remap:
a88a5372 800 tem = Fwhere_is_internal (name, keymap, Qt, Qnil, Qnil);
332e51c1 801
77b37c05 802 if (VECTORP (tem) && ASIZE (tem) > 1
a1d3a188
KS
803 && EQ (AREF (tem, 0), Qremap) && SYMBOLP (AREF (tem, 1))
804 && follow_remap)
805 {
806 name = AREF (tem, 1);
807 follow_remap = 0;
808 goto do_remap;
809 }
810
11f9d6e1
GM
811 /* Note the Fwhere_is_internal can GC, so we have to take
812 relocation of string contents into account. */
d5db4077
KR
813 strp = SDATA (string) + idx;
814 start = SDATA (string) + start_idx;
c6045832 815
265a9e55 816 if (NILP (tem)) /* but not on any keys */
c6045832 817 {
3d0c92a2
PE
818 ptrdiff_t offset = bufp - buf;
819 if (STRING_BYTES_BOUND - 4 < bsize)
820 string_overflow ();
38182d90 821 buf = xrealloc (buf, bsize += 4);
8d17fe0b 822 bufp = buf + offset;
72af86bd 823 memcpy (bufp, "M-x ", 4);
c6045832 824 bufp += 4;
141199d1
RS
825 nchars += 4;
826 if (multibyte)
827 length = multibyte_chars_in_text (start, length_byte);
828 else
829 length = length_byte;
c6045832
JB
830 goto subst;
831 }
832 else
833 { /* function is on a key */
a1bfe073 834 tem = Fkey_description (tem, Qnil);
c6045832
JB
835 goto subst_string;
836 }
837 }
838 /* \{foo} is replaced with a summary of the keymap (symbol-value foo).
839 \<foo> just sets the keymap used for \[cmd]. */
840 else if (strp[0] == '\\' && (strp[1] == '{' || strp[1] == '<'))
841 {
842 struct buffer *oldbuf;
3d0c92a2 843 ptrdiff_t start_idx;
e679a3c1 844 /* This is for computing the SHADOWS arg for describe_map_tree. */
d42f4f0f 845 Lisp_Object active_maps = Fcurrent_active_maps (Qnil, Qnil);
e679a3c1 846 Lisp_Object earlier_maps;
d17f4dba 847 ptrdiff_t count = SPECPDL_INDEX ();
c6045832
JB
848
849 changed = 1;
850 strp += 2; /* skip \{ or \< */
851 start = strp;
d5db4077 852 start_idx = start - SDATA (string);
c6045832 853
ccddfb9e 854 while ((strp - SDATA (string) < SBYTES (string))
c6045832
JB
855 && *strp != '}' && *strp != '>')
856 strp++;
141199d1
RS
857
858 length_byte = strp - start;
c6045832
JB
859 strp++; /* skip } or > */
860
861 /* Save STRP in IDX. */
8a7bde3e 862 idx = strp - SDATA (string);
c6045832
JB
863
864 /* Get the value of the keymap in TEM, or nil if undefined.
865 Do this while still in the user's current buffer
866 in case it is a local variable. */
9eee99eb 867 name = Fintern (make_string ((char *) start, length_byte), Qnil);
c6045832 868 tem = Fboundp (name);
265a9e55 869 if (! NILP (tem))
c6045832
JB
870 {
871 tem = Fsymbol_value (name);
265a9e55 872 if (! NILP (tem))
11f9d6e1 873 {
02067692
SM
874 tem = get_keymap (tem, 0, 1);
875 /* Note that get_keymap can GC. */
d5db4077
KR
876 strp = SDATA (string) + idx;
877 start = SDATA (string) + start_idx;
11f9d6e1 878 }
c6045832
JB
879 }
880
881 /* Now switch to a temp buffer. */
882 oldbuf = current_buffer;
883 set_buffer_internal (XBUFFER (Vprin1_to_string_buffer));
d17f4dba
EZ
884 /* This is for an unusual case where some after-change
885 function uses 'format' or 'prin1' or something else that
886 will thrash Vprin1_to_string_buffer we are using. */
887 specbind (Qinhibit_modification_hooks, Qt);
c6045832 888
265a9e55 889 if (NILP (tem))
c6045832
JB
890 {
891 name = Fsymbol_name (name);
c89926a5 892 insert_string ("\nUses keymap `");
141199d1 893 insert_from_string (name, 0, 0,
d5db4077
KR
894 SCHARS (name),
895 SBYTES (name), 1);
c89926a5 896 insert_string ("', which is not currently defined.\n");
c6045832
JB
897 if (start[-1] == '<') keymap = Qnil;
898 }
899 else if (start[-1] == '<')
900 keymap = tem;
901 else
e679a3c1
RS
902 {
903 /* Get the list of active keymaps that precede this one.
904 If this one's not active, get nil. */
905 earlier_maps = Fcdr (Fmemq (tem, Freverse (active_maps)));
906 describe_map_tree (tem, 1, Fnreverse (earlier_maps),
7d652d97 907 Qnil, 0, 1, 0, 0, 1);
e679a3c1 908 }
c6045832
JB
909 tem = Fbuffer_string ();
910 Ferase_buffer ();
911 set_buffer_internal (oldbuf);
d17f4dba 912 unbind_to (count, Qnil);
c6045832
JB
913
914 subst_string:
d5db4077
KR
915 start = SDATA (tem);
916 length = SCHARS (tem);
917 length_byte = SBYTES (tem);
c6045832 918 subst:
8d17fe0b 919 {
3d0c92a2
PE
920 ptrdiff_t offset = bufp - buf;
921 if (STRING_BYTES_BOUND - length_byte < bsize)
922 string_overflow ();
38182d90 923 buf = xrealloc (buf, bsize += length_byte);
8d17fe0b 924 bufp = buf + offset;
72af86bd 925 memcpy (bufp, start, length_byte);
8d17fe0b
GM
926 bufp += length_byte;
927 nchars += length;
928 /* Check STRING again in case gc relocated it. */
51b59d79 929 strp = SDATA (string) + idx;
8d17fe0b 930 }
c6045832 931 }
141199d1
RS
932 else if (! multibyte) /* just copy other chars */
933 *bufp++ = *strp++, nchars++;
934 else
935 {
936 int len;
141199d1 937
62a6e103 938 STRING_CHAR_AND_LENGTH (strp, len);
141199d1
RS
939 if (len == 1)
940 *bufp = *strp;
941 else
72af86bd 942 memcpy (bufp, strp, len);
141199d1
RS
943 strp += len;
944 bufp += len;
945 nchars++;
946 }
c6045832
JB
947 }
948
949 if (changed) /* don't bother if nothing substituted */
cc5bf9eb 950 tem = make_string_from_bytes (buf, nchars, bufp - buf);
c6045832 951 else
4acb738e 952 tem = string;
9ac0d9e0 953 xfree (buf);
665d3046 954 RETURN_UNGCPRO (tem);
c6045832
JB
955}
956\f
dfcf069d 957void
971de7fb 958syms_of_doc (void)
c6045832 959{
cd3520a4 960 DEFSYM (Qfunction_documentation, "function-documentation");
177c0ea7 961
29208e82 962 DEFVAR_LISP ("internal-doc-file-name", Vdoc_file_name,
335c5470 963 doc: /* Name of file containing documentation strings of built-in symbols. */);
c6045832
JB
964 Vdoc_file_name = Qnil;
965
29208e82 966 DEFVAR_LISP ("build-files", Vbuild_files,
d87a9ab8
JD
967 doc: /* A list of files used to build this Emacs binary. */);
968 Vbuild_files = Qnil;
969
c6045832
JB
970 defsubr (&Sdocumentation);
971 defsubr (&Sdocumentation_property);
972 defsubr (&Ssnarf_documentation);
973 defsubr (&Ssubstitute_command_keys);
974}