Handle #@00 in new reader in a compatible way (bug#63722)

This was a regression from Emacs 28.

* src/lread.c (skip_lazy_string, read0): Make #@00 read as nil, which
is a quirk from the old reader that we preserve for compatibility.
* test/src/lread-tests.el (lread-skip-to-eof): Verify it.

Reported by Richard Newton.
This commit is contained in:
Mattias Engdegård 2023-05-25 22:28:25 +02:00
parent c0d7447e9d
commit f535c0e49d
2 changed files with 27 additions and 6 deletions

View file

@ -3400,8 +3400,9 @@ read_bool_vector (Lisp_Object readcharfun)
} }
/* Skip (and optionally remember) a lazily-loaded string /* Skip (and optionally remember) a lazily-loaded string
preceded by "#@". */ preceded by "#@". Return true if this was a normal skip,
static void false if we read #@00 (which skips to EOF). */
static bool
skip_lazy_string (Lisp_Object readcharfun) skip_lazy_string (Lisp_Object readcharfun)
{ {
ptrdiff_t nskip = 0; ptrdiff_t nskip = 0;
@ -3427,9 +3428,9 @@ skip_lazy_string (Lisp_Object readcharfun)
digits++; digits++;
if (digits == 2 && nskip == 0) if (digits == 2 && nskip == 0)
{ {
/* #@00 means "skip to end" */ /* #@00 means "read nil and skip to end" */
skip_dyn_eof (readcharfun); skip_dyn_eof (readcharfun);
return; return false;
} }
} }
@ -3476,6 +3477,8 @@ skip_lazy_string (Lisp_Object readcharfun)
else else
/* Skip that many bytes. */ /* Skip that many bytes. */
skip_dyn_bytes (readcharfun, nskip); skip_dyn_bytes (readcharfun, nskip);
return true;
} }
/* Given a lazy-loaded string designator VAL, return the actual string. /* Given a lazy-loaded string designator VAL, return the actual string.
@ -3933,8 +3936,10 @@ read0 (Lisp_Object readcharfun, bool locate_syms)
/* #@NUMBER is used to skip NUMBER following bytes. /* #@NUMBER is used to skip NUMBER following bytes.
That's used in .elc files to skip over doc strings That's used in .elc files to skip over doc strings
and function definitions that can be loaded lazily. */ and function definitions that can be loaded lazily. */
skip_lazy_string (readcharfun); if (skip_lazy_string (readcharfun))
goto read_obj; goto read_obj;
obj = Qnil; /* #@00 skips to EOF and yields nil. */
break;
case '$': case '$':
/* #$ -- reference to lazy-loaded string */ /* #$ -- reference to lazy-loaded string */

View file

@ -339,4 +339,20 @@ literals (Bug#20852)."
(should (byte-code-function-p f)) (should (byte-code-function-p f))
(should (equal (aref f 4) "My little\ndoc string\nhere")))))) (should (equal (aref f 4) "My little\ndoc string\nhere"))))))
(ert-deftest lread-skip-to-eof ()
;; Check the special #@00 syntax that, for compatibility, reads as
;; nil while absorbing the remainder of the input.
(with-temp-buffer
(insert "#@00 and the rest\n"
"should be ignored) entirely\n")
(goto-char (point-min))
(should (equal (read (current-buffer)) nil))
(should (eobp))
;; Add an unbalanced bracket to the beginning and try again;
;; we should get an error.
(goto-char (point-min))
(insert "( ")
(goto-char (point-min))
(should-error (read (current-buffer)) :type 'end-of-file)))
;;; lread-tests.el ends here ;;; lread-tests.el ends here