From e43fa98a71d228475877a4b8d44b96e10c507ffa Mon Sep 17 00:00:00 2001 From: Alan Mackenzie Date: Sat, 6 Aug 2022 21:11:18 +0000 Subject: [PATCH] CC Mode: Optimize font-locking stanzas for long raw strings. Also replace some regexp searches which had caused regexp engine stack overflows with simple end-of-line calls. * lisp/progmodes/cc-fonts.el (c-make-syntactic-matcher) (c-make-font-lock-search-form): Start the generated functions with a skipping of comments and strings. (c-make-font-lock-BO-decl-search-function): Start the generated function with a (fast) movement to the start of any literal. * lisp/progmodes/cc-mode.el (c-before-change-check-unbalanced-strings) (c-after-change-mark-abnormal-strings): Replace complicated regexp searches for end of logical line with basic Lisp functions. --- lisp/progmodes/cc-fonts.el | 77 ++++++++++++++++++++------------------ lisp/progmodes/cc-mode.el | 11 ++++-- 2 files changed, 49 insertions(+), 39 deletions(-) diff --git a/lisp/progmodes/cc-fonts.el b/lisp/progmodes/cc-fonts.el index 625010b04b2..2495d21a10f 100644 --- a/lisp/progmodes/cc-fonts.el +++ b/lisp/progmodes/cc-fonts.el @@ -285,6 +285,7 @@ (byte-compile `(lambda (limit) (let (res) + (c-skip-comments-and-strings limit) (while (and (setq res (re-search-forward ,regexp limit t)) (progn (goto-char (match-beginning 0)) @@ -300,43 +301,45 @@ ;; with HIGHLIGHTS, a list of highlighters as specified on page ;; "Search-based Fontification" in the elisp manual. If CHECK-POINT ;; is non-nil, we will check (< (point) limit) in the main loop. - `(while - ,(if check-point - `(and (< (point) limit) - (re-search-forward ,regexp limit t)) - `(re-search-forward ,regexp limit t)) - (unless (progn - (goto-char (match-beginning 0)) - (c-skip-comments-and-strings limit)) - (goto-char (match-end 0)) - ,@(mapcar - (lambda (highlight) - (if (integerp (car highlight)) - ;; e.g. highlight is (1 font-lock-type-face t) - (progn - (unless (eq (nth 2 highlight) t) - (error - "The override flag must currently be t in %s" - highlight)) - (when (nth 3 highlight) - (error - "The laxmatch flag may currently not be set in %s" - highlight)) - `(save-match-data - (c-put-font-lock-face - (match-beginning ,(car highlight)) - (match-end ,(car highlight)) - ,(elt highlight 1)))) - ;; highlight is an "ANCHORED HIGHLIGHTER" of the form - ;; (ANCHORED-MATCHER PRE-FORM POST-FORM SUBEXP-HIGHLIGHTERS...) - (when (nth 3 highlight) - (error "Match highlights currently not supported in %s" + `(progn + (c-skip-comments-and-strings limit) + (while + ,(if check-point + `(and (< (point) limit) + (re-search-forward ,regexp limit t)) + `(re-search-forward ,regexp limit t)) + (unless (progn + (goto-char (match-beginning 0)) + (c-skip-comments-and-strings limit)) + (goto-char (match-end 0)) + ,@(mapcar + (lambda (highlight) + (if (integerp (car highlight)) + ;; e.g. highlight is (1 font-lock-type-face t) + (progn + (unless (eq (nth 2 highlight) t) + (error + "The override flag must currently be t in %s" + highlight)) + (when (nth 3 highlight) + (error + "The laxmatch flag may currently not be set in %s" highlight)) - `(progn - ,(nth 1 highlight) - (save-match-data ,(car highlight)) - ,(nth 2 highlight)))) - highlights)))) + `(save-match-data + (c-put-font-lock-face + (match-beginning ,(car highlight)) + (match-end ,(car highlight)) + ,(elt highlight 1)))) + ;; highlight is an "ANCHORED HIGHLIGHTER" of the form + ;; (ANCHORED-MATCHER PRE-FORM POST-FORM SUBEXP-HIGHLIGHTERS...) + (when (nth 3 highlight) + (error "Match highlights currently not supported in %s" + highlight)) + `(progn + ,(nth 1 highlight) + (save-match-data ,(car highlight)) + ,(nth 2 highlight)))) + highlights))))) (defun c-make-font-lock-search-function (regexp &rest highlights) ;; This function makes a byte compiled function that works much like @@ -416,6 +419,8 @@ ;; lambda more easily. (byte-compile `(lambda (limit) + (let ((lit-start (c-literal-start))) + (when lit-start (goto-char lit-start))) (let ( ;; The font-lock package in Emacs is known to clobber ;; `parse-sexp-lookup-properties' (when it exists). (parse-sexp-lookup-properties diff --git a/lisp/progmodes/cc-mode.el b/lisp/progmodes/cc-mode.el index 70fc1cb73a9..ca4df2d1c7e 100644 --- a/lisp/progmodes/cc-mode.el +++ b/lisp/progmodes/cc-mode.el @@ -1518,7 +1518,10 @@ 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) + (while + (progn (end-of-line) + (eq (char-before) ?\\)) + (forward-line)) ;; We're at an EOLL or point-max. (if (equal (c-get-char-property (point) 'syntax-table) '(15)) (if (memq (char-after) '(?\n ?\r)) @@ -1636,8 +1639,10 @@ Note that the style variables are always made local to the buffer." (min (1+ end) ; 1+, if we're inside an escaped NL. (point-max)) end)) - (re-search-forward "\\(?:\\\\\\(?:.\\|\n\\)\\|[^\\\n\r]\\)*" - nil t) + (while + (progn (end-of-line) + (eq (char-before) ?\\)) + (forward-line)) (point)) c-new-END)) s) -- 2.39.2