emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Too new DOC file or .elc file


From: Stefan Monnier
Subject: Too new DOC file or .elc file
Date: Tue, 04 Dec 2001 21:10:34 -0500

Am I the only one who runs his Emacs for days on end directly
from the source directory ?

In case you don't, here is what happens when you do:

        > make
        > emacs
        ..edit..
        > make
        ..edit..sleep..eat..edit..
        > make
        ..keep going..
        > make
        C-h f fill-region
        ..you just get garbage!!

The problem is that the DOC file has been changed but your
running Emacs doesn't know about it.
Now of course, you can rely on the DOC-NN.NN.NN numbering
scheme to generate new DOC files without overwriting the old
one, but I don't like it too much because I'd rather use my
disk space for other things and because I still have
to clean up those accumulating files at some point, so it's
easier to do it as part of `make' so I don't need to think
about it.

Worse yet, the DOC numbering scheme doesn't solve the other part of
the problem:

        > (cd lisp; make recompile)
        C-h f diff-mode
        ..oh no! more garbage!

now it's the diff-mode.elc file that's been changed without telling
my trusty Emacs who still thinks it can find the docstrings where
they were before.

So I suggest the patch below.  It adds a sanity check to get_doc_string
so it can detect when a docstring reference doesn't point to where
it should and it then returns nil rather than a random bogus string.

Then `documentation' and `documentation-property' are changed as well
to notice when `get_doc_string' returns nil and offer the user
to reload the problematic file.  Ideally, the same thing should happen
in `fetch-bytecode', but it's difficult to "retry after reload"
in that case.

One more thing this does is that it allows snarf-documentation
to be called from an already dumped Emacs.  I can't see any good
reason not to allow it, so I just changed it and things seem to
work just dandy (and I can't think of any reason why they shouldn't).
Was there a good reason to prevent snarf-documentation from being
run after dumping ?


        Stefan


Index: doc.c
===================================================================
RCS file: /cvs/emacs/src/doc.c,v
retrieving revision 1.88
diff -u -r1.88 doc.c
*** doc.c       2001/12/05 01:47:27     1.88
--- doc.c       2001/12/05 02:05:26
***************
*** 106,111 ****
--- 106,115 ----
     (A negative integer is used for user variables, so we can distinguish
     them without actually fetching the doc string.)
  
+    If the location does not point to the beginning of a docstring
+    (e.g. because the file has been modified and the location is stale),
+    return nil.
+ 
     If UNIBYTE is nonzero, always make a unibyte string.
  
     If DEFINITION is nonzero, assume this is for reading
***************
*** 188,194 ****
      }
  
    /* Seek only to beginning of disk block.  */
!   offset = position % (8 * 1024);
    if (0 > lseek (fd, position - offset, 0))
      {
        emacs_close (fd);
--- 192,200 ----
      }
  
    /* Seek only to beginning of disk block.  */
!   /* Make sure we read at least 1024 bytes before `position'
!      so we can check the leading text for consistency.  */
!   offset = min (position, max (1024, position % (8 * 1024)));
    if (0 > lseek (fd, position - offset, 0))
      {
        emacs_close (fd);
***************
*** 246,251 ****
--- 252,281 ----
      }
    emacs_close (fd);
  
+   /* Sanity checking.  */
+   if (CONSP (filepos))
+     {
+       int test = 1;
+       if (get_doc_string_buffer[offset - test++] != ' ')
+       return Qnil;
+       while (get_doc_string_buffer[offset - test] >= '0'
+            && get_doc_string_buffer[offset - test] <= '9')
+       test++;
+       if (get_doc_string_buffer[offset - test++] != '@'
+         || get_doc_string_buffer[offset - test] != '#')
+       return Qnil;
+     }
+   else
+     {
+       int test = 1;
+       if (get_doc_string_buffer[offset - test++] != '\n')
+       return Qnil;
+       while (get_doc_string_buffer[offset - test] > ' ')
+       test++;
+       if (get_doc_string_buffer[offset - test] != '\037')
+       return Qnil;
+     }
+ 
    /* Scan the text and perform quoting with ^A (char code 1).
       ^A^A becomes ^A, ^A0 becomes a null char, and ^A_ becomes a ^_.  */
    from = get_doc_string_buffer + offset;
***************
*** 305,310 ****
--- 335,360 ----
    return get_doc_string (filepos, 0, 1);
  }
  
+ static void
+ reread_doc_file (file)
+ {
+   Lisp_Object reply, prompt[3];
+   struct gcpro gcpro1;
+   GCPRO1 (file);
+   prompt[0] = build_string ("File ");
+   prompt[1] = NILP (file) ? Vdoc_file_name : file;
+   prompt[2] = build_string (" is out-of-sync.  Reload? ");
+   reply = Fy_or_n_p (Fconcat (3, prompt));
+   UNGCPRO;
+   if (NILP (reply))
+     error ("Aborted");
+ 
+   if (NILP (file))
+     Fsnarf_documentation (Vdoc_file_name);
+   else
+     Fload (file, Qt, Qt, Qt, Qnil);
+ }
+ 
  DEFUN ("documentation", Fdocumentation, Sdocumentation, 1, 2, 0,
         doc: /* Return the documentation string of FUNCTION.
  Unless a non-nil second argument RAW is given, the
***************
*** 386,392 ****
      }
  
    if (INTEGERP (doc) || CONSP (doc))
!     doc = get_doc_string (doc, 0, 0);
  
    if (NILP (raw))
      doc = Fsubstitute_command_keys (doc);
--- 436,456 ----
      }
  
    if (INTEGERP (doc) || CONSP (doc))
!     {
!       Lisp_Object tem;
!       tem = get_doc_string (doc, 0, 0);
!       if (NILP (tem))
!       {
!         /* The file is newer, we need to reset the pointers.  */
!         struct gcpro gcpro1, gcpro2;
!         GCPRO2 (function, raw);
!         reread_doc_file (Fcar_safe (doc));
!         UNGCPRO;
!         return Fdocumentation (function, raw);
!       }
!       else
!       doc = tem;
!     }
  
    if (NILP (raw))
      doc = Fsubstitute_command_keys (doc);
***************
*** 409,415 ****
  
    tem = Fget (symbol, prop);
    if (INTEGERP (tem) || (CONSP (tem) && INTEGERP (XCDR (tem))))
!     tem = get_doc_string (tem, 0, 0);
    else if (!STRINGP (tem))
      /* Feval protects its argument.  */
      tem = Feval (tem);
--- 473,491 ----
  
    tem = Fget (symbol, prop);
    if (INTEGERP (tem) || (CONSP (tem) && INTEGERP (XCDR (tem))))
!     {
!       Lisp_Object doc = tem;
!       tem = get_doc_string (tem, 0, 0);
!       if (NILP (tem))
!       {
!         /* The file is newer, we need to reset the pointers.  */
!         struct gcpro gcpro1, gcpro2, gcpro3;
!         GCPRO3 (symbol, prop, raw);
!         reread_doc_file (Fcar_safe (doc));
!         UNGCPRO;
!         return Fdocumentation_property (symbol, prop, raw);
!       }
!     }
    else if (!STRINGP (tem))
      /* Feval protects its argument.  */
      tem = Feval (tem);
***************
*** 482,503 ****
    Lisp_Object sym;
    char *name;
  
- #ifndef CANNOT_DUMP
-   if (NILP (Vpurify_flag))
-     error ("Snarf-documentation can only be called in an undumped Emacs");
- #endif
- 
    CHECK_STRING (filename);
  
  #ifndef CANNOT_DUMP
!   name = (char *) alloca (XSTRING (filename)->size + 14);
!   strcpy (name, "../etc/");
  #else /* CANNOT_DUMP */
!   CHECK_STRING (Vdoc_directory);
!   name = (char *) alloca (XSTRING (filename)->size
!                         + XSTRING (Vdoc_directory)->size + 1);
!   strcpy (name, XSTRING (Vdoc_directory)->data);
  #endif /* CANNOT_DUMP */
    strcat (name, XSTRING (filename)->data);    /*** Add this line ***/
  #ifdef VMS
  #ifndef VMS4_4
--- 558,582 ----
    Lisp_Object sym;
    char *name;
  
    CHECK_STRING (filename);
  
+   if
  #ifndef CANNOT_DUMP
!     (!NILP (Vpurify_flag))
  #else /* CANNOT_DUMP */
!       (0)
  #endif /* CANNOT_DUMP */
+     {
+       name = (char *) alloca (XSTRING (filename)->size + 14);
+       strcpy (name, "../etc/");
+     }
+   else
+     {
+       CHECK_STRING (Vdoc_directory);
+       name = (char *) alloca (XSTRING (filename)->size
+                         + XSTRING (Vdoc_directory)->size + 1);
+       strcpy (name, XSTRING (Vdoc_directory)->data);
+     }
    strcat (name, XSTRING (filename)->data);    /*** Add this line ***/
  #ifdef VMS
  #ifndef VMS4_4




reply via email to

[Prev in Thread] Current Thread [Next in Thread]