summaryrefslogtreecommitdiff
path: root/lisp
diff options
context:
space:
mode:
authorAlan Mackenzie <acm@muc.de>2016-02-29 21:51:32 +0000
committerAlan Mackenzie <acm@muc.de>2016-02-29 21:51:32 +0000
commit71dc8213b18d4baa5802cf6b7181d81f1f76cbdb (patch)
tree54831c443e29609d57d02ab4916b4d34a921350d /lisp
parent93bf7d52841c60ffc10e0c9c789a7987812ce55e (diff)
downloademacs-71dc8213b18d4baa5802cf6b7181d81f1f76cbdb.tar.gz
Handle "noise" macros and compiler directives.
* lisp/progmodes/cc-langs.el (c-symbol-char-key): New language variable. * lisp/progmodes/cc-vars.el (c-noise-macro-names) (c-noise-macro-with-parens-names): New customizable variables. (c-noise-macro-name-re, c-noise-macro-with-parens-name-re): New variables. (c-make-noise-macro-regexps): New function. * lisp/progmodes/cc-engine.el (c-forward-sws, c-backward-sws): Adapt to treat members of c-noise-macro-names as whitespace. (c-forward-noise-clause): New function. (c-forward-keyword-prefixed-id, c-forward-type, c-forward-declarator) (c-forward-decl-or-cast-1, c-backward-over-enum-header) (c-guess-basic-syntax CASE 5A.3, CASE 5A.5, CASE 9A): Handle "noise clauses" in parallel with, e.g., "hangon key clauses". * lisp/progmodes/cc-fonts.el (c-complex-decl-matchers): Handle "noise clauses" in parallel with "prefix-spec keywords". * lisp/progmodes/cc-mode.el (c-mode, c++-mode, objc-mode): call c-make-noise-macro-regexps to initialize the internal variables. * doc/misc/cc-mode.texi ("Noise Macros"): New section documenting the new facilities.
Diffstat (limited to 'lisp')
-rw-r--r--lisp/progmodes/cc-engine.el190
-rw-r--r--lisp/progmodes/cc-fonts.el16
-rw-r--r--lisp/progmodes/cc-langs.el5
-rw-r--r--lisp/progmodes/cc-mode.el3
-rw-r--r--lisp/progmodes/cc-vars.el43
5 files changed, 197 insertions, 60 deletions
diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el
index f5aa4df7c2b..66b5369bbba 100644
--- a/lisp/progmodes/cc-engine.el
+++ b/lisp/progmodes/cc-engine.el
@@ -1543,7 +1543,7 @@ comment at the start of cc-engine.el for more info."
;; two newlines with horizontal whitespace between them.
;;
;; The reason to include the first following char is to cope with
-;; "rung positions" that doesn't have any ordinary whitespace. If
+;; "rung positions" that don't have any ordinary whitespace. If
;; `c-is-sws' is put on a token character it does not have
;; `c-in-sws' set simultaneously. That's the only case when that
;; can occur, and the reason for not extending the `c-in-sws'
@@ -1714,7 +1714,9 @@ comment at the start of cc-engine.el for more info."
;; if it's anything that can't start syntactic ws, so we can bail out
;; early in the majority of cases when there just are a few ws chars.
(skip-chars-forward " \t\n\r\f\v")
- (when (looking-at c-syntactic-ws-start)
+ (when (or (looking-at c-syntactic-ws-start)
+ (and c-opt-cpp-prefix
+ (looking-at c-noise-macro-name-re)))
(setq rung-end-pos (min (1+ (point)) (point-max)))
(if (setq rung-is-marked (text-property-any rung-pos rung-end-pos
@@ -1733,6 +1735,10 @@ comment at the start of cc-engine.el for more info."
(with-silent-modifications
(while
(progn
+ ;; In the following while form, we move over a "ladder" and
+ ;; following simple WS each time round the loop, appending the WS
+ ;; onto the ladder, joining adjacent ladders, and terminating when
+ ;; there is no more WS or we reach EOB.
(while
(when (and rung-is-marked
(get-text-property (point) 'c-in-sws))
@@ -1776,6 +1782,7 @@ comment at the start of cc-engine.el for more info."
(setq rung-pos (point)
last-put-in-sws-pos rung-pos)))
+ ;; Now move over any comments (x)or a CPP construct.
(setq simple-ws-end (point))
(c-forward-comments)
@@ -1801,6 +1808,13 @@ comment at the start of cc-engine.el for more info."
(forward-line 1)
(setq safe-start t)
;; Don't cache at eob in case the buffer is narrowed.
+ (not (eobp)))
+
+ ((and c-opt-cpp-prefix
+ (looking-at c-noise-macro-name-re))
+ ;; Skip over a noise macro.
+ (goto-char (match-end 1))
+ (setq safe-start t)
(not (eobp)))))
;; We've searched over a piece of non-white syntactic ws. See if this
@@ -1907,8 +1921,11 @@ comment at the start of cc-engine.el for more info."
(when (and (not (bobp))
(save-excursion
(backward-char)
- (looking-at c-syntactic-ws-end)))
-
+ (or (looking-at c-syntactic-ws-end)
+ (and c-opt-cpp-prefix
+ (looking-at c-symbol-char-key)
+ (progn (c-beginning-of-current-token)
+ (looking-at c-noise-macro-name-re))))))
;; Try to find a rung position in the simple ws preceding point, so that
;; we can get a cache hit even if the last bit of the simple ws has
;; changed recently.
@@ -1927,6 +1944,9 @@ comment at the start of cc-engine.el for more info."
(with-silent-modifications
(while
(progn
+ ;; Each time round the next while form, we move back over a ladder
+ ;; and append any simple WS preceding it, if possible joining with
+ ;; the previous ladder.
(while
(when (and rung-is-marked
(not (bobp))
@@ -2035,6 +2055,15 @@ comment at the start of cc-engine.el for more info."
;; narrowed out, and we can't risk marking the simple ws
;; at the end of it.
(goto-char next-rung-pos)
+ t)
+
+ ((and c-opt-cpp-prefix
+ (save-excursion
+ (and (< (skip-syntax-backward "w_") 0)
+ (progn (setq next-rung-pos (point))
+ (looking-at c-noise-macro-name-re)))))
+ ;; Skipped over a noise macro
+ (goto-char next-rung-pos)
t)))
;; We've searched over a piece of non-white syntactic ws. See if this
@@ -5807,8 +5836,10 @@ comment at the start of cc-engine.el for more info."
`(c-forward-type)
`(c-forward-name)))
nil
- (and (looking-at c-keywords-regexp)
- (c-forward-keyword-clause 1))))
+ (cond ((looking-at c-keywords-regexp)
+ (c-forward-keyword-clause 1))
+ ((looking-at c-noise-macro-with-parens-name-re)
+ (c-forward-noise-clause)))))
(when (memq res '(t known found prefix))
,(when (eq type 'ref)
`(when c-record-type-identifiers
@@ -5830,6 +5861,17 @@ comment at the start of cc-engine.el for more info."
(c-forward-syntactic-ws)
(c-forward-keyword-prefixed-id ,type)))))
+(defun c-forward-noise-clause ()
+ ;; Point is at a c-noise-macro-with-parens-names macro identifier. Go
+ ;; forward over this name, any parenthesis expression which follows it, and
+ ;; any syntactic WS, ending up at the next token. If there is an unbalanced
+ ;; paren expression, leave point at it. Always Return t.
+ (c-forward-token-2)
+ (if (and (eq (char-after) ?\()
+ (c-go-list-forward))
+ (c-forward-syntactic-ws))
+ t)
+
(defun c-forward-keyword-clause (match)
;; Submatch MATCH in the current match data is assumed to surround a
;; token. If it's a keyword, move over it and any immediately
@@ -6460,6 +6502,13 @@ comment at the start of cc-engine.el for more info."
; "typedef".
(goto-char (match-end 1))
(c-forward-syntactic-ws)
+
+ (while (cond
+ ((looking-at c-decl-hangon-key)
+ (c-forward-keyword-clause 1))
+ ((looking-at c-noise-macro-with-parens-name-re)
+ (c-forward-noise-clause))))
+
(setq pos (point))
(setq name-res (c-forward-name))
@@ -6852,31 +6901,38 @@ comment at the start of cc-engine.el for more info."
;; of the while. These are, e.g. "*" in "int *foo" or "(" and
;; "*" in "int (*foo) (void)" (Note similar code in
;; `c-forward-decl-or-cast-1'.)
- (while (and (looking-at c-type-decl-prefix-key)
- (if (and (c-major-mode-is 'c++-mode)
- (match-beginning 3))
- ;; If the third submatch matches in C++ then
- ;; we're looking at an identifier that's a
- ;; prefix only if it specifies a member pointer.
- (progn
- (setq id-start (point))
- (c-forward-name)
- (if (looking-at "\\(::\\)")
- ;; We only check for a trailing "::" and
- ;; let the "*" that should follow be
- ;; matched in the next round.
- t
- ;; It turned out to be the real identifier,
- ;; so flag that and stop.
- (setq got-identifier t)
- nil))
- t))
- (if (eq (char-after) ?\()
- (progn
- (setq paren-depth (1+ paren-depth))
- (forward-char))
- (goto-char (match-end 1)))
- (c-forward-syntactic-ws))
+ (while
+ (cond
+ ((looking-at c-decl-hangon-key)
+ (c-forward-keyword-clause 1))
+ ((looking-at c-noise-macro-with-parens-name-re)
+ (c-forward-noise-clause))
+ ((and (looking-at c-type-decl-prefix-key)
+ (if (and (c-major-mode-is 'c++-mode)
+ (match-beginning 3))
+ ;; If the third submatch matches in C++ then
+ ;; we're looking at an identifier that's a
+ ;; prefix only if it specifies a member pointer.
+ (progn
+ (setq id-start (point))
+ (c-forward-name)
+ (if (looking-at "\\(::\\)")
+ ;; We only check for a trailing "::" and
+ ;; let the "*" that should follow be
+ ;; matched in the next round.
+ t
+ ;; It turned out to be the real identifier,
+ ;; so flag that and stop.
+ (setq got-identifier t)
+ nil))
+ t))
+ (if (eq (char-after) ?\()
+ (progn
+ (setq paren-depth (1+ paren-depth))
+ (forward-char))
+ (goto-char (match-end 1)))
+ (c-forward-syntactic-ws)
+ t)))
;; If we haven't passed the identifier already, do it now.
(unless got-identifier
@@ -6901,9 +6957,12 @@ comment at the start of cc-engine.el for more info."
;; Skip over any trailing bit, such as "__attribute__".
(progn
- (when (looking-at c-decl-hangon-key)
- (c-forward-keyword-clause 1))
- (<= (point) limit))
+ (while (cond
+ ((looking-at c-decl-hangon-key)
+ (c-forward-keyword-clause 1))
+ ((looking-at c-noise-macro-with-parens-name-re)
+ (c-forward-noise-clause))))
+ (<= (point) limit))
;; Search syntactically to the end of the declarator (";",
;; ",", a closing paren, eob etc) or to the beginning of an
@@ -7082,18 +7141,24 @@ comment at the start of cc-engine.el for more info."
;; macros like __INLINE__, so we recognize both types and known
;; specifiers after them too.
(while
- (let* ((start (point)) kwd-sym kwd-clause-end found-type)
+ (let* ((start (point)) kwd-sym kwd-clause-end found-type noise-start)
+ (cond
;; Look for a specifier keyword clause.
- (when (or (looking-at c-prefix-spec-kwds-re) ;FIXME!!! includes auto
- (and (c-major-mode-is 'java-mode)
- (looking-at "@[A-Za-z0-9]+")))
- (if (save-match-data (looking-at c-typedef-key))
- (setq at-typedef t))
+ ((or (looking-at c-prefix-spec-kwds-re)
+ (and (c-major-mode-is 'java-mode)
+ (looking-at "@[A-Za-z0-9]+")))
+ (save-match-data
+ (if (looking-at c-typedef-key)
+ (setq at-typedef t)))
(setq kwd-sym (c-keyword-sym (match-string 1)))
(save-excursion
(c-forward-keyword-clause 1)
(setq kwd-clause-end (point))))
+ ((looking-at c-noise-macro-with-parens-name-re)
+ (setq noise-start (point))
+ (c-forward-noise-clause)
+ (setq kwd-clause-end (point))))
(when (setq found-type (c-forward-type t)) ; brace-block-too
;; Found a known or possible type or a prefix of a known type.
@@ -7131,16 +7196,17 @@ comment at the start of cc-engine.el for more info."
backup-at-type-decl nil
backup-maybe-typeless nil))
- (if kwd-sym
+ (if (or kwd-sym noise-start)
(progn
;; Handle known specifier keywords and
;; `c-decl-hangon-kwds' which can occur after known
;; types.
- (if (c-keyword-member kwd-sym 'c-decl-hangon-kwds)
- ;; It's a hang-on keyword that can occur anywhere.
+ (if (or (c-keyword-member kwd-sym 'c-decl-hangon-kwds)
+ noise-start)
+ ;; It's a hang-on keyword or noise clause that can occur
+ ;; anywhere.
(progn
- (setq at-decl-or-cast t)
(if at-type
;; Move the identifier start position if
;; we've passed a type.
@@ -7192,8 +7258,11 @@ comment at the start of cc-engine.el for more info."
;; If a known type was found, we still need to skip over any
;; hangon keyword clauses after it. Otherwise it has already
;; been done in the loop above.
- (while (looking-at c-decl-hangon-key)
- (c-forward-keyword-clause 1))
+ (while
+ (cond ((looking-at c-decl-hangon-key)
+ (c-forward-keyword-clause 1))
+ ((looking-at c-noise-macro-with-parens-name-re)
+ (c-forward-noise-clause))))
(setq id-start (point)))
((eq at-type 'prefix)
@@ -8960,6 +9029,11 @@ comment at the start of cc-engine.el for more info."
t)
((looking-at c-after-brace-list-key) t)
((looking-at c-brace-list-key) nil)
+ ((eq (char-after) ?\()
+ (and (eq (c-backward-token-2) 0)
+ (or (looking-at c-decl-hangon-key)
+ (looking-at c-noise-macro-with-parens-name-re))))
+
((and c-recognize-<>-arglists
(eq (char-after) ?<)
(looking-at "\\s("))
@@ -10220,9 +10294,11 @@ comment at the start of cc-engine.el for more info."
;; CASE 5A.3: brace list open
((save-excursion
(c-beginning-of-decl-1 lim)
- (while (looking-at c-specifier-key)
- (goto-char (match-end 1))
- (c-forward-syntactic-ws indent-point))
+ (while (cond
+ ((looking-at c-specifier-key)
+ (c-forward-keyword-clause 1))
+ ((looking-at c-noise-macro-with-parens-name-re)
+ (c-forward-noise-clause))))
(setq placeholder (c-point 'boi))
(or (consp special-brace-list)
(and (or (save-excursion
@@ -10274,9 +10350,11 @@ comment at the start of cc-engine.el for more info."
(t
(save-excursion
(c-beginning-of-decl-1 lim)
- (while (looking-at c-specifier-key)
- (goto-char (match-end 1))
- (c-forward-syntactic-ws indent-point))
+ (while (cond
+ ((looking-at c-specifier-key)
+ (c-forward-keyword-clause 1))
+ ((looking-at c-noise-macro-with-parens-name-re)
+ (c-forward-noise-clause))))
(c-add-syntax 'defun-open (c-point 'boi))
;; Bogus to use bol here, but it's the legacy. (Resolved,
;; 2007-11-09)
@@ -10907,9 +10985,11 @@ comment at the start of cc-engine.el for more info."
(c-beginning-of-statement-1
(c-safe-position (1- containing-sexp) paren-state))
(c-forward-token-2 0)
- (while (looking-at c-specifier-key)
- (goto-char (match-end 1))
- (c-forward-syntactic-ws))
+ (while (cond
+ ((looking-at c-specifier-key)
+ (c-forward-keyword-clause 1))
+ ((looking-at c-noise-macro-with-parens-name-re)
+ (c-forward-noise-clause))))
(c-add-syntax 'brace-list-open (c-point 'boi))))
;; CASE 9B: brace-list-close brace
diff --git a/lisp/progmodes/cc-fonts.el b/lisp/progmodes/cc-fonts.el
index 3cc537bba3d..a7097b98c9d 100644
--- a/lisp/progmodes/cc-fonts.el
+++ b/lisp/progmodes/cc-fonts.el
@@ -1698,10 +1698,16 @@ on level 2 only and so aren't combined with `c-complex-decl-matchers'."
(unless (c-skip-comments-and-strings limit)
(c-forward-syntactic-ws)
;; Handle prefix declaration specifiers.
- (when (or (looking-at c-prefix-spec-kwds-re)
- (and (c-major-mode-is 'java-mode)
- (looking-at "@[A-Za-z0-9]+")))
- (c-forward-keyword-clause 1))
+ (while
+ (or
+ (when (or (looking-at c-prefix-spec-kwds-re)
+ (and (c-major-mode-is 'java-mode)
+ (looking-at "@[A-Za-z0-9]+")))
+ (c-forward-keyword-clause 1)
+ t)
+ (when (looking-at c-noise-macro-with-parens-name-re)
+ (c-forward-noise-clause)
+ t)))
,(if (c-major-mode-is 'c++-mode)
`(when (and (c-forward-type)
(eq (char-after) ?=))
@@ -1827,7 +1833,7 @@ higher."
"\\)\\>"
;; Disallow various common punctuation chars that can't come
;; before the '{' of the enum list, to avoid searching too far.
- "[^][{}();/#=]*"
+ "[^][{};/#=]*"
"{")
'((c-font-lock-declarators limit t nil)
(save-match-data
diff --git a/lisp/progmodes/cc-langs.el b/lisp/progmodes/cc-langs.el
index 86b6bec78a1..d212482790d 100644
--- a/lisp/progmodes/cc-langs.el
+++ b/lisp/progmodes/cc-langs.el
@@ -619,6 +619,11 @@ This is of the form that fits inside [ ] in a regexp."
objc (concat c-alnum "_$@"))
(c-lang-defvar c-symbol-chars (c-lang-const c-symbol-chars))
+(c-lang-defconst c-symbol-char-key
+ "Regexp matching a sequence of at least one identifier character."
+ t (concat "[" (c-lang-const c-symbol-chars) "]+"))
+(c-lang-defvar c-symbol-char-key (c-lang-const c-symbol-char-key))
+
(c-lang-defconst c-symbol-key
"Regexp matching identifiers and keywords (with submatch 0). Assumed
to match if `c-symbol-start' matches on the same position."
diff --git a/lisp/progmodes/cc-mode.el b/lisp/progmodes/cc-mode.el
index 58aebf8b410..9ebe6f79eb3 100644
--- a/lisp/progmodes/cc-mode.el
+++ b/lisp/progmodes/cc-mode.el
@@ -1493,6 +1493,7 @@ Key bindings:
abbrev-mode t)
(use-local-map c-mode-map)
(c-init-language-vars-for 'c-mode)
+ (c-make-noise-macro-regexps)
(c-make-macro-with-semi-re) ; matches macro names whose expansion ends with ;
(c-common-init 'c-mode)
(easy-menu-add c-c-menu)
@@ -1548,6 +1549,7 @@ Key bindings:
abbrev-mode t)
(use-local-map c++-mode-map)
(c-init-language-vars-for 'c++-mode)
+ (c-make-noise-macro-regexps)
(c-make-macro-with-semi-re) ; matches macro names whose expansion ends with ;
(c-common-init 'c++-mode)
(easy-menu-add c-c++-menu)
@@ -1601,6 +1603,7 @@ Key bindings:
abbrev-mode t)
(use-local-map objc-mode-map)
(c-init-language-vars-for 'objc-mode)
+ (c-make-noise-macro-regexps)
(c-make-macro-with-semi-re) ; matches macro names whose expansion ends with ;
(c-common-init 'objc-mode)
(easy-menu-add c-objc-menu)
diff --git a/lisp/progmodes/cc-vars.el b/lisp/progmodes/cc-vars.el
index 8cee733ec8e..a6957185a2b 100644
--- a/lisp/progmodes/cc-vars.el
+++ b/lisp/progmodes/cc-vars.el
@@ -1619,6 +1619,49 @@ names)."))
:type 'c-extra-types-widget
:group 'c)
+(defvar c-noise-macro-with-parens-name-re nil)
+(defvar c-noise-macro-name-re nil)
+
+(defcustom c-noise-macro-names nil
+ "A list of names of macros which expand to nothing, or compiler extensions
+like \"????\" which are syntactic noise. Such a macro/extension is complete in
+itself, never having parentheses. All these names must be syntactically valid
+identifiers.
+
+If you change this variable's value, call the function
+`c-make-noise-macro-regexps' to set the necessary internal variables (or do
+this implicitly by reinitialising C/C++/Objc Mode on any buffer)."
+ :type '(repeat :tag "List of names" string)
+ :group 'c)
+
+(defcustom c-noise-macro-with-parens-names nil
+ "A list of names of macros \(or compiler extensions like \"__attribute__\")
+which optionally have arguments in parentheses, and which expand to nothing.
+These are recognized by CC Mode only in declarations."
+ :type '(regexp :tag "List of names (possibly empty)" string)
+ :group 'c)
+
+(defun c-make-noise-macro-regexps ()
+ ;; Convert `c-noise-macro-names' and `c-noise-macro-with-parens-names' into
+ ;; `c-noise-macro-name-re' and `c-noise-macro-with-parens-name-re'.
+ (setq c-noise-macro-with-parens-name-re
+ (cond ((null c-noise-macro-with-parens-names) "\\<\\>")
+ ((consp c-noise-macro-with-parens-names)
+ (concat (regexp-opt c-noise-macro-with-parens-names t)
+ "\\([^[:alnum:]_$]\\|$\\)"))
+ ((stringp c-noise-macro-with-parens-names)
+ (copy-sequence c-noise-macro-with-parens-names))
+ (t (error "c-make-noise-macro-regexps: \
+c-noise-macro-with-parens-names is invalid: %s" c-noise-macro-with-parens-names))))
+ (setq c-noise-macro-name-re
+ (cond ((null c-noise-macro-names) "\\<\\>")
+ ((consp c-noise-macro-names)
+ (concat (regexp-opt c-noise-macro-names t)
+ "\\([^[:alnum:]_$]\\|$\\)"))
+ ((stringp c-noise-macro-names)
+ (copy-sequence c-noise-macro-names))
+ (t (error "c-make-noise-macro-regexps: \
+c-noise-macro-names is invalid: %s" c-noise-macro-names)))))
;; Non-customizable variables, still part of the interface to CC Mode
(defvar c-macro-with-semi-re nil