mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-01-08 12:40:49 -08:00
Fontify bitfield declarations properly.
cc-langs.el (c-has-bitfields): New lang variable. (c-symbol-chars): Now exported as a lang variable. (c-not-primitive-type-keywords): New lang variable. cc-fonts.el (c-font-lock-declarations): Jump over the QT keyword "more" to prevent "more slots: ...." being spuriously parsed as a bitfield declaraion. cc-engine.el (c-beginning-of-statement-1): Refactor and enhance to handle bitfield declarations. (c-punctuation-in): New function. (c-forward-decl-or-cast-1): Enhance CASE 3 to handle bitfield declarations properly.
This commit is contained in:
parent
68575ab00b
commit
b248a85d10
4 changed files with 180 additions and 95 deletions
|
|
@ -1,3 +1,21 @@
|
|||
2011-07-26 Alan Mackenzie <acm@muc.de>
|
||||
|
||||
Fontify bitfield declarations properly.
|
||||
|
||||
* progmodes/cc-langs.el (c-has-bitfields): New lang variable.
|
||||
(c-symbol-chars): Now exported as a lang variable.
|
||||
(c-not-primitive-type-keywords): New lang variable.
|
||||
|
||||
* progmodes/cc-fonts.el (c-font-lock-declarations): Jump over the
|
||||
QT keyword "more" to prevent "more slots: ...." being spuriously
|
||||
parsed as a bitfield declaraion.
|
||||
|
||||
* progmodes/cc-engine.el (c-beginning-of-statement-1): Refactor
|
||||
and enhance to handle bitfield declarations.
|
||||
(c-punctuation-in): New function.
|
||||
(c-forward-decl-or-cast-1): Enhance CASE 3 to handle bitfield
|
||||
declarations properly.
|
||||
|
||||
2011-07-26 Ulf Jasper <ulf.jasper@web.de>
|
||||
|
||||
* calendar/icalendar.el (icalendar--all-events): Take care of
|
||||
|
|
|
|||
|
|
@ -709,6 +709,9 @@ comment at the start of cc-engine.el for more info."
|
|||
;; content was found in the label. Note that we might still
|
||||
;; regard it a label if it starts with `c-label-kwds'.
|
||||
label-good-pos
|
||||
;; Putative positions of the components of a bitfield declaration,
|
||||
;; e.g. "int foo : NUM_FOO_BITS ;"
|
||||
bitfield-type-pos bitfield-id-pos bitfield-size-pos
|
||||
;; Symbol just scanned back over (e.g. 'while or 'boundary).
|
||||
;; See above.
|
||||
sym
|
||||
|
|
@ -765,13 +768,22 @@ comment at the start of cc-engine.el for more info."
|
|||
;; Record this as the first token if not starting inside it.
|
||||
(setq tok start))
|
||||
|
||||
;; The following while loop goes back one sexp (balanced parens,
|
||||
;; etc. with contents, or symbol or suchlike) each iteration. This
|
||||
;; movement is accomplished with a call to scan-sexps approx 130 lines
|
||||
;; below.
|
||||
|
||||
;; The following while loop goes back one sexp (balanced parens,
|
||||
;; etc. with contents, or symbol or suchlike) each iteration. This
|
||||
;; movement is accomplished with a call to c-backward-sexp approx 170
|
||||
;; lines below.
|
||||
;;
|
||||
;; The loop is exited only by throwing nil to the (catch 'loop ...):
|
||||
;; 1. On reaching the start of a macro;
|
||||
;; 2. On having passed a stmt boundary with the PDA stack empty;
|
||||
;; 3. On reaching the start of an Objective C method def;
|
||||
;; 4. From macro `c-bos-pop-state'; when the stack is empty;
|
||||
;; 5. From macro `c-bos-pop-state-and-retry' when the stack is empty.
|
||||
(while
|
||||
(catch 'loop ;; Throw nil to break, non-nil to continue.
|
||||
(cond
|
||||
;; Are we in a macro, just after the opening #?
|
||||
((save-excursion
|
||||
(and macro-start ; Always NIL for AWK.
|
||||
(progn (skip-chars-backward " \t")
|
||||
|
|
@ -792,7 +804,7 @@ comment at the start of cc-engine.el for more info."
|
|||
(setq pos saved
|
||||
ret 'macro
|
||||
ignore-labels t))
|
||||
(throw 'loop nil))
|
||||
(throw 'loop nil)) ; 1. Start of macro.
|
||||
|
||||
;; Do a round through the automaton if we've just passed a
|
||||
;; statement boundary or passed a "while"-like token.
|
||||
|
|
@ -801,7 +813,7 @@ comment at the start of cc-engine.el for more info."
|
|||
(setq sym (intern (match-string 1)))))
|
||||
|
||||
(when (and (< pos start) (null stack))
|
||||
(throw 'loop nil))
|
||||
(throw 'loop nil)) ; 2. Statement boundary.
|
||||
|
||||
;; The PDA state handling.
|
||||
;;
|
||||
|
|
@ -918,19 +930,14 @@ comment at the start of cc-engine.el for more info."
|
|||
;; HERE IS THE SINGLE PLACE INSIDE THE PDA LOOP WHERE WE MOVE
|
||||
;; BACKWARDS THROUGH THE SOURCE.
|
||||
|
||||
;; This is typically fast with the caching done by
|
||||
;; c-(backward|forward)-sws.
|
||||
(c-backward-syntactic-ws)
|
||||
|
||||
(let ((before-sws-pos (point))
|
||||
;; Set as long as we have to continue jumping by sexps.
|
||||
;; It's the position to use as end in the next round.
|
||||
sexp-loop-continue-pos
|
||||
;; The end position of the area to search for statement
|
||||
;; barriers in this round.
|
||||
(sexp-loop-end-pos pos))
|
||||
(maybe-after-boundary-pos pos))
|
||||
|
||||
;; The following while goes back one sexp per iteration.
|
||||
;; Go back over exactly one logical sexp, taking proper
|
||||
;; account of macros and escaped EOLs.
|
||||
(while
|
||||
(progn
|
||||
(unless (c-safe (c-backward-sexp) t)
|
||||
|
|
@ -938,81 +945,87 @@ comment at the start of cc-engine.el for more info."
|
|||
;; stack won't be empty the code below will report a
|
||||
;; suitable error.
|
||||
(throw 'loop nil))
|
||||
(cond
|
||||
;; Have we moved into a macro?
|
||||
((and (not macro-start)
|
||||
(c-beginning-of-macro))
|
||||
;; Have we crossed a statement boundary? If not,
|
||||
;; keep going back until we find one or a "real" sexp.
|
||||
(and
|
||||
(save-excursion
|
||||
(c-end-of-macro)
|
||||
(not (c-crosses-statement-barrier-p
|
||||
(point) maybe-after-boundary-pos)))
|
||||
(setq maybe-after-boundary-pos (point))))
|
||||
;; Have we just gone back over an escaped NL? This
|
||||
;; doesn't count as a sexp.
|
||||
((looking-at "\\\\$")))))
|
||||
|
||||
;; Check if the sexp movement crossed a statement or
|
||||
;; declaration boundary. But first modify the point
|
||||
;; so that `c-crosses-statement-barrier-p' only looks
|
||||
;; at the non-sexp chars following the sexp.
|
||||
(save-excursion
|
||||
(when (setq
|
||||
boundary-pos
|
||||
(cond
|
||||
((if macro-start
|
||||
nil
|
||||
(save-excursion
|
||||
(when (c-beginning-of-macro)
|
||||
;; Set continuation position in case
|
||||
;; `c-crosses-statement-barrier-p'
|
||||
;; doesn't detect anything below.
|
||||
(setq sexp-loop-continue-pos (point)))))
|
||||
;; If the sexp movement took us into a
|
||||
;; macro then there were only some non-sexp
|
||||
;; chars after it. Skip out of the macro
|
||||
;; to analyze them but not the non-sexp
|
||||
;; chars that might be inside the macro.
|
||||
(c-end-of-macro)
|
||||
(c-crosses-statement-barrier-p
|
||||
(point) sexp-loop-end-pos))
|
||||
|
||||
((and
|
||||
(eq (char-after) ?{)
|
||||
(not (c-looking-at-inexpr-block lim nil t)))
|
||||
;; Passed a block sexp. That's a boundary
|
||||
;; alright.
|
||||
(point))
|
||||
|
||||
((looking-at "\\s\(")
|
||||
;; Passed some other paren. Only analyze
|
||||
;; the non-sexp chars after it.
|
||||
(goto-char (1+ (c-down-list-backward
|
||||
before-sws-pos)))
|
||||
;; We're at a valid token start position
|
||||
;; (outside the `save-excursion') if
|
||||
;; `c-crosses-statement-barrier-p' failed.
|
||||
(c-crosses-statement-barrier-p
|
||||
(point) sexp-loop-end-pos))
|
||||
|
||||
(t
|
||||
;; Passed a symbol sexp or line
|
||||
;; continuation. It doesn't matter that
|
||||
;; it's included in the analyzed region.
|
||||
(if (c-crosses-statement-barrier-p
|
||||
(point) sexp-loop-end-pos)
|
||||
t
|
||||
;; If it was a line continuation then we
|
||||
;; have to continue looping.
|
||||
(if (looking-at "\\\\$")
|
||||
(setq sexp-loop-continue-pos (point)))
|
||||
nil))))
|
||||
|
||||
(setq pptok ptok
|
||||
ptok tok
|
||||
tok boundary-pos
|
||||
sym 'boundary)
|
||||
;; Like a C "continue". Analyze the next sexp.
|
||||
(throw 'loop t)))
|
||||
|
||||
sexp-loop-continue-pos) ; End of "go back a sexp" loop condition.
|
||||
(goto-char sexp-loop-continue-pos)
|
||||
(setq sexp-loop-end-pos sexp-loop-continue-pos
|
||||
sexp-loop-continue-pos nil))))
|
||||
;; Have we crossed a statement boundary?
|
||||
(setq boundary-pos
|
||||
(cond
|
||||
;; Are we at a macro beginning?
|
||||
((and (not macro-start)
|
||||
c-opt-cpp-prefix
|
||||
(looking-at c-opt-cpp-prefix))
|
||||
(save-excursion
|
||||
(c-end-of-macro)
|
||||
(c-crosses-statement-barrier-p
|
||||
(point) maybe-after-boundary-pos)))
|
||||
;; Just gone back over a brace block?
|
||||
((and
|
||||
(eq (char-after) ?{)
|
||||
(not (c-looking-at-inexpr-block lim nil t)))
|
||||
(save-excursion
|
||||
(c-forward-sexp) (point)))
|
||||
;; Just gone back over some paren block?
|
||||
((looking-at "\\s\(")
|
||||
(save-excursion
|
||||
(goto-char (1+ (c-down-list-backward
|
||||
before-sws-pos)))
|
||||
(c-crosses-statement-barrier-p
|
||||
(point) maybe-after-boundary-pos)))
|
||||
;; Just gone back over an ordinary symbol of some sort?
|
||||
(t (c-crosses-statement-barrier-p
|
||||
(point) maybe-after-boundary-pos))))
|
||||
|
||||
(when boundary-pos
|
||||
(setq pptok ptok
|
||||
ptok tok
|
||||
tok boundary-pos
|
||||
sym 'boundary)
|
||||
;; Like a C "continue". Analyze the next sexp.
|
||||
(throw 'loop t))))
|
||||
|
||||
;; ObjC method def?
|
||||
(when (and c-opt-method-key
|
||||
(setq saved (c-in-method-def-p)))
|
||||
(setq pos saved
|
||||
ignore-labels t) ; Avoid the label check on exit.
|
||||
(throw 'loop nil))
|
||||
(throw 'loop nil)) ; 3. ObjC method def.
|
||||
|
||||
;; Might we have a bitfield declaration, "<type> <id> : <size>"?
|
||||
(if c-has-bitfields
|
||||
(cond
|
||||
;; The : <size> and <id> fields?
|
||||
((and (numberp c-maybe-labelp)
|
||||
(not bitfield-size-pos)
|
||||
(save-excursion
|
||||
(goto-char (or tok start))
|
||||
(not (looking-at c-keywords-regexp)))
|
||||
(not (looking-at c-keywords-regexp))
|
||||
(not (c-punctuation-in (point) c-maybe-labelp)))
|
||||
(setq bitfield-size-pos (or tok start)
|
||||
bitfield-id-pos (point)))
|
||||
;; The <type> field?
|
||||
((and bitfield-id-pos
|
||||
(not bitfield-type-pos))
|
||||
(if (and (looking-at c-symbol-key) ; Can only be an integer type. :-)
|
||||
(not (looking-at c-not-primitive-type-keywords-regexp))
|
||||
(not (c-punctuation-in (point) tok)))
|
||||
(setq bitfield-type-pos (point))
|
||||
(setq bitfield-size-pos nil
|
||||
bitfield-id-pos nil)))))
|
||||
|
||||
;; Handle labels.
|
||||
(unless (eq ignore-labels t)
|
||||
|
|
@ -1044,8 +1057,10 @@ comment at the start of cc-engine.el for more info."
|
|||
pptok ptok
|
||||
ptok tok
|
||||
tok (point)
|
||||
pos tok))) ; Not nil (for the while loop).
|
||||
|
||||
pos tok) ; always non-nil
|
||||
) ; end of (catch loop ....)
|
||||
) ; end of sexp-at-a-time (while ....)
|
||||
|
||||
;; If the stack isn't empty there might be errors to report.
|
||||
(while stack
|
||||
(if (and (vectorp saved-pos) (eq (length saved-pos) 3))
|
||||
|
|
@ -1067,6 +1082,7 @@ comment at the start of cc-engine.el for more info."
|
|||
(eq c-maybe-labelp t)
|
||||
(not (eq ret 'beginning))
|
||||
after-labels-pos
|
||||
(not bitfield-type-pos) ; Bitfields take precedence over labels.
|
||||
(or (not label-good-pos)
|
||||
(<= label-good-pos pos)
|
||||
(progn
|
||||
|
|
@ -1104,6 +1120,19 @@ comment at the start of cc-engine.el for more info."
|
|||
(goto-char pos)
|
||||
ret)))
|
||||
|
||||
(defun c-punctuation-in (from to)
|
||||
"Return non-nil if there is a non-comment non-macro punctuation character
|
||||
between FROM and TO. FROM must not be in a string or comment. The returned
|
||||
value is the position of the first such character."
|
||||
(save-excursion
|
||||
(goto-char from)
|
||||
(let ((pos (point)))
|
||||
(while (progn (skip-chars-forward c-symbol-chars to)
|
||||
(c-forward-syntactic-ws to)
|
||||
(> (point) pos))
|
||||
(setq pos (point))))
|
||||
(and (< (point) to) (point))))
|
||||
|
||||
(defun c-crosses-statement-barrier-p (from to)
|
||||
"Return non-nil if buffer positions FROM to TO cross one or more
|
||||
statement or declaration boundaries. The returned value is actually
|
||||
|
|
@ -6618,19 +6647,27 @@ comment at the start of cc-engine.el for more info."
|
|||
(if backup-at-type
|
||||
(progn
|
||||
|
||||
;; CASE 3
|
||||
(when (= (point) start)
|
||||
;; Got a plain list of identifiers. If a colon follows it's
|
||||
;; a valid label. Otherwise the last one probably is the
|
||||
;; declared identifier and we should back up to the previous
|
||||
;; type, providing it isn't a cast.
|
||||
|
||||
;; CASE 3
|
||||
(when (= (point) start)
|
||||
;; Got a plain list of identifiers. If a colon follows it's
|
||||
;; a valid label, or maybe a bitfield. Otherwise the last
|
||||
;; one probably is the declared identifier and we should
|
||||
;; back up to the previous type, providing it isn't a cast.
|
||||
(if (and (eq (char-after) ?:)
|
||||
(not (c-major-mode-is 'java-mode)))
|
||||
;; If we've found a specifier keyword then it's a
|
||||
;; declaration regardless.
|
||||
(throw 'at-decl-or-cast (eq at-decl-or-cast t))
|
||||
(setq backup-if-not-cast t)
|
||||
(throw 'at-decl-or-cast t)))
|
||||
(cond
|
||||
;; If we've found a specifier keyword then it's a
|
||||
;; declaration regardless.
|
||||
((eq at-decl-or-cast t)
|
||||
(throw 'at-decl-or-cast t))
|
||||
((and c-has-bitfields
|
||||
(eq at-decl-or-cast 'ids)) ; bitfield.
|
||||
(setq backup-if-not-cast t)
|
||||
(throw 'at-decl-or-cast t)))
|
||||
|
||||
(setq backup-if-not-cast t)
|
||||
(throw 'at-decl-or-cast t)))
|
||||
|
||||
;; CASE 4
|
||||
(when (and got-suffix
|
||||
|
|
|
|||
|
|
@ -1179,6 +1179,14 @@ casts and declarations are fontified. Used on level 2 and higher."
|
|||
(goto-char start-pos)))
|
||||
|
||||
;; Now analyze the construct.
|
||||
;; In QT, "more" is an irritating keyword that expands to nothing.
|
||||
;; We skip over it to prevent recognition of "more slots: <symbol>"
|
||||
;; as a bitfield declaration.
|
||||
(when (and (c-major-mode-is 'c++-mode)
|
||||
(looking-at
|
||||
(concat "\\(more\\)\\([^" c-symbol-chars "]\\|$\\)")))
|
||||
(goto-char (match-end 1))
|
||||
(c-forward-syntactic-ws))
|
||||
(setq decl-or-cast (c-forward-decl-or-cast-1
|
||||
match-pos context last-cast-end))
|
||||
|
||||
|
|
|
|||
|
|
@ -511,6 +511,12 @@ parameters \(point-min), \(point-max) and <buffer size>."
|
|||
|
||||
;;; Lexer-level syntax (identifiers, tokens etc).
|
||||
|
||||
(c-lang-defconst c-has-bitfields
|
||||
"Whether the language has bitfield declarations."
|
||||
t nil
|
||||
(c c++ objc) t)
|
||||
(c-lang-defvar c-has-bitfields (c-lang-const c-has-bitfields))
|
||||
|
||||
(c-lang-defconst c-symbol-start
|
||||
"Regexp that matches the start of a symbol, i.e. any identifier or
|
||||
keyword. It's unspecified how far it matches. Does not contain a \\|
|
||||
|
|
@ -528,6 +534,7 @@ This is of the form that fits inside [ ] in a regexp."
|
|||
;; operator chars too, but they are handled with other means instead.
|
||||
t (concat c-alnum "_$")
|
||||
objc (concat c-alnum "_$@"))
|
||||
(c-lang-defvar c-symbol-chars (c-lang-const c-symbol-chars))
|
||||
|
||||
(c-lang-defconst c-symbol-key
|
||||
"Regexp matching identifiers and keywords (with submatch 0). Assumed
|
||||
|
|
@ -1927,6 +1934,21 @@ one of `c-type-list-kwds', `c-ref-list-kwds',
|
|||
(c-lang-defvar c-not-decl-init-keywords
|
||||
(c-lang-const c-not-decl-init-keywords))
|
||||
|
||||
(c-lang-defconst c-not-primitive-type-keywords
|
||||
"List of all keywords apart from primitive types (like \"int\")."
|
||||
t (set-difference (c-lang-const c-keywords)
|
||||
(c-lang-const c-primitive-type-kwds)
|
||||
:test 'string-equal)
|
||||
;; The "more" for C++ is the QT keyword (as in "more slots:").
|
||||
;; This variable is intended for use in c-beginning-of-statement-1.
|
||||
c++ (append (c-lang-const c-not-primitive-type-keywords) '("more")))
|
||||
|
||||
(c-lang-defconst c-not-primitive-type-keywords-regexp
|
||||
t (c-make-keywords-re t
|
||||
(c-lang-const c-not-primitive-type-keywords)))
|
||||
(c-lang-defvar c-not-primitive-type-keywords-regexp
|
||||
(c-lang-const c-not-primitive-type-keywords-regexp))
|
||||
|
||||
(c-lang-defconst c-protection-kwds
|
||||
"Access protection label keywords in classes."
|
||||
t nil
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue