emacs-diffs
[Top][All Lists]
Advanced

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

master 13824c4: Fix c-tentative-buffer-changes to be nestable in c-save-


From: Alan Mackenzie
Subject: master 13824c4: Fix c-tentative-buffer-changes to be nestable in c-save-buffer-state
Date: Fri, 20 Aug 2021 17:14:15 -0400 (EDT)

branch: master
commit 13824c44d28427931a7e3284adec9a3a38cd2323
Author: Alan Mackenzie <acm@muc.de>
Commit: Alan Mackenzie <acm@muc.de>

    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.
---
 lisp/progmodes/cc-defs.el | 50 +++++++++++++++++++++++++++++++----------------
 1 file changed, 33 insertions(+), 17 deletions(-)

diff --git a/lisp/progmodes/cc-defs.el b/lisp/progmodes/cc-defs.el
index 01bd64c..3cb1912 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))



reply via email to

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