comparison src/doc.c @ 44324:def57419f6ec

(get_doc_string): Return nil of the location is wrong. (reread_doc_file): New fun. (Fdocumentation, Fdocumentation_property): Call it if get_doc_string fails. (Fsnarf_documentation): Make it work for a dumped Emacs.
author Stefan Monnier <monnier@iro.umontreal.ca>
date Mon, 01 Apr 2002 23:04:46 +0000
parents 5943cc278b4c
children 80c9e94bec17
comparison
equal deleted inserted replaced
44323:fcc0f55d734f 44324:def57419f6ec
103 If it is (FILE . INTEGER), use FILE as the file name 103 If it is (FILE . INTEGER), use FILE as the file name
104 and INTEGER as the position in that file. 104 and INTEGER as the position in that file.
105 But if INTEGER is negative, make it positive. 105 But if INTEGER is negative, make it positive.
106 (A negative integer is used for user variables, so we can distinguish 106 (A negative integer is used for user variables, so we can distinguish
107 them without actually fetching the doc string.) 107 them without actually fetching the doc string.)
108
109 If the location does not point to the beginning of a docstring
110 (e.g. because the file has been modified and the location is stale),
111 return nil.
108 112
109 If UNIBYTE is nonzero, always make a unibyte string. 113 If UNIBYTE is nonzero, always make a unibyte string.
110 114
111 If DEFINITION is nonzero, assume this is for reading 115 If DEFINITION is nonzero, assume this is for reading
112 a dynamic function definition; convert the bytestring 116 a dynamic function definition; convert the bytestring
186 if (fd < 0) 190 if (fd < 0)
187 error ("Cannot open doc string file \"%s\"", name); 191 error ("Cannot open doc string file \"%s\"", name);
188 } 192 }
189 193
190 /* Seek only to beginning of disk block. */ 194 /* Seek only to beginning of disk block. */
191 offset = position % (8 * 1024); 195 /* Make sure we read at least 1024 bytes before `position'
196 so we can check the leading text for consistency. */
197 offset = min (position, max (1024, position % (8 * 1024)));
192 if (0 > lseek (fd, position - offset, 0)) 198 if (0 > lseek (fd, position - offset, 0))
193 { 199 {
194 emacs_close (fd); 200 emacs_close (fd);
195 error ("Position %ld out of range in doc string file \"%s\"", 201 error ("Position %ld out of range in doc string file \"%s\"",
196 position, name); 202 position, name);
243 break; 249 break;
244 } 250 }
245 p += nread; 251 p += nread;
246 } 252 }
247 emacs_close (fd); 253 emacs_close (fd);
254
255 /* Sanity checking. */
256 if (CONSP (filepos))
257 {
258 int test = 1;
259 if (get_doc_string_buffer[offset - test++] != ' ')
260 return Qnil;
261 while (get_doc_string_buffer[offset - test] >= '0'
262 && get_doc_string_buffer[offset - test] <= '9')
263 test++;
264 if (get_doc_string_buffer[offset - test++] != '@'
265 || get_doc_string_buffer[offset - test] != '#')
266 return Qnil;
267 }
268 else
269 {
270 int test = 1;
271 if (get_doc_string_buffer[offset - test++] != '\n')
272 return Qnil;
273 while (get_doc_string_buffer[offset - test] > ' ')
274 test++;
275 if (get_doc_string_buffer[offset - test] != '\037')
276 return Qnil;
277 }
248 278
249 /* Scan the text and perform quoting with ^A (char code 1). 279 /* Scan the text and perform quoting with ^A (char code 1).
250 ^A^A becomes ^A, ^A0 becomes a null char, and ^A_ becomes a ^_. */ 280 ^A^A becomes ^A, ^A0 becomes a null char, and ^A_ becomes a ^_. */
251 from = get_doc_string_buffer + offset; 281 from = get_doc_string_buffer + offset;
252 to = get_doc_string_buffer + offset; 282 to = get_doc_string_buffer + offset;
301 Lisp_Object 331 Lisp_Object
302 read_doc_string (filepos) 332 read_doc_string (filepos)
303 Lisp_Object filepos; 333 Lisp_Object filepos;
304 { 334 {
305 return get_doc_string (filepos, 0, 1); 335 return get_doc_string (filepos, 0, 1);
336 }
337
338 static void
339 reread_doc_file (file)
340 {
341 Lisp_Object reply, prompt[3];
342 struct gcpro gcpro1;
343 GCPRO1 (file);
344 prompt[0] = build_string ("File ");
345 prompt[1] = NILP (file) ? Vdoc_file_name : file;
346 prompt[2] = build_string (" is out-of-sync. Reload? ");
347 reply = Fy_or_n_p (Fconcat (3, prompt));
348 UNGCPRO;
349 if (NILP (reply))
350 error ("Aborted");
351
352 if (NILP (file))
353 Fsnarf_documentation (Vdoc_file_name);
354 else
355 Fload (file, Qt, Qt, Qt, Qnil);
306 } 356 }
307 357
308 DEFUN ("documentation", Fdocumentation, Sdocumentation, 1, 2, 0, 358 DEFUN ("documentation", Fdocumentation, Sdocumentation, 1, 2, 0,
309 doc: /* Return the documentation string of FUNCTION. 359 doc: /* Return the documentation string of FUNCTION.
310 Unless a non-nil second argument RAW is given, the 360 Unless a non-nil second argument RAW is given, the
382 oops: 432 oops:
383 Fsignal (Qinvalid_function, Fcons (fun, Qnil)); 433 Fsignal (Qinvalid_function, Fcons (fun, Qnil));
384 } 434 }
385 435
386 if (INTEGERP (doc) || CONSP (doc)) 436 if (INTEGERP (doc) || CONSP (doc))
387 doc = get_doc_string (doc, 0, 0); 437 {
438 Lisp_Object tem;
439 tem = get_doc_string (doc, 0, 0);
440 if (NILP (tem))
441 {
442 /* The file is newer, we need to reset the pointers. */
443 struct gcpro gcpro1, gcpro2;
444 GCPRO2 (function, raw);
445 reread_doc_file (Fcar_safe (doc));
446 UNGCPRO;
447 return Fdocumentation (function, raw);
448 }
449 else
450 doc = tem;
451 }
388 452
389 if (NILP (raw)) 453 if (NILP (raw))
390 doc = Fsubstitute_command_keys (doc); 454 doc = Fsubstitute_command_keys (doc);
391 return doc; 455 return doc;
392 } 456 }
405 { 469 {
406 Lisp_Object tem; 470 Lisp_Object tem;
407 471
408 tem = Fget (symbol, prop); 472 tem = Fget (symbol, prop);
409 if (INTEGERP (tem) || (CONSP (tem) && INTEGERP (XCDR (tem)))) 473 if (INTEGERP (tem) || (CONSP (tem) && INTEGERP (XCDR (tem))))
410 tem = get_doc_string (tem, 0, 0); 474 {
475 Lisp_Object doc = tem;
476 tem = get_doc_string (tem, 0, 0);
477 if (NILP (tem))
478 {
479 /* The file is newer, we need to reset the pointers. */
480 struct gcpro gcpro1, gcpro2, gcpro3;
481 GCPRO3 (symbol, prop, raw);
482 reread_doc_file (Fcar_safe (doc));
483 UNGCPRO;
484 return Fdocumentation_property (symbol, prop, raw);
485 }
486 }
411 else if (!STRINGP (tem)) 487 else if (!STRINGP (tem))
412 /* Feval protects its argument. */ 488 /* Feval protects its argument. */
413 tem = Feval (tem); 489 tem = Feval (tem);
414 490
415 if (NILP (raw) && STRINGP (tem)) 491 if (NILP (raw) && STRINGP (tem))
478 register int pos; 554 register int pos;
479 register char *p, *end; 555 register char *p, *end;
480 Lisp_Object sym; 556 Lisp_Object sym;
481 char *name; 557 char *name;
482 558
559 CHECK_STRING (filename);
560
561 if
483 #ifndef CANNOT_DUMP 562 #ifndef CANNOT_DUMP
484 if (NILP (Vpurify_flag)) 563 (!NILP (Vpurify_flag))
485 error ("Snarf-documentation can only be called in an undumped Emacs");
486 #endif
487
488 CHECK_STRING (filename);
489
490 #ifndef CANNOT_DUMP
491 name = (char *) alloca (XSTRING (filename)->size + 14);
492 strcpy (name, "../etc/");
493 #else /* CANNOT_DUMP */ 564 #else /* CANNOT_DUMP */
494 CHECK_STRING (Vdoc_directory); 565 (0)
495 name = (char *) alloca (XSTRING (filename)->size 566 #endif /* CANNOT_DUMP */
567 {
568 name = (char *) alloca (XSTRING (filename)->size + 14);
569 strcpy (name, "../etc/");
570 }
571 else
572 {
573 CHECK_STRING (Vdoc_directory);
574 name = (char *) alloca (XSTRING (filename)->size
496 + XSTRING (Vdoc_directory)->size + 1); 575 + XSTRING (Vdoc_directory)->size + 1);
497 strcpy (name, XSTRING (Vdoc_directory)->data); 576 strcpy (name, XSTRING (Vdoc_directory)->data);
498 #endif /* CANNOT_DUMP */ 577 }
499 strcat (name, XSTRING (filename)->data); /*** Add this line ***/ 578 strcat (name, XSTRING (filename)->data); /*** Add this line ***/
500 #ifdef VMS 579 #ifdef VMS
501 #ifndef VMS4_4 580 #ifndef VMS4_4
502 /* For VMS versions with limited file name syntax, 581 /* For VMS versions with limited file name syntax,
503 convert the name to something VMS will allow. */ 582 convert the name to something VMS will allow. */