;;; cc-fonts.el --- font lock support for CC Mode
-;; Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2011 Free Software Foundation, Inc.
;; Authors: 2003- Alan Mackenzie
;; 2002- Martin Stjernholm
(set-face-foreground 'c-annotation-face "blue")
(eval-and-compile
- ;; We need the following functions during compilation since they're
- ;; called when the `c-lang-defconst' initializers are evaluated.
- ;; Define them at runtime too for the sake of derived modes.
+ ;; We need the following definitions during compilation since they're
+ ;; used when the `c-lang-defconst' initializers are evaluated. Define
+ ;; them at runtime too for the sake of derived modes.
+
+ ;; This indicates the "font locking context", and is set just before
+ ;; fontification is done. If non-nil, it says, e.g., point starts
+ ;; from within a #if preprocessor construct.
+ (defvar c-font-lock-context nil)
+ (make-variable-buffer-local 'c-font-lock-context)
(defmacro c-put-font-lock-face (from to face)
;; Put a face on a region (overriding any existing face) in the way
nil)))))
res))))
+ (defun c-make-font-lock-search-form (regexp highlights)
+ ;; Return a lisp form which will fontify every occurrence of REGEXP
+ ;; (a regular expression, NOT a function) between POINT and `limit'
+ ;; with HIGHLIGHTS, a list of highlighters as specified on page
+ ;; "Search-based Fontification" in the elisp manual.
+ `(while (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"
+ 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
;; a matcher element in `font-lock-keywords'. It cuts out a little
;; bit of the overhead compared to a real matcher. The main reason
;; is however to pass the real search limit to the anchored
;; matcher(s), since most (if not all) font-lock implementations
- ;; arbitrarily limits anchored matchers to the same line, and also
+ ;; arbitrarily limit anchored matchers to the same line, and also
;; to insulate against various other irritating differences between
;; the different (X)Emacs font-lock packages.
;;
;; covered by the font-lock context.)
;; Note: Replace `byte-compile' with `eval' to debug the generated
- ;; lambda easier.
+ ;; lambda more easily.
(byte-compile
`(lambda (limit)
- (let (;; The font-lock package in Emacs is known to clobber
+ (let ( ;; The font-lock package in Emacs is known to clobber
;; `parse-sexp-lookup-properties' (when it exists).
(parse-sexp-lookup-properties
(cc-eval-when-compile
(boundp 'parse-sexp-lookup-properties))))
- (while (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))
- (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))))
- (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))))
+
+ ;; (while (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))
+ ;; (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))))
+ ;; (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)))
+ ,(c-make-font-lock-search-form regexp highlights))
+
nil)))
+ (defun c-make-font-lock-BO-decl-search-function (regexp &rest highlights)
+ ;; This function makes a byte compiled function that first moves back
+ ;; to the beginning of the current declaration (if any), then searches
+ ;; forward for matcher elements (as in `font-lock-keywords') and
+ ;; fontifies them.
+ ;;
+ ;; The motivation for moving back to the declaration start is to
+ ;; establish a context for the current text when, e.g., a character
+ ;; is typed on a C++ inheritance continuation line, or a jit-lock
+ ;; chunk starts there.
+ ;;
+ ;; The new function works much like a matcher element in
+ ;; `font-lock-keywords'. It cuts out a little bit of the overhead
+ ;; compared to a real matcher. The main reason is however to pass the
+ ;; real search limit to the anchored matcher(s), since most (if not
+ ;; all) font-lock implementations arbitrarily limit anchored matchers
+ ;; to the same line, and also to insulate against various other
+ ;; irritating differences between the different (X)Emacs font-lock
+ ;; packages.
+ ;;
+ ;; REGEXP is the matcher, which must be a regexp. Only matches
+ ;; where the beginning is outside any comment or string literal are
+ ;; significant.
+ ;;
+ ;; HIGHLIGHTS is a list of highlight specs, just like in
+ ;; `font-lock-keywords', with these limitations: The face is always
+ ;; overridden (no big disadvantage, since hits in comments etc are
+ ;; filtered anyway), there is no "laxmatch", and an anchored matcher
+ ;; is always a form which must do all the fontification directly.
+ ;; `limit' is a variable bound to the real limit in the context of
+ ;; the anchored matcher forms.
+ ;;
+ ;; This function does not do any hidden buffer changes, but the
+ ;; generated functions will. (They are however used in places
+ ;; covered by the font-lock context.)
+
+ ;; Note: Replace `byte-compile' with `eval' to debug the generated
+ ;; lambda more easily.
+ (byte-compile
+ `(lambda (limit)
+ (let ( ;; The font-lock package in Emacs is known to clobber
+ ;; `parse-sexp-lookup-properties' (when it exists).
+ (parse-sexp-lookup-properties
+ (cc-eval-when-compile
+ (boundp 'parse-sexp-lookup-properties))))
+ (goto-char
+ (let ((here (point)))
+ (if (eq (car (c-beginning-of-decl-1)) 'same)
+ (point)
+ here)))
+ ,(c-make-font-lock-search-form regexp highlights))
+ nil)))
+
+ (defun c-make-font-lock-context-search-function (normal &rest state-stanzas)
+ ;; This function makes a byte compiled function that works much like
+ ;; a matcher element in `font-lock-keywords', with the following
+ ;; enhancement: the generated function will test for particular "font
+ ;; lock contexts" at the start of the region, i.e. is this point in
+ ;; the middle of some particular construct? if so the generated
+ ;; function will first fontify the tail of the construct, before
+ ;; going into the main loop and fontify full constructs up to limit.
+ ;;
+ ;; The generated function takes one parameter called `limit', and
+ ;; will fontify the region between POINT and LIMIT.
+ ;;
+ ;; NORMAL is a list of the form (REGEXP HIGHLIGHTS .....), and is
+ ;; used to fontify the "regular" bit of the region.
+ ;; STATE-STANZAS is list of elements of the form (STATE LIM REGEXP
+ ;; HIGHLIGHTS), each element coding one possible font lock context.
+
+ ;; o - REGEXP is a font-lock regular expression (NOT a function),
+ ;; o - HIGHLIGHTS is a list of zero or more highlighters as defined
+ ;; on page "Search-based Fontification" in the elisp manual. As
+ ;; yet (2009-06), they must have OVERRIDE set, and may not have
+ ;; LAXMATCH set.
+ ;;
+ ;; o - STATE is the "font lock context" (e.g. in-cpp-expr) and is
+ ;; not quoted.
+ ;; o - LIM is a lisp form whose evaluation will yield the limit
+ ;; position in the buffer for fontification by this stanza.
+ ;;
+ ;; This function does not do any hidden buffer changes, but the
+ ;; generated functions will. (They are however used in places
+ ;; covered by the font-lock context.)
+ ;;
+ ;; Note: Replace `byte-compile' with `eval' to debug the generated
+ ;; lambda more easily.
+ (byte-compile
+ `(lambda (limit)
+ (let ( ;; The font-lock package in Emacs is known to clobber
+ ;; `parse-sexp-lookup-properties' (when it exists).
+ (parse-sexp-lookup-properties
+ (cc-eval-when-compile
+ (boundp 'parse-sexp-lookup-properties))))
+ ,@(mapcar
+ (lambda (stanza)
+ (let ((state (car stanza))
+ (lim (nth 1 stanza))
+ (regexp (nth 2 stanza))
+ (highlights (cdr (cddr stanza))))
+ `(if (eq c-font-lock-context ',state)
+ (let ((limit ,lim))
+ ,(c-make-font-lock-search-form
+ regexp highlights)))))
+ state-stanzas)
+ ,(c-make-font-lock-search-form (car normal) (cdr normal))
+ nil))))
+
; (eval-after-load "edebug" ; 2006-07-09: def-edebug-spec is now in subr.el.
; '(progn
(def-edebug-spec c-fontify-types-and-refs let*)
(c-lang-const c-cpp-expr-directives)))
(cef-re (c-make-keywords-re t
(c-lang-const c-cpp-expr-functions))))
- `((,(c-make-font-lock-search-function
- (concat noncontinued-line-end
- (c-lang-const c-opt-cpp-prefix)
- ced-re ; 1 + ncle-depth
- ;; Match the whole logical line to look
- ;; for the functions in.
- "\\(\\\\\\(.\\|[\n\r]\\)\\|[^\n\r]\\)*")
- `((let ((limit (match-end 0)))
- (while (re-search-forward ,cef-re limit 'move)
- (c-put-font-lock-face (match-beginning 1)
- (match-end 1)
- c-preprocessor-face-name)))
- (goto-char (match-end ,(1+ ncle-depth)))))))))
+
+ `((,(c-make-font-lock-context-search-function
+ `(,(concat noncontinued-line-end
+ (c-lang-const c-opt-cpp-prefix)
+ ced-re ; 1 + ncle-depth
+ ;; Match the whole logical line to look
+ ;; for the functions in.
+ "\\(\\\\\\(.\\|[\n\r]\\)\\|[^\n\r]\\)*")
+ ((let ((limit (match-end 0)))
+ (while (re-search-forward ,cef-re limit 'move)
+ (c-put-font-lock-face (match-beginning 1)
+ (match-end 1)
+ c-preprocessor-face-name)))
+ (goto-char (match-end ,(1+ ncle-depth)))))
+ `(in-cpp-expr
+ (save-excursion (c-end-of-macro) (point))
+ ,cef-re
+ (1 c-preprocessor-face-name t)))))))
;; Fontify the directive names.
(,(c-make-font-lock-search-function
;; Clear the list of found types if we start from the start of the
;; buffer, to make it easier to get rid of misspelled types and
- ;; variables that has gotten recognized as types in malformed code.
+ ;; variables that have gotten recognized as types in malformed code.
(when (bobp)
(c-clear-found-types))
- ;; Clear the c-type char properties in the region to recalculate
- ;; them properly. This is necessary e.g. to handle constructs that
- ;; might been required as declarations temporarily during editing.
- ;; The interesting properties are anyway those put on the closest
- ;; token before the region.
- (c-clear-char-properties (point) limit 'c-type)
+ ;; Clear the c-type char properties which mark the region, to recalculate
+ ;; them properly. The most interesting properties are those put on the
+ ;; closest token before the region.
+ (save-excursion
+ (let ((pos (point)))
+ (c-backward-syntactic-ws)
+ (c-clear-char-properties
+ (if (and (not (bobp))
+ (memq (c-get-char-property (1- (point)) 'c-type)
+ '(c-decl-arg-start
+ c-decl-end
+ c-decl-id-start
+ c-decl-type-start)))
+ (1- (point))
+ pos)
+ limit 'c-type)))
;; Update `c-state-cache' to the beginning of the region. This will
;; make `c-beginning-of-syntax' go faster when it's used later on,
;; Check if the fontified region starts inside a declarator list so
;; that `c-font-lock-declarators' should be called at the start.
+ ;; The declared identifiers are font-locked correctly as types, if
+ ;; that is what they are.
(let ((prop (save-excursion
(c-backward-syntactic-ws)
(unless (bobp)
(c-forward-syntactic-ws limit)
(c-font-lock-declarators limit t (eq prop 'c-decl-type-start))))
+ (setq c-font-lock-context ;; (c-guess-font-lock-context)
+ (save-excursion
+ (if (and c-cpp-expr-intro-re
+ (c-beginning-of-macro)
+ (looking-at c-cpp-expr-intro-re))
+ 'in-cpp-expr)))
nil)
(defun c-font-lock-<>-arglists (limit)
nil)
(defun c-font-lock-declarators (limit list types)
- ;; Assuming the point is at the start of a declarator in a
- ;; declaration, fontify it. If LIST is non-nil, fontify also all
- ;; following declarators in a comma separated list (e.g. "foo" and
- ;; "bar" in "int foo = 17, bar;"). Stop at LIMIT. If TYPES is
- ;; non-nil, fontify all identifiers as types. Nil is always
- ;; returned.
+ ;; Assuming the point is at the start of a declarator in a declaration,
+ ;; fontify the identifier it declares. (If TYPES is set, it does this via
+ ;; the macro `c-fontify-types-and-refs'.)
+ ;;
+ ;; If LIST is non-nil, also fontify the ids in any following declarators in
+ ;; a comma separated list (e.g. "foo" and "*bar" in "int foo = 17, *bar;");
+ ;; additionally, mark the commas with c-type property 'c-decl-id-start or
+ ;; 'c-decl-type-start (according to TYPES). Stop at LIMIT.
+ ;;
+ ;; If TYPES is non-nil, fontify all identifiers as types.
+ ;;
+ ;; Nil is always returned. The function leaves point at the delimiter after
+ ;; the last declarator it processes.
;;
;; This function might do hidden buffer changes.
c-last-identifier-range
(separator-prop (if types 'c-decl-type-start 'c-decl-id-start)))
- (while (and
+ ;; The following `while' fontifies a single declarator id each time round.
+ ;; It loops only when LIST is non-nil.
+ (while
+ ;; Inside the following "condition form", we move forward over the
+ ;; declarator's identifier up as far as any opening bracket (for array
+ ;; size) or paren (for parameters of function-type) or brace (for
+ ;; array/struct initialization) or "=" or terminating delimiter
+ ;; (e.g. "," or ";" or "}").
+ (and
pos
(< (point) limit)
+ ;; The following form moves forward over the declarator's
+ ;; identifier (and what precedes it), returning t. If there
+ ;; wasn't one, it returns nil, terminating the `while'.
(let (got-identifier)
(setq paren-depth 0)
- ;; Skip over type decl prefix operators. (Note similar
- ;; code in `c-forward-decl-or-cast-1'.)
+ ;; Skip over type decl prefix operators, one for each iteration
+ ;; 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 2))
- ;; If the second submatch matches in C++ then
+ (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
(goto-char (match-end 1)))
(c-forward-syntactic-ws))
- ;; If we didn't pass the identifier above already, do it now.
+ ;; If we haven't passed the identifier already, do it now.
(unless got-identifier
(setq id-start (point))
(c-forward-name))
(/= id-end pos))
- ;; Skip out of the parens surrounding the identifier.
+ ;; Skip out of the parens surrounding the identifier. If closing
+ ;; parens are missing, this form returns nil.
(or (= paren-depth 0)
(c-safe (goto-char (scan-lists (point) 1 paren-depth))))
(<= (point) limit)
+ ;; Skip over any trailing bit, such as "__attribute__".
(progn
(when (looking-at c-decl-hangon-key)
(c-forward-keyword-clause 1))
(<= (point) limit))
;; Search syntactically to the end of the declarator (";",
- ;; ",", a closen paren, eob etc) or to the beginning of an
+ ;; ",", a closing paren, eob etc) or to the beginning of an
;; initializer or function prototype ("=" or "\\s\(").
;; Note that the open paren will match array specs in
;; square brackets, and we treat them as initializers too.
(char-after (match-beginning 1))))
(if types
- ;; Register and fontify the identifer as a type.
+ ;; Register and fontify the identifier as a type.
(let ((c-promote-possible-types t))
(goto-char id-start)
(c-forward-type))
id-face)))
(goto-char next-pos)
- (setq pos nil)
+ (setq pos nil) ; So as to terminate the enclosing `while' form.
(when list
;; Jump past any initializer or function prototype to see if
;; there's a ',' to continue at.
(cond ((eq id-face 'font-lock-function-name-face)
;; Skip a parenthesized initializer (C++) or a function
;; prototype.
- (if (c-safe (c-forward-sexp 1) t)
+ (if (c-safe (c-forward-sexp 1) t) ; over the parameter list.
(c-forward-syntactic-ws limit)
- (goto-char limit)))
+ (goto-char limit))) ; unbalanced parens
- (got-init
+ (got-init ; "=" sign OR opening "(", "[", or "{"
;; Skip an initializer expression. If we're at a '='
;; then accept a brace list directly after it to cope
;; with array initializers. Otherwise stop at braces
(and (if (and (eq got-init ?=)
(= (c-forward-token-2 1 nil limit) 0)
(looking-at "{"))
- (c-safe (c-forward-sexp) t)
+ (c-safe (c-forward-sexp) t) ; over { .... }
t)
;; FIXME: Should look for c-decl-end markers here;
;; we might go far into the following declarations
(c-put-char-property (point) 'c-type separator-prop)
(forward-char)
(c-forward-syntactic-ws limit)
- (setq pos (point))))))
+ (setq pos (point)))))) ; acts to make the `while' form continue.
nil)
(defconst c-font-lock-maybe-decl-faces
font-lock-keyword-face))
(defun c-font-lock-declarations (limit)
+ ;; Fontify all the declarations, casts and labels from the point to LIMIT.
+ ;; Assumes that strings and comments have been fontified already.
+ ;;
;; This function will be called from font-lock for a region bounded by POINT
;; and LIMIT, as though it were to identify a keyword for
;; font-lock-keyword-face. It always returns NIL to inhibit this and
;; prevent a repeat invocation. See elisp/lispref page "Search-based
;; Fontification".
;;
- ;; Fontify all the declarations, casts and labels from the point to LIMIT.
- ;; Assumes that strings and comments have been fontified already.
- ;;
;; This function might do hidden buffer changes.
;;(message "c-font-lock-declarations search from %s to %s" (point) limit)
(save-restriction
- (let (;; The position where `c-find-decl-spots' stopped.
+ (let (;; The position where `c-find-decl-spots' last stopped.
start-pos
- ;; 'decl if we're in an arglist containing declarations (but
- ;; if `c-recognize-paren-inits' is set it might also be an
- ;; initializer arglist), '<> if the arglist is of angle
- ;; bracket type, 'arglist if it's some other arglist, or nil
- ;; if not in an arglist at all.
+ ;; o - 'decl if we're in an arglist containing declarations
+ ;; (but if `c-recognize-paren-inits' is set it might also be
+ ;; an initializer arglist);
+ ;; o - '<> if the arglist is of angle bracket type;
+ ;; o - 'arglist if it's some other arglist;
+ ;; o - nil, if not in an arglist at all. This includes the
+ ;; parenthesised condition which follows "if", "while", etc.
context
;; The position of the next token after the closing paren of
;; the last detected cast.
(boundp 'parse-sexp-lookup-properties))))
;; Below we fontify a whole declaration even when it crosses the limit,
- ;; to avoid gaps when lazy-lock fontifies the file a screenful at a
+ ;; to avoid gaps when jit/lazy-lock fontifies the file a block at a
;; time. That is however annoying during editing, e.g. the following is
;; a common situation while the first line is being written:
;;
;; "some_other_variable" as an identifier, and the latter will not
;; correct itself until the second line is changed. To avoid that we
;; narrow to the limit if the region to fontify is a single line.
- (narrow-to-region
- (point-min)
- (if (<= limit (c-point 'bonl))
+ (if (<= limit (c-point 'bonl))
+ (narrow-to-region
+ (point-min)
(save-excursion
;; Narrow after any operator chars following the limit though,
;; since those characters can be useful in recognizing a
;; after the header).
(goto-char limit)
(skip-chars-forward c-nonsymbol-chars)
- (point))
- limit))
+ (point))))
(c-find-decl-spots
limit
(when
;; The result of the form below is true when we don't recognize a
;; declaration or cast.
- (if (and (eq (get-text-property (point) 'face)
- 'font-lock-keyword-face)
- (looking-at c-not-decl-init-keywords))
+ (if (or (and (eq (get-text-property (point) 'face)
+ 'font-lock-keyword-face)
+ (looking-at c-not-decl-init-keywords))
+ (and c-macro-with-semi-re
+ (looking-at c-macro-with-semi-re))) ; 2008-11-04
;; Don't do anything more if we're looking at a keyword that
;; can't start a declaration.
t
- ;; Set `context'. Look for "<" for the sake of C++-style template
- ;; arglists.
- (if (memq (char-before match-pos) '(?\( ?, ?\[ ?<))
-
- ;; Find out the type of the arglist.
- (if (<= match-pos (point-min))
- (setq context 'arglist)
- (let ((type (c-get-char-property (1- match-pos) 'c-type)))
- (cond ((eq type 'c-decl-arg-start)
- ;; Got a cached hit in a declaration arglist.
- (setq context 'decl))
- ((or (eq type 'c-<>-arg-sep)
- (eq (char-before match-pos) ?<))
- ;; Inside an angle bracket arglist.
- (setq context '<>))
- (type
- ;; Got a cached hit in some other type of arglist.
- (setq context 'arglist))
- ((if inside-macro
- (< match-pos max-type-decl-end-before-token)
- (< match-pos max-type-decl-end))
- ;; The point is within the range of a previously
- ;; encountered type decl expression, so the arglist
- ;; is probably one that contains declarations.
- ;; However, if `c-recognize-paren-inits' is set it
- ;; might also be an initializer arglist.
- (setq context 'decl)
- ;; The result of this check is cached with a char
- ;; property on the match token, so that we can look
- ;; it up again when refontifying single lines in a
- ;; multiline declaration.
- (c-put-char-property (1- match-pos)
- 'c-type 'c-decl-arg-start))
- (t
- (setq context 'arglist)))))
-
- (setq context nil))
-
- ;; If we're in a normal arglist context we don't want to
- ;; recognize commas in nested angle bracket arglists since
- ;; those commas could be part of our own arglist.
- (setq c-restricted-<>-arglists (and c-recognize-<>-arglists
- (eq context 'arglist))
-
- ;; Now analyze the construct.
- decl-or-cast (c-forward-decl-or-cast-1
+ ;; Set `context' and `c-restricted-<>-arglists'. Look for
+ ;; "<" for the sake of C++-style template arglists.
+ ;; Ignore "(" when it's part of a control flow construct
+ ;; (e.g. "for (").
+ (let ((type (and (> match-pos (point-min))
+ (c-get-char-property (1- match-pos) 'c-type))))
+ (cond ((not (memq (char-before match-pos) '(?\( ?, ?\[ ?<)))
+ (setq context nil
+ c-restricted-<>-arglists nil))
+ ;; A control flow expression
+ ((and (eq (char-before match-pos) ?\()
+ (save-excursion
+ (goto-char match-pos)
+ (backward-char)
+ (c-backward-token-2)
+ (looking-at c-block-stmt-2-key)))
+ (setq context nil
+ c-restricted-<>-arglists t))
+ ;; Near BOB.
+ ((<= match-pos (point-min))
+ (setq context 'arglist
+ c-restricted-<>-arglists t))
+ ;; Got a cached hit in a declaration arglist.
+ ((eq type 'c-decl-arg-start)
+ (setq context 'decl
+ c-restricted-<>-arglists nil))
+ ;; Inside an angle bracket arglist.
+ ((or (eq type 'c-<>-arg-sep)
+ (eq (char-before match-pos) ?<))
+ (setq context '<>
+ c-restricted-<>-arglists nil))
+ ;; Got a cached hit in some other type of arglist.
+ (type
+ (setq context 'arglist
+ c-restricted-<>-arglists t))
+ ((if inside-macro
+ (< match-pos max-type-decl-end-before-token)
+ (< match-pos max-type-decl-end))
+ ;; The point is within the range of a previously
+ ;; encountered type decl expression, so the arglist
+ ;; is probably one that contains declarations.
+ ;; However, if `c-recognize-paren-inits' is set it
+ ;; might also be an initializer arglist.
+ (setq context 'decl
+ c-restricted-<>-arglists nil)
+ ;; The result of this check is cached with a char
+ ;; property on the match token, so that we can look
+ ;; it up again when refontifying single lines in a
+ ;; multiline declaration.
+ (c-put-char-property (1- match-pos)
+ 'c-type 'c-decl-arg-start))
+ (t (setq context 'arglist
+ c-restricted-<>-arglists t))))
+
+ ;; Check we haven't missed a preceding "typedef".
+ (when (not (looking-at c-typedef-key))
+ (c-backward-syntactic-ws)
+ (c-backward-token-2)
+ (or (looking-at c-typedef-key)
+ (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))
- (if (not decl-or-cast)
- ;; False alarm. Return t to go on to the next check.
- t
-
- (if (eq decl-or-cast 'cast)
- ;; Save the position after the previous cast so we can feed
- ;; it to `c-forward-decl-or-cast-1' in the next round. That
- ;; helps it discover cast chains like "(a) (b) c".
- (setq last-cast-end (point))
-
- ;; Set `max-type-decl-end' or `max-type-decl-end-before-token'
- ;; under the assumption that we're after the first type decl
- ;; expression in the declaration now. That's not really true;
- ;; we could also be after a parenthesized initializer
- ;; expression in C++, but this is only used as a last resort
- ;; to slant ambiguous expression/declarations, and overall
- ;; it's worth the risk to occasionally fontify an expression
- ;; as a declaration in an initializer expression compared to
- ;; getting ambiguous things in normal function prototypes
- ;; fontified as expressions.
- (if inside-macro
- (when (> (point) max-type-decl-end-before-token)
- (setq max-type-decl-end-before-token (point)))
- (when (> (point) max-type-decl-end)
- (setq max-type-decl-end (point))))
-
- ;; Back up to the type to fontify the declarator(s).
- (goto-char (car decl-or-cast))
-
- (let ((decl-list
- (if context
- ;; Should normally not fontify a list of
- ;; declarators inside an arglist, but the first
- ;; argument in the ';' separated list of a "for"
- ;; statement is an exception.
- (when (eq (char-before match-pos) ?\()
- (save-excursion
- (goto-char (1- match-pos))
- (c-backward-syntactic-ws)
- (and (c-simple-skip-symbol-backward)
- (looking-at c-paren-stmt-key))))
- t)))
-
- ;; Fix the `c-decl-id-start' or `c-decl-type-start' property
- ;; before the first declarator if it's a list.
- ;; `c-font-lock-declarators' handles the rest.
- (when decl-list
- (save-excursion
- (c-backward-syntactic-ws)
- (unless (bobp)
- (c-put-char-property (1- (point)) 'c-type
- (if (cdr decl-or-cast)
- 'c-decl-type-start
- 'c-decl-id-start)))))
-
- (c-font-lock-declarators
- (point-max) decl-list (cdr decl-or-cast))))
-
- ;; A cast or declaration has been successfully identified, so do
- ;; all the fontification of types and refs that's been recorded.
+ (cond
+ ((eq decl-or-cast 'cast)
+ ;; Save the position after the previous cast so we can feed
+ ;; it to `c-forward-decl-or-cast-1' in the next round. That
+ ;; helps it discover cast chains like "(a) (b) c".
+ (setq last-cast-end (point))
(c-fontify-recorded-types-and-refs)
- nil))
+ nil)
+
+ (decl-or-cast
+ ;; We've found a declaration.
+
+ ;; Set `max-type-decl-end' or `max-type-decl-end-before-token'
+ ;; under the assumption that we're after the first type decl
+ ;; expression in the declaration now. That's not really true;
+ ;; we could also be after a parenthesized initializer
+ ;; expression in C++, but this is only used as a last resort
+ ;; to slant ambiguous expression/declarations, and overall
+ ;; it's worth the risk to occasionally fontify an expression
+ ;; as a declaration in an initializer expression compared to
+ ;; getting ambiguous things in normal function prototypes
+ ;; fontified as expressions.
+ (if inside-macro
+ (when (> (point) max-type-decl-end-before-token)
+ (setq max-type-decl-end-before-token (point)))
+ (when (> (point) max-type-decl-end)
+ (setq max-type-decl-end (point))))
+
+ ;; Back up to the type to fontify the declarator(s).
+ (goto-char (car decl-or-cast))
+
+ (let ((decl-list
+ (if context
+ ;; Should normally not fontify a list of
+ ;; declarators inside an arglist, but the first
+ ;; argument in the ';' separated list of a "for"
+ ;; statement is an exception.
+ (when (eq (char-before match-pos) ?\()
+ (save-excursion
+ (goto-char (1- match-pos))
+ (c-backward-syntactic-ws)
+ (and (c-simple-skip-symbol-backward)
+ (looking-at c-paren-stmt-key))))
+ t)))
+
+ ;; Fix the `c-decl-id-start' or `c-decl-type-start' property
+ ;; before the first declarator if it's a list.
+ ;; `c-font-lock-declarators' handles the rest.
+ (when decl-list
+ (save-excursion
+ (c-backward-syntactic-ws)
+ (unless (bobp)
+ (c-put-char-property (1- (point)) 'c-type
+ (if (cdr decl-or-cast)
+ 'c-decl-type-start
+ 'c-decl-id-start)))))
+
+ (c-font-lock-declarators
+ (point-max) decl-list (cdr decl-or-cast)))
+
+ ;; A declaration has been successfully identified, so do all the
+ ;; fontification of types and refs that've been recorded.
+ (c-fontify-recorded-types-and-refs)
+ nil)
+
+ (t
+ ;; Are we at a declarator? Try to go back to the declaration
+ ;; to check this. If we get there, check whether a "typedef"
+ ;; is there, then fontify the declarators accordingly.
+ (let ((decl-search-lim (max (- (point) 50000) (point-min)))
+ paren-state bod-res encl-pos is-typedef
+ c-recognize-knr-p) ; Strictly speaking, bogus, but it
+ ; speeds up lisp.h tremendously.
+ (save-excursion
+ (setq bod-res (car (c-beginning-of-decl-1 decl-search-lim)))
+ (if (and (eq bod-res 'same)
+ (progn
+ (c-backward-syntactic-ws)
+ (eq (char-before) ?\})))
+ (c-beginning-of-decl-1 decl-search-lim))
+
+ ;; We're now putatively at the declaration.
+ (setq paren-state (c-parse-state))
+ ;; At top level or inside a "{"?
+ (if (or (not (setq encl-pos
+ (c-most-enclosing-brace paren-state)))
+ (eq (char-after encl-pos) ?\{))
+ (progn
+ (when (looking-at c-typedef-key) ; "typedef"
+ (setq is-typedef t)
+ (goto-char (match-end 0))
+ (c-forward-syntactic-ws))
+ ;; At a real declaration?
+ (if (memq (c-forward-type t) '(t known found))
+ (progn
+ (c-font-lock-declarators limit t is-typedef)
+ nil)
+ ;; False alarm. Return t to go on to the next check.
+ (goto-char start-pos)
+ t))
+ t))))))
;; It was a false alarm. Check if we're in a label (or other
;; construct with `:' except bitfield) instead.
nil)))
+(defun c-font-lock-enum-tail (limit)
+ ;; Fontify an enum's identifiers when POINT is within the enum's brace
+ ;; block.
+ ;;
+ ;; This function will be called from font-lock for a region bounded by POINT
+ ;; and LIMIT, as though it were to identify a keyword for
+ ;; font-lock-keyword-face. It always returns NIL to inhibit this and
+ ;; prevent a repeat invocation. See elisp/lispref page "Search-based
+ ;; Fontification".
+ ;;
+ ;; Note that this function won't attempt to fontify beyond the end of the
+ ;; current enum block, if any.
+ (let* ((paren-state (c-parse-state))
+ (encl-pos (c-most-enclosing-brace paren-state))
+ (start (point))
+ )
+ (when (and
+ encl-pos
+ (eq (char-after encl-pos) ?\{)
+ (save-excursion
+ (goto-char encl-pos)
+ (c-backward-syntactic-ws)
+ (c-simple-skip-symbol-backward)
+ (or (looking-at c-brace-list-key) ; "enum"
+ (progn (c-backward-syntactic-ws)
+ (c-simple-skip-symbol-backward)
+ (looking-at c-brace-list-key)))))
+ (c-syntactic-skip-backward "^{," nil t)
+ (c-put-char-property (1- (point)) 'c-type 'c-decl-id-start)
+
+ (c-forward-syntactic-ws)
+ (c-font-lock-declarators limit t nil)))
+ nil)
+
+(defun c-font-lock-enclosing-decls (limit)
+ ;; Fontify the declarators of (nested) declarations we're in the middle of.
+ ;; This is mainly for when a jit-lock etc. chunk starts inside the brace
+ ;; block of a struct/union/class, etc.
+ ;;
+ ;; This function will be called from font-lock for a region bounded by POINT
+ ;; and LIMIT, as though it were to identify a keyword for
+ ;; font-lock-keyword-face. It always returns NIL to inhibit this and
+ ;; prevent a repeat invocation. See elisp/lispref page "Search-based
+ ;; Fontification".
+ (let* ((paren-state (c-parse-state))
+ (start (point))
+ decl-context bo-decl in-typedef type-type ps-elt)
+
+ ;; First, are we actually in a "local" declaration?
+ (setq decl-context (c-beginning-of-decl-1)
+ bo-decl (point)
+ in-typedef (looking-at c-typedef-key))
+ (if in-typedef (c-forward-token-2))
+ (when (and (eq (car decl-context) 'same)
+ (< bo-decl start))
+ ;; Are we genuinely at a type?
+ (setq type-type (c-forward-type t))
+ (if (and type-type
+ (or (not (eq type-type 'maybe))
+ (looking-at c-symbol-key)))
+ (c-font-lock-declarators limit t in-typedef)))
+
+ ;; Secondly, are we in any nested struct/union/class/etc. braces?
+ (while paren-state
+ (setq ps-elt (car paren-state)
+ paren-state (cdr paren-state))
+ (when (and (atom ps-elt)
+ (eq (char-after ps-elt) ?\{))
+ (goto-char ps-elt)
+ (setq decl-context (c-beginning-of-decl-1)
+ in-typedef (looking-at c-typedef-key))
+ (if in-typedef (c-forward-token-2))
+ (when (and c-opt-block-decls-with-vars-key
+ (looking-at c-opt-block-decls-with-vars-key))
+ (goto-char ps-elt)
+ (when (c-safe (c-forward-sexp))
+ (c-forward-syntactic-ws)
+ (c-font-lock-declarators limit t in-typedef)))))))
+
(c-lang-defconst c-simple-decl-matchers
"Simple font lock matchers for types and declarations. These are used
on level 2 only and so aren't combined with `c-complex-decl-matchers'."
"Complex font lock matchers for types and declarations. Used on level
3 and higher."
- ;; Note: This code in this form dumps a number of funtions into the
+ ;; Note: This code in this form dumps a number of functions into the
;; resulting constant, `c-matchers-3'. At run time, font lock will call
;; each of them as a "FUNCTION" (see Elisp page "Search-based
;; Fontification"). The font lock region is delimited by POINT and the
;; Fontify all declarations, casts and normal labels.
c-font-lock-declarations
+ ;; Fontify declarators when POINT is within their declaration.
+ c-font-lock-enclosing-decls
+
;; Fontify angle bracket arglists like templates in C++.
,@(when (c-lang-const c-recognize-<>-arglists)
`(c-font-lock-<>-arglists))
`(,(concat "\\<\\(" re "\\)\\>")
1 'font-lock-type-face)))
- ;; Fontify types preceded by `c-type-prefix-kwds'.
+ ;; Fontify types preceded by `c-type-prefix-kwds' (e.g. "struct").
,@(when (c-lang-const c-type-prefix-kwds)
`((,(byte-compile
`(lambda (limit)
(unless (c-skip-comments-and-strings limit)
(c-forward-syntactic-ws)
;; Handle prefix declaration specifiers.
- (when (looking-at c-prefix-spec-kwds-re)
+ (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))
,(if (c-major-mode-is 'c++-mode)
`(when (and (c-forward-type)
;; override it if it turns out to be an new declaration, but
;; it will be wrong if it's an expression (see the test
;; decls-8.cc).
- ,@(when (c-lang-const c-opt-block-decls-with-vars-key)
- `((,(c-make-font-lock-search-function
- (concat "}"
- (c-lang-const c-single-line-syntactic-ws)
- "\\(" ; 1 + c-single-line-syntactic-ws-depth
- (c-lang-const c-type-decl-prefix-key)
- "\\|"
- (c-lang-const c-symbol-key)
- "\\)")
- `((c-font-lock-declarators limit t nil)
- (progn
- (c-put-char-property (match-beginning 0) 'c-type
- 'c-decl-id-start)
- (goto-char (match-beginning
- ,(1+ (c-lang-const
- c-single-line-syntactic-ws-depth)))))
- (goto-char (match-end 0)))))))
+;; ,@(when (c-lang-const c-opt-block-decls-with-vars-key)
+;; `((,(c-make-font-lock-search-function
+;; (concat "}"
+;; (c-lang-const c-single-line-syntactic-ws)
+;; "\\(" ; 1 + c-single-line-syntactic-ws-depth
+;; (c-lang-const c-type-decl-prefix-key)
+;; "\\|"
+;; (c-lang-const c-symbol-key)
+;; "\\)")
+;; `((c-font-lock-declarators limit t nil) ; That `nil' says use `font-lock-variable-name-face';
+;; ; `t' would mean `font-lock-function-name-face'.
+;; (progn
+;; (c-put-char-property (match-beginning 0) 'c-type
+;; 'c-decl-id-start)
+;; ; 'c-decl-type-start)
+;; (goto-char (match-beginning
+;; ,(1+ (c-lang-const
+;; c-single-line-syntactic-ws-depth)))))
+;; (goto-char (match-end 0)))))))
;; Fontify the type in C++ "new" expressions.
,@(when (c-major-mode-is 'c++-mode)
generic casts and declarations are fontified. Used on level 2 and
higher."
- t `(;; Fontify the identifiers inside enum lists. (The enum type
+ t `(,@(when (c-lang-const c-brace-id-list-kwds)
+ ;; Fontify the remaining identifiers inside an enum list when we start
+ ;; inside it.
+ `(c-font-lock-enum-tail
+ ;; Fontify the identifiers inside enum lists. (The enum type
;; name is handled by `c-simple-decl-matchers' or
;; `c-complex-decl-matchers' below.
- ,@(when (c-lang-const c-brace-id-list-kwds)
- `((,(c-make-font-lock-search-function
+ (,(c-make-font-lock-search-function
(concat
"\\<\\("
(c-make-keywords-re nil (c-lang-const c-brace-id-list-kwds))
c-label-face-name nil t))))))
;; Fontify the clauses after various keywords.
- ,@(when (or (c-lang-const c-type-list-kwds)
- (c-lang-const c-ref-list-kwds)
- (c-lang-const c-colon-type-list-kwds)
- (c-lang-const c-paren-type-kwds))
- `((,(c-make-font-lock-search-function
- (concat "\\<\\("
- (c-make-keywords-re nil
- (append (c-lang-const c-type-list-kwds)
- (c-lang-const c-ref-list-kwds)
- (c-lang-const c-colon-type-list-kwds)
- (c-lang-const c-paren-type-kwds)))
- "\\)\\>")
- '((c-fontify-types-and-refs ((c-promote-possible-types t))
- (c-forward-keyword-clause 1)
- (if (> (point) limit) (goto-char limit))))))))
-
- ,@(when (c-major-mode-is 'java-mode)
- `((eval . (list "\\<\\(@[a-zA-Z0-9]+\\)\\>" 1 c-annotation-face))))
+ ,@(when (or (c-lang-const c-type-list-kwds)
+ (c-lang-const c-ref-list-kwds)
+ (c-lang-const c-colon-type-list-kwds))
+ `((,(c-make-font-lock-BO-decl-search-function
+ (concat "\\<\\("
+ (c-make-keywords-re nil
+ (append (c-lang-const c-type-list-kwds)
+ (c-lang-const c-ref-list-kwds)
+ (c-lang-const c-colon-type-list-kwds)))
+ "\\)\\>")
+ '((c-fontify-types-and-refs ((c-promote-possible-types t))
+ (c-forward-keyword-clause 1)
+ (if (> (point) limit) (goto-char limit))))))))
+
+ ,@(when (c-lang-const c-paren-type-kwds)
+ `((,(c-make-font-lock-search-function
+ (concat "\\<\\("
+ (c-make-keywords-re nil
+ (c-lang-const c-paren-type-kwds))
+ "\\)\\>")
+ '((c-fontify-types-and-refs ((c-promote-possible-types t))
+ (c-forward-keyword-clause 1)
+ (if (> (point) limit) (goto-char limit))))))))
+
+ ,@(when (c-major-mode-is 'java-mode)
+ `((eval . (list "\\<\\(@[a-zA-Z0-9]+\\)\\>" 1 c-annotation-face))))
))
(c-lang-defconst c-matchers-1
;;; C++.
(defun c-font-lock-c++-new (limit)
+ ;; FIXME!!! Put in a comment about the context of this function's
+ ;; invocation. I think it's called as an ANCHORED-MATCHER within an
+ ;; ANCHORED-HIGHLIGHTER. (2007/2/10).
+ ;;
;; Assuming point is after a "new" word, check that it isn't inside
;; a string or comment, and if so try to fontify the type in the
;; allocation expression. Nil is always returned.
(defconst gtkdoc-font-lock-doc-comments
(let ((symbol "[a-zA-Z0-9_]+")
(header "^ \\* "))
- `((,(concat header "\\(" symbol "\\):[ \t]*$")
+ `((,(concat header "\\(" symbol "\\):[ \t]*$")
1 ,c-doc-markup-face-name prepend nil)
(,(concat symbol "()")
0 ,c-doc-markup-face-name prepend nil)
;; 2006-07-10: awk-font-lock-keywords has been moved back to cc-awk.el.
(cc-provide 'cc-fonts)
-;; arch-tag: 2f65f405-735f-4da5-8d4b-b957844c5203
;;; cc-fonts.el ends here