comparison src/doc.c @ 3368:959746c534f6

[xemacs-hg @ 2006-04-29 16:15:21 by aidan] Support builtin functions in find-function.
author aidan
date Sat, 29 Apr 2006 16:15:31 +0000
parents facf3239ba30
children 3583b965b1c5
comparison
equal deleted inserted replaced
3367:84ee3ca77e7f 3368:959746c534f6
37 37
38 Lisp_Object Vinternal_doc_file_name; 38 Lisp_Object Vinternal_doc_file_name;
39 39
40 Lisp_Object QSsubstitute; 40 Lisp_Object QSsubstitute;
41 41
42 /* Read and return doc string or instructions from open file descriptor FD 42 /* Work out what source file a function or variable came from, taking the
43 at position POSITION. Does not close the file. Returns string; or if 43 information from the documentation file. */
44 error, returns a cons holding the error data to pass to Fsignal. 44
45 NAME_NONRELOC and NAME_RELOC are only used for the error messages. */ 45 static Lisp_Object
46 extract_object_file_name (int fd, EMACS_INT doc_pos,
47 Ibyte *name_nonreloc, Lisp_Object name_reloc,
48 int standard_doc_file)
49 {
50 Ibyte buf[DOC_MAX_FILENAME_LENGTH];
51 Ibyte *buffer = buf;
52 int buffer_size = sizeof (buf), space_left;
53 Ibyte *from, *to;
54 REGISTER Ibyte *p = buffer;
55 Lisp_Object return_me;
56 Lisp_Object fdstream = Qnil, instream = Qnil;
57 struct gcpro gcpro1, gcpro2;
58 EMACS_INT position, seenS = 0;
59
60 GCPRO2 (fdstream, instream);
61
62 position = doc_pos > DOC_MAX_FILENAME_LENGTH ?
63 doc_pos - DOC_MAX_FILENAME_LENGTH : 0;
64
65 if (0 > lseek (fd, position, 0))
66 {
67 if (name_nonreloc)
68 name_reloc = build_intstring (name_nonreloc);
69 return_me = list3 (build_msg_string
70 ("Position out of range in doc string file"),
71 name_reloc, make_int (position));
72 goto done;
73 }
74
75 fdstream = make_filedesc_input_stream (fd, 0, -1, 0);
76 Lstream_set_buffering (XLSTREAM (fdstream), LSTREAM_UNBUFFERED, 0);
77 instream =
78 make_coding_input_stream
79 (XLSTREAM (fdstream), standard_doc_file ? Qescape_quoted : Qbinary,
80 CODING_DECODE, 0);
81 Lstream_set_buffering (XLSTREAM (instream), LSTREAM_UNBUFFERED, 0);
82
83 space_left = buffer_size - (p - buffer);
84 while (space_left > 0)
85 {
86 int nread;
87
88 nread = Lstream_read (XLSTREAM (instream), p, space_left);
89 if (nread < 0)
90 {
91 return_me = list1 (build_msg_string
92 ("Read error on documentation file"));
93 goto done;
94 }
95
96 p[nread] = 0;
97
98 if (!nread)
99 break;
100
101 p += nread;
102 space_left = buffer_size - (p - buffer);
103 }
104
105 /* First, search backward for the "\037S" that marks the beginning of the
106 file name, then search forward from that to the newline or to the end
107 of the buffer. */
108 from = p;
109
110 while (from > buf)
111 {
112 --from;
113 if (seenS)
114 {
115 if ('\037' == *from)
116 {
117 /* Got a file name; adjust `from' to point to it, break out of
118 the loop. */
119 from += 2;
120 break;
121 }
122 }
123 /* Is *from 'S' ? */
124 seenS = ('S' == *from);
125 }
126
127 if (buf == from)
128 {
129 /* We've scanned back to the beginning of the buffer without hitting
130 the file name. Either the file name plus the symbol name is longer
131 than DOC_MAX_FILENAME_LENGTH--which shouldn't happen, because it'll
132 trigger an assertion failure in make-docfile, the DOC file is
133 corrupt, or it was produced by a version of make-docfile that
134 doesn't store the file name with the symbol name and docstring. */
135 return_me = list1 (build_msg_string
136 ("Object file name not stored in doc file"));
137 goto done;
138 }
139
140 to = from;
141 /* Search for the end of the file name. */
142 while (++to < p)
143 {
144 if ('\n' == *to || '\037' == *to)
145 {
146 break;
147 }
148 }
149
150 /* Don't require the file name to end in a newline. */
151 return_me = make_string (from, to - from);
152
153 done:
154 if (!NILP (instream))
155 {
156 Lstream_delete (XLSTREAM (instream));
157 Lstream_delete (XLSTREAM (fdstream));
158 }
159
160 UNGCPRO;
161 return return_me;
162 }
46 163
47 Lisp_Object 164 Lisp_Object
48 unparesseuxify_doc_string (int fd, EMACS_INT position, 165 unparesseuxify_doc_string (int fd, EMACS_INT position,
49 Ibyte *name_nonreloc, Lisp_Object name_reloc, 166 Ibyte *name_nonreloc, Lisp_Object name_reloc,
50 int standard_doc_file) 167 int standard_doc_file)
285 if (!STRINGP (string)) 402 if (!STRINGP (string))
286 invalid_state ("loading bytecode failed to return string", string); 403 invalid_state ("loading bytecode failed to return string", string);
287 return Fread (string); 404 return Fread (string);
288 } 405 }
289 406
407 static Lisp_Object
408 get_object_file_name (Lisp_Object filepos)
409 {
410 REGISTER int fd;
411 REGISTER Ibyte *name_nonreloc = 0;
412 EMACS_INT position;
413 Lisp_Object file, tem;
414 Lisp_Object name_reloc = Qnil;
415 int standard_doc_file = 0;
416
417 if (INTP (filepos))
418 {
419 file = Vinternal_doc_file_name;
420 standard_doc_file = 1;
421 position = XINT (filepos);
422 }
423 else if (CONSP (filepos) && INTP (XCDR (filepos)))
424 {
425 file = XCAR (filepos);
426 position = XINT (XCDR (filepos));
427 if (position < 0)
428 position = - position;
429 }
430 else
431 return Qnil;
432
433 if (!STRINGP (file))
434 return Qnil;
435
436 /* Put the file name in NAME as a C string.
437 If it is relative, combine it with Vdoc_directory. */
438
439 tem = Ffile_name_absolute_p (file);
440 if (NILP (tem))
441 {
442 Bytecount minsize;
443 /* XEmacs: Move this check here. OK if called during loadup to
444 load byte code instructions. */
445 if (!STRINGP (Vdoc_directory))
446 return Qnil;
447
448 minsize = XSTRING_LENGTH (Vdoc_directory);
449 /* sizeof ("../lib-src/") == 12 */
450 if (minsize < 12)
451 minsize = 12;
452 name_nonreloc = alloca_ibytes (minsize + XSTRING_LENGTH (file) + 8);
453 string_join (name_nonreloc, Vdoc_directory, file);
454 }
455 else
456 name_reloc = file;
457
458 fd = qxe_open (name_nonreloc ? name_nonreloc :
459 XSTRING_DATA (name_reloc), O_RDONLY | OPEN_BINARY, 0);
460 if (fd < 0)
461 {
462 if (purify_flag)
463 {
464 /* sizeof ("../lib-src/") == 12 */
465 name_nonreloc = alloca_ibytes (12 + XSTRING_LENGTH (file) + 8);
466 /* Preparing to dump; DOC file is probably not installed.
467 So check in ../lib-src. */
468 qxestrcpy_ascii (name_nonreloc, "../lib-src/");
469 qxestrcat (name_nonreloc, XSTRING_DATA (file));
470
471 fd = qxe_open (name_nonreloc, O_RDONLY | OPEN_BINARY, 0);
472 }
473
474 if (fd < 0)
475 report_file_error ("Cannot open doc string file",
476 name_nonreloc ? build_intstring (name_nonreloc) :
477 name_reloc);
478 }
479
480 tem = extract_object_file_name (fd, position, name_nonreloc, name_reloc,
481 standard_doc_file);
482 retry_close (fd);
483
484 if (!STRINGP (tem))
485 signal_error_1 (Qinvalid_byte_code, tem);
486
487 return tem;
488 }
489
490
491 static void
492 weird_doc (Lisp_Object sym, const CIbyte *weirdness, const CIbyte *type,
493 int pos)
494 {
495 if (!strcmp (weirdness, GETTEXT ("duplicate"))) return;
496 message ("Note: Strange doc (%s) for %s %s @ %d",
497 weirdness, type, XSTRING_DATA (XSYMBOL (sym)->name), pos);
498 }
499
500 DEFUN ("built-in-symbol-file", Fbuilt_in_symbol_file, 1, 1, 0, /*
501 Return the C source file built-in symbol SYM comes from.
502 Don't use this. Use the more general `symbol-file' (q.v.) instead.
503 */
504 (symbol))
505 {
506 /* This function can GC */
507 Lisp_Object fun;
508 Lisp_Object filename = Qnil;
509
510 if (EQ(Ffboundp(symbol), Qt))
511 {
512 fun = Findirect_function (symbol);
513
514 if (SUBRP (fun))
515 {
516 if (XSUBR (fun)->doc == 0)
517 return Qnil;
518
519 if ((EMACS_INT) XSUBR (fun)->doc >= 0)
520 {
521 weird_doc (symbol, "No file info available for function",
522 GETTEXT("function"), 0);
523 return Qnil;
524 }
525 else
526 filename = get_object_file_name
527 (make_int (- (EMACS_INT) XSUBR (fun)->doc));
528 }
529 }
530 else if (EQ(Fboundp(symbol), Qt))
531 {
532 Lisp_Object doc_offset = Fget (symbol, Qvariable_documentation, Qnil);
533
534 if (!NILP(doc_offset))
535 {
536 if (INTP(doc_offset))
537 {
538 filename = get_object_file_name
539 (XINT (doc_offset) > 0 ? doc_offset
540 : make_int (- XINT (doc_offset)));
541 }
542 else if (CONSP(doc_offset))
543 {
544 filename = get_object_file_name(doc_offset);
545 }
546 }
547 }
548 return filename;
549 }
550
290 DEFUN ("documentation", Fdocumentation, 1, 2, 0, /* 551 DEFUN ("documentation", Fdocumentation, 1, 2, 0, /*
291 Return the documentation string of FUNCTION. 552 Return the documentation string of FUNCTION.
292 Unless a non-nil second argument RAW is given, the 553 Unless a non-nil second argument RAW is given, the
293 string is passed through `substitute-command-keys'. 554 string is passed through `substitute-command-keys'.
294 */ 555 */
417 doc = Fsubstitute_command_keys (doc); 678 doc = Fsubstitute_command_keys (doc);
418 UNGCPRO; 679 UNGCPRO;
419 return doc; 680 return doc;
420 } 681 }
421 682
422 static void
423 weird_doc (Lisp_Object sym, const CIbyte *weirdness, const CIbyte *type,
424 int pos)
425 {
426 if (!strcmp (weirdness, GETTEXT ("duplicate"))) return;
427 message ("Note: Strange doc (%s) for %s %s @ %d",
428 weirdness, type, XSTRING_DATA (XSYMBOL (sym)->name), pos);
429 }
430 683
431 DEFUN ("Snarf-documentation", Fsnarf_documentation, 1, 1, 0, /* 684 DEFUN ("Snarf-documentation", Fsnarf_documentation, 1, 1, 0, /*
432 Used during Emacs initialization, before dumping runnable Emacs, 685 Used during Emacs initialization, before dumping runnable Emacs,
433 to find pointers to doc strings stored in `.../lib-src/DOC' and 686 to find pointers to doc strings stored in `.../lib-src/DOC' and
434 record them in function definitions. 687 record them in function definitions.
1006 /************************************************************************/ 1259 /************************************************************************/
1007 1260
1008 void 1261 void
1009 syms_of_doc (void) 1262 syms_of_doc (void)
1010 { 1263 {
1264 DEFSUBR (Fbuilt_in_symbol_file);
1011 DEFSUBR (Fdocumentation); 1265 DEFSUBR (Fdocumentation);
1012 DEFSUBR (Fdocumentation_property); 1266 DEFSUBR (Fdocumentation_property);
1013 DEFSUBR (Fsnarf_documentation); 1267 DEFSUBR (Fsnarf_documentation);
1014 DEFSUBR (Fverify_documentation); 1268 DEFSUBR (Fverify_documentation);
1015 DEFSUBR (Fsubstitute_command_keys); 1269 DEFSUBR (Fsubstitute_command_keys);