]> git.eshelyaron.com Git - emacs.git/commitdiff
Make force-load-doc-strings work again
authorMattias Engdegård <mattiase@acm.org>
Sat, 6 Aug 2022 11:38:12 +0000 (13:38 +0200)
committerMattias Engdegård <mattiase@acm.org>
Sun, 7 Aug 2022 08:25:03 +0000 (10:25 +0200)
When load-force-doc-strings is true, read (#$ . POS) as the (unibyte)
string referred to.  This feature was lost by mistake in the recent
nonrecursive reader rewrite.

Noticed by Stefan Monnier.

* src/lread.c (get_lazy_string): New function (code mostly recycled
from an old version).
(read0): Detect (#$ . FIXNUM) and retrieve the string if appropriate.
* test/src/lread-resources/lazydoc.el:
* test/src/lread-tests.el (lread-force-load-doc-strings):
New test.

src/lread.c
test/src/lread-resources/lazydoc.el [new file with mode: 0644]
test/src/lread-tests.el

index b7d8d9eeca529055ba54950c5234cb28acab8e9e..58fe3c5a9c5c22fab81d725942287ce12972f323 100644 (file)
@@ -3496,6 +3496,64 @@ skip_lazy_string (Lisp_Object readcharfun)
     skip_dyn_bytes (readcharfun, nskip);
 }
 
+static Lisp_Object
+get_lazy_string (Lisp_Object val)
+{
+  char *saved = NULL;
+  file_offset saved_position;
+  /* Get a doc string from the file we are loading.
+     If it's in saved_doc_string, get it from there.
+
+     Here, we don't know if the string is a bytecode string or a doc
+     string.  As a bytecode string must be unibyte, we always return a
+     unibyte string.  If it is actually a doc string, caller must make
+     it multibyte.  */
+
+  /* Position is negative for user variables.  */
+  EMACS_INT pos = eabs (XFIXNUM (XCDR (val)));
+  if (pos >= saved_doc_string_position
+      && pos < (saved_doc_string_position + saved_doc_string_length))
+    {
+      saved = saved_doc_string;
+      saved_position = saved_doc_string_position;
+    }
+  /* Look in prev_saved_doc_string the same way.  */
+  else if (pos >= prev_saved_doc_string_position
+          && pos < (prev_saved_doc_string_position
+                    + prev_saved_doc_string_length))
+    {
+      saved = prev_saved_doc_string;
+      saved_position = prev_saved_doc_string_position;
+    }
+  if (saved)
+    {
+      ptrdiff_t start = pos - saved_position;
+      ptrdiff_t from = start;
+      ptrdiff_t to = start;
+
+      /* Process quoting with ^A, and find the end of the string,
+        which is marked with ^_ (037).  */
+      while (saved[from] != 037)
+       {
+         int c = saved[from++];
+         if (c == 1)
+           {
+             c = saved[from++];
+             saved[to++] = (c == 1 ? c
+                            : c == '0' ? 0
+                            : c == '_' ? 037
+                            : c);
+           }
+         else
+           saved[to++] = c;
+       }
+
+      return make_unibyte_string (saved + start, to - start);
+    }
+  else
+    return get_doc_string (val, 1, 0);
+}
+
 
 /* Length of prefix only consisting of symbol constituent characters.  */
 static ptrdiff_t
@@ -4237,6 +4295,15 @@ read0 (Lisp_Object readcharfun, bool locate_syms)
            XSETCDR (e->u.list.tail, obj);
            read_stack_pop ();
            obj = e->u.list.head;
+
+           /* Hack: immediately convert (#$ . FIXNUM) to the corresponding
+              string if load-force-doc-strings is set.  */
+           if (load_force_doc_strings
+               && BASE_EQ (XCAR (obj), Vload_file_name)
+               && !NILP (XCAR (obj))
+               && FIXNUMP (XCDR (obj)))
+             obj = get_lazy_string (obj);
+
            break;
          }
 
diff --git a/test/src/lread-resources/lazydoc.el b/test/src/lread-resources/lazydoc.el
new file mode 100644 (file)
index 0000000..cb434c2
Binary files /dev/null and b/test/src/lread-resources/lazydoc.el differ
index f190f14781e996ce8c3f595317b9cf13517468b2..2f25de4cc39b1e2ed838f87221b36eff1e806ceb 100644 (file)
@@ -322,4 +322,21 @@ literals (Bug#20852)."
   (should-error (read-from-string "?\\\n x"))
   (should (equal (read-from-string "\"a\\\nb\"") '("ab" . 6))))
 
+(ert-deftest lread-force-load-doc-strings ()
+  ;; Verify that lazy doc strings are loaded lazily by default,
+  ;; but eagerly with `force-load-doc-strings' set.
+  (let ((file (expand-file-name "lazydoc.el" (ert-resource-directory))))
+    (fmakunbound 'lazydoc-fun)
+    (load file)
+    (let ((f (symbol-function 'lazydoc-fun)))
+      (should (byte-code-function-p f))
+      (should (equal (aref f 4) (cons file 87))))
+
+    (fmakunbound 'lazydoc-fun)
+    (let ((load-force-doc-strings t))
+      (load file)
+      (let ((f (symbol-function 'lazydoc-fun)))
+        (should (byte-code-function-p f))
+        (should (equal (aref f 4) "My little\ndoc string\nhere"))))))
+
 ;;; lread-tests.el ends here