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