Mercurial > hg > xemacs-beta
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); |