From 39acaff574140b67ef5311c5764a6b3b29491991 Mon Sep 17 00:00:00 2001 From: Alan Mackenzie Date: Thu, 2 May 2019 14:30:29 +0000 Subject: CC Mode: Fix multiline block comments in macros. In particulr, handle multiline block comments whose newlines are not escaped. There is an example of this in #define EXTRA_CONTEXT_FIELDS in editfns.c. * lisp/progmodes/cc-engine.el (c-beginning-of-macro, c-end-of-macro): Enclose the loops scanning escaped newlines with outer loops which check heuristically for, respectively, a block comment ender and a block comment starter on the lines we end up on. (A rigorous syntactic check would be too slow, here.) * lisp/progmodes/cc-langs.el (c-last-c-comment-end-on-line-re) (c-last-open-c-comment-start-on-line-re): New language constants/variables. --- lisp/progmodes/cc-engine.el | 49 ++++++++++++++++++++++++++++++++++++--------- lisp/progmodes/cc-langs.el | 20 ++++++++++++++++++ 2 files changed, 60 insertions(+), 9 deletions(-) diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el index a0459b9f2ae..f9e570e9f3f 100644 --- a/lisp/progmodes/cc-engine.el +++ b/lisp/progmodes/cc-engine.el @@ -287,7 +287,8 @@ otherwise return nil and leave point unchanged. Note that this function might do hidden buffer changes. See the comment at the start of cc-engine.el for more info." - (let ((here (point))) + (let ((here (point)) + (pause (c-point 'eol))) (when c-opt-cpp-prefix (if (and (car c-macro-cache) (>= (point) (car c-macro-cache)) @@ -307,8 +308,23 @@ comment at the start of cc-engine.el for more info." (save-restriction (if lim (narrow-to-region lim (point-max))) (beginning-of-line) - (while (eq (char-before (1- (point))) ?\\) - (forward-line -1)) + (when (or (null lim) + (>= here lim)) + (while + (progn + (while (eq (char-before (1- (point))) ?\\) + (forward-line -1)) + (when (and c-last-c-comment-end-on-line-re + (re-search-forward + c-last-c-comment-end-on-line-re pause t)) + (goto-char (match-end 1)) + (if (c-backward-single-comment) + (progn + (beginning-of-line) + (setq pause (point))) + (goto-char pause) + nil))))) + (back-to-indentation) (if (and (<= (point) here) (save-match-data (looking-at c-opt-cpp-start)) @@ -345,12 +361,23 @@ comment at the start of cc-engine.el for more info." c-macro-cache-start-pos nil c-macro-cache-syntactic nil c-macro-cache-no-comment nil)) - (while (progn - (end-of-line) - (when (and (eq (char-before) ?\\) - (not (eobp))) - (forward-char) - t))) + (while + (progn + (while (progn + (end-of-line) + (when (and (eq (char-before) ?\\) + (not (eobp))) + (forward-char) + t))) + (if (and c-last-open-c-comment-start-on-line-re + (re-search-backward + c-last-open-c-comment-start-on-line-re + (c-point 'bol) t)) + (progn + (goto-char (match-beginning 1)) + (c-forward-single-comment)) + nil))) + (when (and (car c-macro-cache) (bolp) (not (eq (char-before (1- (point))) ?\\))) @@ -2007,6 +2034,10 @@ comment at the start of cc-engine.el for more info." ;; Take elaborate precautions to detect an open block comment at ;; the end of a macro. If we find one, we set `safe-start' to nil ;; and break off any further scanning of comments. + ;; + ;; (2019-05-02): `c-end-of-macro' now moves completely over block + ;; comments, even multiline ones lacking \s at their EOLs. So a + ;; lot of the following is probably redundant now. (let ((com-begin (point)) com-end in-macro) (when (and (c-forward-single-comment) (setq com-end (point)) diff --git a/lisp/progmodes/cc-langs.el b/lisp/progmodes/cc-langs.el index 50f8b8473be..00c581a06a9 100644 --- a/lisp/progmodes/cc-langs.el +++ b/lisp/progmodes/cc-langs.el @@ -1589,6 +1589,26 @@ properly." (c-lang-defvar c-line-comment-start-regexp (c-lang-const c-line-comment-start-regexp)) +(c-lang-defconst c-last-c-comment-end-on-line-re + "Regexp which matches the last block comment ender on the +current line, if any, or nil in those languages without block +comments. When a match is found, submatch 1 contains the comment +ender." + t "\\(\\*/\\)\\([^*]\\|\\*[^/]\\)*$" + awk nil) +(c-lang-defvar c-last-c-comment-end-on-line-re + (c-lang-const c-last-c-comment-end-on-line-re)) + +(c-lang-defconst c-last-open-c-comment-start-on-line-re + "Regexp which matches the last block comment start on the +current ine, if any, or nil in those languages without block +comments. When a match is found, submatch 1 contains the comment +starter." + t "\\(/\\*\\)\\([^*]\\|\\*[^/]\\)*$" + awk nil) +(c-lang-defvar c-last-open-c-comment-start-on-line-re + (c-lang-const c-last-open-c-comment-start-on-line-re)) + (c-lang-defconst c-literal-start-regexp ;; Regexp to match the start of comments and string literals. t (concat (c-lang-const c-comment-start-regexp) -- cgit v1.2.1