diff options
author | Alan Mackenzie <acm@muc.de> | 2021-08-20 21:12:37 +0000 |
---|---|---|
committer | Alan Mackenzie <acm@muc.de> | 2021-08-20 21:12:37 +0000 |
commit | 13824c44d28427931a7e3284adec9a3a38cd2323 (patch) | |
tree | 01ac8626d8f2f4cbd8c4f11d0cf9f8dbbbf39549 /lisp/progmodes/cc-defs.el | |
parent | 681faf9f0bc41972932b72ef34c026419b6eb54d (diff) | |
download | emacs-13824c44d28427931a7e3284adec9a3a38cd2323.tar.gz emacs-13824c44d28427931a7e3284adec9a3a38cd2323.tar.bz2 emacs-13824c44d28427931a7e3284adec9a3a38cd2323.zip |
Fix c-tentative-buffer-changes to be nestable in c-save-buffer-state
* lisp/progmodes/cc-defs.el (c-tentative-buffer-changes)
(c-tnt-chng-record-state, c-tnt-chng-cleanup): Enhance such that a
buffer-undo-list of t is handled specially, so that a nil isn't consed onto
it. Thus garbage collection can't later remove the (nil . t) from the end of
the buffer-undo-list, causing an infinite loop.
Diffstat (limited to 'lisp/progmodes/cc-defs.el')
-rw-r--r-- | lisp/progmodes/cc-defs.el | 50 |
1 files changed, 33 insertions, 17 deletions
diff --git a/lisp/progmodes/cc-defs.el b/lisp/progmodes/cc-defs.el index 01bd64cb5c3..3cb1912b730 100644 --- a/lisp/progmodes/cc-defs.el +++ b/lisp/progmodes/cc-defs.el @@ -660,19 +660,27 @@ even when the buffer is read-only, and without interference from various buffer change hooks." (declare (indent 0) (debug t)) `(let (-tnt-chng-keep - -tnt-chng-state) + -tnt-chng-state + (old-undo-list buffer-undo-list)) (unwind-protect ;; Insert an undo boundary for use with `undo-more'. We ;; don't use `undo-boundary' since it doesn't insert one ;; unconditionally. - (setq buffer-undo-list (cons nil buffer-undo-list) - -tnt-chng-state (c-tnt-chng-record-state) + (setq buffer-undo-list + (if (eq old-undo-list t) + nil + (cons nil buffer-undo-list)) + old-undo-list (if (eq old-undo-list t) + t + buffer-undo-list) + -tnt-chng-state (c-tnt-chng-record-state + old-undo-list) -tnt-chng-keep (progn ,@body)) (c-tnt-chng-cleanup -tnt-chng-keep -tnt-chng-state)))) -(defun c-tnt-chng-record-state () +(defun c-tnt-chng-record-state (old-undo-list) ;; Used internally in `c-tentative-buffer-changes'. - (vector buffer-undo-list ; 0 + (vector old-undo-list ; 0 (current-buffer) ; 1 ;; No need to use markers for the point and mark; if the ;; undo got out of synch we're hosed anyway. @@ -690,18 +698,26 @@ various buffer change hooks." (setq buffer-undo-list (cdr saved-undo-list)) (if keep - ;; Find and remove the undo boundary. - (let ((p buffer-undo-list)) - (while (not (eq (cdr p) saved-undo-list)) - (setq p (cdr p))) - (setcdr p (cdr saved-undo-list))) - - ;; `primitive-undo' will remove the boundary. - (setq saved-undo-list (cdr saved-undo-list)) - (let ((undo-in-progress t)) - (while (not (eq (setq buffer-undo-list - (primitive-undo 1 buffer-undo-list)) - saved-undo-list)))) + (if (eq saved-undo-list t) + (progn + (c-benign-error + "Can't save additional undo list in c-tnt-chng-cleanup") + (setq buffer-undo-list t)) + ;; Find and remove the undo boundary. + (let ((p buffer-undo-list)) + (while (not (eq (cdr p) saved-undo-list)) + (setq p (cdr p))) + (setcdr p (cdr saved-undo-list)))) + + (let ((undo-in-progress t) + (end-undo-list (if (eq saved-undo-list t) + nil + ;; `primitive-undo' will remove the boundary. + (cdr saved-undo-list)))) + (while (not (eq buffer-undo-list end-undo-list)) + (setq buffer-undo-list (primitive-undo 1 buffer-undo-list)))) + (if (eq saved-undo-list t) + (setq buffer-undo-list t)) (when (buffer-live-p (elt saved-state 1)) (set-buffer (elt saved-state 1)) |