From 66cbe8b946bf83ab19c0d9a7b9fc03e951ffd5b6 Mon Sep 17 00:00:00 2001 From: Alan Mackenzie Date: Fri, 15 May 2020 19:24:29 +0000 Subject: [PATCH] CC Mode: Fix bug #40052, where a very large macro was too slow in scrolling * lisp/progmodes/cc-engine.el (c-end-of-macro): Fix faulty cache handling, where the upper bound of c-macro-cache was never being set. (c-forward-comment-minus-1): New macro which terminates unwanted indefinite backward searching with lots of escaped newlines in c-backward-single-comment. (c-backward-single-comment, c-backward-comments): Use the new macro above. * lisp/progmodes/cc-mode.el (c-before-change-check-unbalanced-strings) (c-after-change-mark-abnormal-strings, c-after-change-escape-NL-in-string): Optimize three regexps by using shy groups, thus preventing regexp stack overflow while handling the large C Macro. --- lisp/progmodes/cc-engine.el | 23 +++++++++++++++++++---- lisp/progmodes/cc-mode.el | 8 ++++---- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el index aa3f7d399e9..8c8296fd6da 100644 --- a/lisp/progmodes/cc-engine.el +++ b/lisp/progmodes/cc-engine.el @@ -405,7 +405,7 @@ comment at the start of cc-engine.el for more info." (when (and (car c-macro-cache) (> (point) (car c-macro-cache)) ; in case we have a ; zero-sized region. - (not (eq (char-before (1- (point))) ?\\))) + (not lim)) (setcdr c-macro-cache (point)) (setq c-macro-cache-syntactic nil))))))) @@ -1642,6 +1642,21 @@ comment at the start of cc-engine.el for more info." (forward-char 2) t)))) +(defmacro c-forward-comment-minus-1 () + "Call (forward-comment -1), taking care of escaped newlines. +Return the result of `forward-comment' if it gets called, nil otherwise." + `(if (not comment-end-can-be-escaped) + (forward-comment -1) + (when (and (< (skip-syntax-backward " >") 0) + (eq (char-after) ?\n)) + (forward-char)) + (cond + ((and (eq (char-before) ?\n) + (eq (char-before (1- (point))) ?\\)) + (backward-char) + nil) + (t (forward-comment -1))))) + (defun c-backward-single-comment () "Move backward past whitespace and the closest preceding comment, if any. Return t if a comment was found, nil otherwise. In either case, the @@ -1675,12 +1690,12 @@ This function does not do any hidden buffer changes." ;; same line. (re-search-forward "\\=\\s *[\n\r]" start t) - (if (if (forward-comment -1) + (if (if (c-forward-comment-minus-1) (if (eolp) ;; If forward-comment above succeeded and we're at eol ;; then the newline we moved over above didn't end a ;; line comment, so we give it another go. - (forward-comment -1) + (c-forward-comment-minus-1) t)) ;; Emacs <= 20 and XEmacs move back over the closer of a @@ -1709,7 +1724,7 @@ comment at the start of cc-engine.el for more info." (if (let (moved-comment) (while - (and (not (setq moved-comment (forward-comment -1))) + (and (not (setq moved-comment (c-forward-comment-minus-1))) ;; Cope specifically with ^M^J here - ;; forward-comment sometimes gets stuck after ^Ms, ;; sometimes after ^M^J. diff --git a/lisp/progmodes/cc-mode.el b/lisp/progmodes/cc-mode.el index e3a924efb06..d822788bee2 100644 --- a/lisp/progmodes/cc-mode.el +++ b/lisp/progmodes/cc-mode.el @@ -1431,7 +1431,7 @@ Note that the style variables are always made local to the buffer." ;; Move to end of logical line (as it will be after the change, or as it ;; was before unescaping a NL.) - (re-search-forward "\\(\\\\\\(.\\|\n\\)\\|[^\\\n\r]\\)*" nil t) + (re-search-forward "\\(?:\\\\\\(?:.\\|\n\\)\\|[^\\\n\r]\\)*" nil t) ;; We're at an EOLL or point-max. (if (equal (c-get-char-property (point) 'syntax-table) '(15)) (if (memq (char-after) '(?\n ?\r)) @@ -1539,7 +1539,7 @@ Note that the style variables are always made local to the buffer." (progn (goto-char (min (1+ end) ; 1+, in case a NL has become escaped. (point-max))) - (re-search-forward "\\(\\\\\\(.\\|\n\\)\\|[^\\\n\r]\\)*" + (re-search-forward "\\(?:\\\\\\(?:.\\|\n\\)\\|[^\\\n\r]\\)*" nil t) (point)) c-new-END)) @@ -1620,8 +1620,8 @@ Note that the style variables are always made local to the buffer." (c-beginning-of-macro)))) (goto-char (1+ end)) ; After the \ ;; Search forward for EOLL - (setq lim (re-search-forward "\\(\\\\\\(.\\|\n\\)\\|[^\\\n\r]\\)*" - nil t)) + (setq lim (re-search-forward "\\(?:\\\\\\(?:.\\|\n\\)\\|[^\\\n\r]\\)*" + nil t)) (goto-char (1+ end)) (when (c-search-forward-char-property-with-value-on-char 'syntax-table '(15) ?\" lim) -- 2.39.2