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