aboutsummaryrefslogtreecommitdiffstats
path: root/lisp/progmodes/cc-fonts.el
diff options
context:
space:
mode:
authorMartin Stjernholm <[email protected]>2003-07-03 12:30:59 +0000
committerMartin Stjernholm <[email protected]>2003-07-03 12:30:59 +0000
commitd9e94c22736810b8bd61964a322ecc9664e09e14 (patch)
treece672e1ad395b22302fe7f1a847ca931f67f5510 /lisp/progmodes/cc-fonts.el
parentbac598bbf5d00efafe178061c849801babe79bf0 (diff)
Updated CC Mode to version 5.30.
Diffstat (limited to 'lisp/progmodes/cc-fonts.el')
-rw-r--r--lisp/progmodes/cc-fonts.el2879
1 files changed, 2879 insertions, 0 deletions
diff --git a/lisp/progmodes/cc-fonts.el b/lisp/progmodes/cc-fonts.el
new file mode 100644
index 0000000000..8a0ba6d192
--- /dev/null
+++ b/lisp/progmodes/cc-fonts.el
@@ -0,0 +1,2879 @@
+;;; cc-fonts.el --- font lock support for CC Mode
+
+;; Copyright (C) 2002, 03 Free Software Foundation, Inc.
+
+;; Authors: 2003- Alan Mackenzie
+;; 2002- Martin Stjernholm
+;; Maintainer: [email protected]
+;; Created: 07-Jan-2002
+;; Version: See cc-mode.el
+;; Keywords: c languages oop
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program; see the file COPYING. If not, write to
+;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; Some comments on the use of faces:
+;;
+;; o `c-label-face-name' is either `font-lock-constant-face' (in Emacs
+;; 20 and later), or `font-lock-reference-face'.
+;;
+;; o `c-constant-face-name', `c-reference-face-name' and
+;; `c-doc-markup-face-name' are essentially set up like
+;; `c-label-face-name'.
+;;
+;; o `c-preprocessor-face-name' is `font-lock-preprocessor-face' in
+;; XEmacs and - in lack of a closer equivalent -
+;; `font-lock-builtin-face' or `font-lock-reference-face' in Emacs.
+;;
+;; o `c-doc-face-name' is `font-lock-doc-string-face' in XEmacs,
+;; `font-lock-doc-face' in Emacs 21 and later, or
+;; `font-lock-comment-face' in older Emacs (that since source
+;; documentation are actually comments in these languages, as opposed
+;; to elisp).
+;;
+;; o `c-invalid-face-name' is `font-lock-warning-face' in Emacs. In
+;; older XEmacs there's no corresponding standard face, so there
+;; it's mapped to a special `c-invalid-face'.
+;;
+;; TBD: We should probably provide real faces for the above uses and
+;; instead initialize them from the standard faces.
+
+;;; Code:
+
+;; The faces that already have been put onto the text is tested in
+;; various places to direct further fontifications. For this to work,
+;; the following assumptions regarding the faces must hold (apart from
+;; the dependencies on the font locking order):
+;;
+;; o `font-lock-comment-face' and the face in `c-doc-face-name' is
+;; not used in anything but comments.
+;; o If any face (e.g. `c-doc-markup-face-name') but those above is
+;; used in comments, it doesn't replace them.
+;; o `font-lock-string-face' is not used in anything but string
+;; literals (single or double quoted).
+;; o `font-lock-keyword-face' and the face in `c-label-face-name' are
+;; never overlaid with other faces.
+
+(eval-when-compile
+ (let ((load-path
+ (if (and (boundp 'byte-compile-dest-file)
+ (stringp byte-compile-dest-file))
+ (cons (file-name-directory byte-compile-dest-file) load-path)
+ load-path)))
+ (load "cc-bytecomp" nil t)))
+
+(cc-require 'cc-defs)
+(cc-require-when-compile 'cc-langs)
+(cc-require 'cc-vars)
+(cc-require 'cc-engine)
+(cc-require-when-compile 'cc-awk) ; Change from cc-require, 2003/6/18 to
+;; prevent cc-awk being loaded when it's not needed. There is now a (require
+;; 'cc-awk) in (defun awk-mode ..).
+
+;; Avoid repeated loading through the eval-after-load directive in
+;; cc-mode.el.
+(provide 'cc-fonts)
+
+(cc-external-require 'font-lock)
+
+(cc-bytecomp-defvar parse-sexp-lookup-properties) ; Emacs only.
+
+;; Need to declare these local symbols during compilation since
+;; they're referenced from lambdas in `byte-compile' calls that are
+;; executed at compile time. They don't need to have the proper
+;; definitions, though, since the generated functions aren't called
+;; during compilation.
+(cc-bytecomp-defvar c-preprocessor-face-name)
+(cc-bytecomp-defvar c-reference-face-name)
+(cc-bytecomp-defun c-fontify-recorded-types-and-refs)
+(cc-bytecomp-defun c-font-lock-declarators)
+(cc-bytecomp-defun c-font-lock-objc-iip-decl)
+(cc-bytecomp-defun c-font-lock-objc-method)
+(cc-bytecomp-defun c-font-lock-invalid-string)
+
+;; Emacs 19 doesn't have `defface'. This "replacement" leaves a lot
+;; to be wished for but at least it avoids any errors.
+(cc-eval-when-compile
+ (or (fboundp 'defface)
+ (cc-bytecomp-defmacro defface (face spec doc &rest args)
+ `(make-face ',face))))
+
+
+;; Note that font-lock in XEmacs doesn't expand face names as
+;; variables, so we have to use the (eval . FORM) in the font lock
+;; matchers wherever we use these alias variables.
+
+(defconst c-preprocessor-face-name
+ (cond ((c-face-name-p 'font-lock-preprocessor-face)
+ ;; XEmacs has a font-lock-preprocessor-face.
+ 'font-lock-preprocessor-face)
+ ((c-face-name-p 'font-lock-builtin-face)
+ ;; In Emacs 20 and later font-lock-builtin-face has
+ ;; traditionally been used for preprocessor directives.
+ 'font-lock-builtin-face)
+ (t
+ 'font-lock-reference-face)))
+
+(cc-bytecomp-defvar font-lock-constant-face)
+
+(defconst c-label-face-name
+ (cond ((c-face-name-p 'font-lock-label-face)
+ ;; If it happens to occur in the future. (Well, the more
+ ;; pragmatic reason is to get unique faces for the test
+ ;; suite.)
+ 'font-lock-label-face)
+ ((and (c-face-name-p 'font-lock-constant-face)
+ (eq font-lock-constant-face 'font-lock-constant-face))
+ ;; Test both if font-lock-constant-face exists and that it's
+ ;; not an alias for something else. This is important since
+ ;; we compare already set faces in various places.
+ 'font-lock-constant-face)
+ (t
+ 'font-lock-reference-face)))
+
+(defconst c-constant-face-name
+ (if (and (c-face-name-p 'font-lock-constant-face)
+ (eq font-lock-constant-face 'font-lock-constant-face))
+ ;; This doesn't exist in XEmacs <= 20 and some earlier versions
+ ;; of XEmacs 21.
+ 'font-lock-constant-face
+ c-label-face-name))
+
+(defconst c-reference-face-name
+ (if (and (c-face-name-p 'font-lock-reference-face)
+ (eq font-lock-reference-face 'font-lock-reference-face))
+ ;; This is considered obsolete in Emacs 20 and later, but it
+ ;; still maps well to this use. (Another reason to do this is
+ ;; to get unique faces for the test suite.)
+ 'font-lock-reference-face
+ c-label-face-name))
+
+;; This should not mapped to a face that also is used to fontify things
+;; that aren't comments or string literals.
+(defconst c-doc-face-name
+ (cond ((c-face-name-p 'font-lock-doc-string-face)
+ ;; XEmacs.
+ 'font-lock-doc-string-face)
+ ((c-face-name-p 'font-lock-doc-face)
+ ;; Emacs 21 and later.
+ 'font-lock-doc-face)
+ (t
+ 'font-lock-comment-face)))
+
+(defconst c-doc-markup-face-name
+ (if (c-face-name-p 'font-lock-doc-markup-face)
+ ;; If it happens to occur in the future. (Well, the more
+ ;; pragmatic reason is to get unique faces for the test
+ ;; suite.)
+ 'font-lock-doc-markup-face
+ c-label-face-name))
+
+(defconst c-invalid-face-name
+ (if (c-face-name-p 'font-lock-warning-face)
+ ;; Emacs >= 20 and XEmacs >= 21 has a font-lock-warning-face.
+ 'font-lock-warning-face
+ ;; Otherwise we provide a face.
+ 'c-invalid-face))
+
+(unless (c-face-name-p c-invalid-face-name)
+ (defconst c-invalid-face 'c-invalid-face) ; Necessary in Emacs 19.
+ (defface c-invalid-face
+ '((((class color) (background light)) (:foreground "red"))
+ (((class color)) (:foreground "hotpink"))
+ (t (:inverse-video t)))
+ "Face used to highlight invalid syntax."
+ :group 'c-fonts))
+
+;; To make hard spaces visible an inverted version of
+;; `c-invalid-face-name' is used. Since font-lock in Emacs expands
+;; all face names in `font-lock-keywords' as variables we need to have
+;; a variable for it that resolves to its own name.
+(defconst c-nonbreakable-space-face 'c-nonbreakable-space-face)
+
+(cc-bytecomp-defun face-inverse-video-p) ; Only in Emacs.
+(cc-bytecomp-defun face-property-instance) ; Only in XEmacs.
+
+(defun c-make-inverse-face (oldface newface)
+ ;; Emacs and XEmacs have completely different face manipulation
+ ;; routines. :P
+ ;;
+ ;; This function does not do any hidden buffer changes
+ (copy-face oldface newface)
+ (cond ((fboundp 'face-inverse-video-p)
+ ;; Emacs 20 and later. This only looks at the inverse flag
+ ;; in the current frame. Other display configurations might
+ ;; be different, but it can only show if the same Emacs has
+ ;; frames on e.g. a color and a monochrome display
+ ;; simultaneously.
+ (unless (face-inverse-video-p oldface)
+ (invert-face newface)))
+ ((fboundp 'face-property-instance)
+ ;; XEmacs. Same pitfall here.
+ (unless (face-property-instance oldface 'reverse)
+ (invert-face newface)))
+ (t
+ ;; Emacs 19 has no inverse flag at all. Just inverse the
+ ;; face and hope it wasn't inversed already.
+ (invert-face newface))))
+
+(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.
+
+ (defmacro c-put-font-lock-face (from to face)
+ ;; Put a face on a region (overriding any existing face) in the way
+ ;; font-lock would do it. In XEmacs that means putting an
+ ;; additional font-lock property, or else the font-lock package
+ ;; won't recognize it as fontified and might override it
+ ;; incorrectly.
+ (if (fboundp 'font-lock-set-face)
+ ;; Note: This function has no docstring in XEmacs so it might be
+ ;; considered internal.
+ `(font-lock-set-face ,from ,to ,face)
+ `(put-text-property ,from ,to 'face ,face)))
+
+ (defmacro c-remove-font-lock-face (from to)
+ ;; This is the inverse of `c-put-font-lock-face'.
+ (if (fboundp 'font-lock-remove-face)
+ `(font-lock-remove-face ,from ,to)
+ `(remove-text-properties ,from ,to '(face nil))))
+
+ (defmacro c-put-font-lock-string-face (from to)
+ ;; Put `font-lock-string-face' on a string. The surrounding
+ ;; quotes are included in Emacs but not in XEmacs. The passed
+ ;; region should include them.
+ (if (featurep 'xemacs)
+ `(c-put-font-lock-face (1+ ,from) (1- ,to) 'font-lock-string-face)
+ `(c-put-font-lock-face ,from ,to 'font-lock-string-face)))
+
+ (defmacro c-fontify-types-and-refs (varlist &rest body)
+ ;; Like `let', but additionally activates `c-record-type-identifiers'
+ ;; and `c-record-ref-identifiers', and fontifies the recorded ranges
+ ;; accordingly on exit.
+ `(let ((c-record-type-identifiers t)
+ c-record-ref-identifiers
+ ,@varlist)
+ (prog1 (progn ,@body)
+ (c-fontify-recorded-types-and-refs))))
+ (put 'c-fontify-types-and-refs 'lisp-indent-function 1)
+ (eval-after-load "edebug" '(def-edebug-spec c-fontify-types-and-refs let*))
+
+ (defun c-skip-comments-and-strings (limit)
+ ;; If the point is within a region fontified as a comment or
+ ;; string literal skip to the end of it or to LIMIT, whichever
+ ;; comes first, and return t. Otherwise return nil. The match
+ ;; data is not clobbered.
+ (when (c-got-face-at (point) c-literal-faces)
+ (while (progn
+ (goto-char (next-single-property-change
+ (point) 'face nil limit))
+ (and (< (point) limit)
+ (c-got-face-at (point) c-literal-faces))))
+ t))
+
+ (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
+ ;; 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 easier.
+ (byte-compile
+ `(lambda (limit)
+ (let (-match-end-pos-
+ ;; 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)
+ (setq -match-end-pos- (point))
+ (unless (progn
+ (goto-char (match-beginning 0))
+ (c-skip-comments-and-strings limit))
+ (goto-char -match-end-pos-)
+ ,@(mapcar
+ (lambda (highlight)
+ (if (integerp (car highlight))
+ (progn
+ (unless (nth 2 highlight)
+ (error
+ "The override flag must currently be set 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))))
+ nil))))
+
+(defun c-fontify-recorded-types-and-refs ()
+ ;; Converts the ranges recorded on `c-record-type-identifiers' and
+ ;; `c-record-ref-identifiers' to fontification.
+ (let (elem)
+ (while (consp c-record-type-identifiers)
+ (setq elem (car c-record-type-identifiers)
+ c-record-type-identifiers (cdr c-record-type-identifiers))
+ (c-put-font-lock-face (car elem) (cdr elem)
+ 'font-lock-type-face))
+ (while c-record-ref-identifiers
+ (setq elem (car c-record-ref-identifiers)
+ c-record-ref-identifiers (cdr c-record-ref-identifiers))
+ ;; Note that the reference face is a variable that is
+ ;; dereferenced, since it's an alias in Emacs.
+ (c-put-font-lock-face (car elem) (cdr elem)
+ c-reference-face-name))))
+
+(c-lang-defconst c-cpp-matchers
+ "Font lock matchers for preprocessor directives and purely lexical
+stuff. Used on level 1 and higher."
+
+ ;; Note: `c-font-lock-declarations' assumes that no matcher here
+ ;; sets `font-lock-type-face' in languages where
+ ;; `c-recognize-<>-arglists' is set.
+
+ t `(,@(when (c-lang-const c-opt-cpp-prefix)
+ (let* ((noncontinued-line-end "\\(\\=\\|\\(\\=\\|[^\\]\\)[\n\r]\\)")
+ (ncle-depth (c-regexp-opt-depth noncontinued-line-end))
+ (sws-depth (c-lang-const c-syntactic-ws-depth)))
+ `(;; The stuff after #error and #warning is a message, so
+ ;; fontify it as a string.
+ (,(concat noncontinued-line-end
+ (c-lang-const c-opt-cpp-prefix)
+ "\\(error\\|warning\\)\\>\\s *\\(.*\\)$")
+ ,(+ ncle-depth 2) font-lock-string-face)
+
+ ;; Fontify filenames in #include <...> as strings.
+ (,(concat noncontinued-line-end
+ (c-lang-const c-opt-cpp-prefix)
+ "\\(import\\|include\\)\\>"
+ (c-lang-const c-syntactic-ws)
+ "\\(<[^>\n\r]*>?\\)")
+ (,(+ ncle-depth sws-depth 2)
+ font-lock-string-face)
+
+ ;; Use an anchored matcher to put paren syntax on the brackets.
+ (,(byte-compile
+ `(lambda (limit)
+ (let ((beg-pos
+ (match-beginning ,(+ ncle-depth sws-depth 2)))
+ (end-pos
+ (1- (match-end ,(+ ncle-depth sws-depth 2)))))
+ (if (eq (char-after end-pos) ?>)
+ (progn
+ (c-mark-<-as-paren beg-pos)
+ (c-mark->-as-paren end-pos))
+ (c-clear-char-property beg-pos 'syntax-table)))
+ nil))))
+
+ ;; #define.
+ (,(c-make-font-lock-search-function
+ (concat
+ noncontinued-line-end
+ (c-lang-const c-opt-cpp-prefix)
+ "define\\>"
+ (c-lang-const c-syntactic-ws)
+ "\\(" (c-lang-const c-symbol-key) "\\)" ; 1 + ncle + sws
+ (concat "\\(" ; 2 + ncle + sws + c-sym-key
+ ;; Macro with arguments - a "function".
+ "\\(\(\\)" ; 3 + ncle + sws + c-sym-key
+ "\\|"
+ ;; Macro without arguments - a "variable".
+ "\\([^\(]\\|$\\)"
+ "\\)"))
+ `((if (match-beginning ,(+ 3 ncle-depth sws-depth
+ (c-lang-const c-symbol-key-depth)))
+ ;; "Function". Fontify the name and the arguments.
+ (save-restriction
+ (c-put-font-lock-face
+ (match-beginning ,(+ 1 ncle-depth sws-depth))
+ (match-end ,(+ 1 ncle-depth sws-depth))
+ 'font-lock-function-name-face)
+ (goto-char (match-end
+ ,(+ 3 ncle-depth sws-depth
+ (c-lang-const c-symbol-key-depth))))
+
+ (narrow-to-region (point-min) limit)
+ (while (and
+ (progn
+ (c-forward-syntactic-ws)
+ (looking-at c-symbol-key))
+ (progn
+ (c-put-font-lock-face
+ (match-beginning 0) (match-end 0)
+ 'font-lock-variable-name-face)
+ (goto-char (match-end 0))
+ (c-forward-syntactic-ws)
+ (eq (char-after) ?,)))
+ (forward-char)))
+
+ ;; "Variable".
+ (c-put-font-lock-face
+ (match-beginning ,(+ 1 ncle-depth sws-depth))
+ (match-end ,(+ 1 ncle-depth sws-depth))
+ 'font-lock-variable-name-face)))))
+
+ ;; Fontify cpp function names in preprocessor
+ ;; expressions in #if and #elif.
+ ,(when (c-lang-const c-cpp-defined-fns)
+ `(,(c-make-font-lock-search-function
+ (concat noncontinued-line-end
+ (c-lang-const c-opt-cpp-prefix)
+ "\\(if\\|elif\\)\\>" ; 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
+ ,(concat "\\<\\("
+ (c-regexp-opt
+ (c-lang-const c-cpp-defined-fns)
+ nil)
+ "\\)\\>"
+ "\\s *\(?")
+ limit 'move)
+ (c-put-font-lock-face (match-beginning 1)
+ (match-end 1)
+ c-preprocessor-face-name)))
+ (goto-char (match-end ,(1+ ncle-depth)))))))
+
+ ;; Fontify the directive names.
+ (,(c-make-font-lock-search-function
+ (concat noncontinued-line-end
+ "\\("
+ (c-lang-const c-opt-cpp-prefix)
+ "[" (c-lang-const c-symbol-chars) "]+"
+ "\\)")
+ `(,(1+ ncle-depth) c-preprocessor-face-name t)))
+ )))
+
+ ,@(when (c-major-mode-is 'pike-mode)
+ `((eval . (list "\\`#![^\n\r]*"
+ 0 c-preprocessor-face-name))))
+
+ ;; Make hard spaces visible through an inverted `c-invalid-face-name'.
+ (eval . (list
+ "\240"
+ 0 (progn
+ (unless (c-face-name-p 'c-nonbreakable-space-face)
+ (c-make-inverse-face c-invalid-face-name
+ 'c-nonbreakable-space-face))
+ 'c-nonbreakable-space-face)))
+ ))
+
+(defun c-font-lock-invalid-string ()
+ ;; Assuming the point is after the opening character of a string,
+ ;; fontify that char with `c-invalid-face-name' if the string
+ ;; decidedly isn't terminated properly. Assumes the string already
+ ;; is syntactically fontified.
+ (let ((end (1+ (c-point 'eol))))
+ (and (eq (get-text-property (point) 'face) 'font-lock-string-face)
+ (= (next-single-property-change (point) 'face nil end) end)
+ ;; We're at eol inside a string. The first check above is
+ ;; necessary in XEmacs since it doesn't fontify the string
+ ;; delimiters themselves. Thus an empty string won't have
+ ;; the string face anywhere.
+ (if (c-major-mode-is '(c-mode c++-mode objc-mode pike-mode))
+ ;; There's no \ before the newline.
+ (not (eq (char-before (1- end)) ?\\))
+ ;; Quoted newlines aren't supported.
+ t)
+ (if (c-major-mode-is 'pike-mode)
+ ;; There's no # before the string, so newlines
+ ;; aren't allowed.
+ (not (eq (char-before (1- (point))) ?#))
+ t)
+ (c-put-font-lock-face (1- (point)) (point) c-invalid-face-name))))
+
+(c-lang-defconst c-basic-matchers-before
+ "Font lock matchers for basic keywords, labels, references and various
+other easily recognizable things that should be fontified before generic
+casts and declarations are fontified. Used on level 2 and higher."
+
+ ;; Note: `c-font-lock-declarations' assumes that no matcher here
+ ;; sets `font-lock-type-face' in languages where
+ ;; `c-recognize-<>-arglists' is set.
+
+ t `(;; Put a warning face on the opener of unclosed strings that
+ ;; can't span lines. Later font
+ ;; lock packages have a `font-lock-syntactic-face-function' for
+ ;; this, but it doesn't give the control we want since any
+ ;; fontification done inside the function will be
+ ;; unconditionally overridden.
+ ,(c-make-font-lock-search-function
+ ;; Match a char before the string starter to make
+ ;; `c-skip-comments-and-strings' work correctly.
+ (concat ".\\(" c-string-limit-regexp "\\)")
+ '((c-font-lock-invalid-string)))
+
+ ;; Fontify keyword constants.
+ ,@(when (c-lang-const c-constant-kwds)
+ (let ((re (c-make-keywords-re nil (c-lang-const c-constant-kwds))))
+ (if (c-major-mode-is 'pike-mode)
+ ;; No symbol is a keyword after "->" in Pike.
+ `((eval . (list ,(concat "\\(\\=\\|\\(\\=\\|[^-]\\)[^>]\\)"
+ "\\<\\(" re "\\)\\>")
+ 3 c-constant-face-name)))
+ `((eval . (list ,(concat "\\<\\(" re "\\)\\>")
+ 1 c-constant-face-name))))))
+
+ ;; Fontify all keywords except the primitive types.
+ ,(if (c-major-mode-is 'pike-mode)
+ ;; No symbol is a keyword after "->" in Pike.
+ `(,(concat "\\(\\=\\|\\(\\=\\|[^-]\\)[^>]\\)"
+ "\\<" (c-lang-const c-regular-keywords-regexp))
+ 3 font-lock-keyword-face)
+ `(,(concat "\\<" (c-lang-const c-regular-keywords-regexp))
+ 1 font-lock-keyword-face))
+
+ ;; Fontify leading identifiers in fully qualified names like
+ ;; "foo::bar" in languages that supports such things.
+ ,@(when (c-lang-const c-opt-identifier-concat-key)
+ `((,(byte-compile
+ ;; Must use a function here since we match longer
+ ;; than we want to move before doing a new search.
+ ;; This is not necessary for XEmacs >= 20 since it
+ ;; restarts the search from the end of the first
+ ;; highlighted submatch (something that causes
+ ;; problems in other places).
+ `(lambda (limit)
+ (while (re-search-forward
+ ,(concat "\\(\\<" ; 1
+ "\\(" (c-lang-const c-symbol-key) "\\)" ; 2
+ "[ \t\n\r\f\v]*"
+ (c-lang-const c-opt-identifier-concat-key)
+ "[ \t\n\r\f\v]*"
+ "\\)"
+ "\\("
+ (c-lang-const c-opt-after-id-concat-key)
+ "\\)")
+ limit t)
+ (unless (progn
+ (goto-char (match-beginning 0))
+ (c-skip-comments-and-strings limit))
+ (or (get-text-property (match-beginning 2) 'face)
+ (c-put-font-lock-face (match-beginning 2)
+ (match-end 2)
+ c-reference-face-name))
+ (goto-char (match-end 1)))))))))
+
+ ;; Fontify the special declarations in Objective-C.
+ ,@(when (c-major-mode-is 'objc-mode)
+ `(;; Fontify class names in the beginning of message expressions.
+ ,(c-make-font-lock-search-function
+ "\\["
+ '((c-fontify-types-and-refs ()
+ (c-forward-syntactic-ws limit)
+ (let ((start (point)))
+ ;; In this case we accept both primitive and known types.
+ (when (eq (c-forward-type) 'known)
+ (goto-char start)
+ (let ((c-promote-possible-types t))
+ (c-forward-type))))
+ (if (> (point) limit) (goto-char limit)))))
+
+ ;; The @interface/@implementation/@protocol directives.
+ (,(concat "\\<"
+ (c-regexp-opt
+ '("@interface" "@implementation" "@protocol")
+ t)
+ "\\>")
+ (,(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))))
+ (save-restriction
+ (narrow-to-region (point-min) limit)
+ (c-font-lock-objc-iip-decl)))
+ nil))))))
+ ))
+
+(defun c-font-lock-complex-decl-prepare (limit)
+ ;; Called before any of the matchers in `c-complex-decl-matchers'.
+ ;; Nil is always returned.
+
+ ;;(message "c-font-lock-complex-decl-prepare %s %s" (point) limit)
+
+ ;; 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.
+ (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)
+
+ ;; 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,
+ ;; and it's near the point most of the time.
+ (c-parse-state)
+
+ ;; Check if the fontified region starts inside a declarator list so
+ ;; that `c-font-lock-declarators' should be called at the start.
+ (let ((prop (save-excursion
+ (c-backward-syntactic-ws)
+ (unless (bobp)
+ (c-get-char-property (1- (point)) 'c-type)))))
+ (when (memq prop '(c-decl-id-start c-decl-type-start))
+ (c-forward-syntactic-ws limit)
+ (c-font-lock-declarators limit t (eq prop 'c-decl-type-start))))
+
+ nil)
+
+(defun c-font-lock-<>-arglists (limit)
+ ;; Fontify types and references in names containing angle bracket
+ ;; arglists from the point to LIMIT. This will also fontify cases
+ ;; like normal function calls on the form "foo (a < b, c > d)", but
+ ;; `c-font-lock-declarations' will undo that later. Nil is always
+ ;; returned.
+
+ (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)))
+ id-start id-end pos kwd-sym)
+
+ (while (and (< (point) limit)
+ (re-search-forward c-opt-<>-arglist-start limit t))
+
+ (setq id-start (match-beginning 1)
+ id-end (match-end 1)
+ pos (point))
+
+ (goto-char id-start)
+ (unless (c-skip-comments-and-strings limit)
+ (setq kwd-sym nil)
+ (if (or (not (eq (get-text-property id-start 'face)
+ 'font-lock-keyword-face))
+ (when (looking-at c-opt-<>-sexp-key)
+ (setq kwd-sym (c-keyword-sym (match-string 1)))))
+ (progn
+ (goto-char (1- pos))
+ ;; Check for comment/string both at the identifier and
+ ;; at the "<".
+ (unless (c-skip-comments-and-strings limit)
+
+ (when (c-forward-<>-arglist (c-keyword-member kwd-sym
+ 'c-<>-type-kwds)
+ t)
+ (when (and c-opt-identifier-concat-key
+ (not (get-text-property id-start 'face)))
+ (c-forward-syntactic-ws)
+ (if (looking-at c-opt-identifier-concat-key)
+ (c-put-font-lock-face id-start id-end
+ c-reference-face-name)
+ (c-put-font-lock-face id-start id-end
+ 'font-lock-type-face))))
+
+ (goto-char pos)))
+ (goto-char pos)))))
+ 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.
+
+ ;;(message "c-font-lock-declarators from %s to %s" (point) limit)
+ (c-fontify-types-and-refs
+ ((pos (point)) next-pos id-start id-end
+ paren-depth
+ id-face got-init
+ c-last-identifier-range
+ (separator-prop (if types 'c-decl-type-start 'c-decl-id-start)))
+
+ (while (and
+ pos
+ (< (point) limit)
+
+ (let (got-identifier)
+ (setq paren-depth 0)
+ ;; Skip over type decl prefix operators. (Note similar
+ ;; code in `c-font-lock-declarations'.)
+ (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
+ ;; 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))
+
+ ;; If we didn't pass the identifier above already, do it now.
+ (unless got-identifier
+ (setq id-start (point))
+ (c-forward-name))
+ (setq id-end (point))
+
+ (/= id-end pos))
+
+ ;; Skip out of the parens surrounding the identifier.
+ (or (= paren-depth 0)
+ (c-safe (goto-char (scan-lists (point) 1 paren-depth))))
+
+ (<= (point) limit)
+
+ ;; Search syntactically to the end of the declarator (";",
+ ;; ",", ")", ">" (for <> arglists), eob etc) or to the
+ ;; beginning of an initializer or function prototype ("="
+ ;; or "\\s\(").
+ (c-syntactic-re-search-forward
+ "[\];,\{\}\[\)>]\\|\\'\\|\\(=\\|\\(\\s\(\\)\\)" limit t t))
+
+ (setq next-pos (match-beginning 0)
+ id-face (if (match-beginning 2)
+ 'font-lock-function-name-face
+ 'font-lock-variable-name-face)
+ got-init (match-beginning 1))
+
+ (if types
+ ;; Register and fontify the identifer as a type.
+ (let ((c-promote-possible-types t))
+ (goto-char id-start)
+ (c-forward-type))
+ ;; Fontify the last symbol in the identifier if it isn't fontified
+ ;; already. The check is necessary only in certain cases where this
+ ;; function is used "sloppily", e.g. in `c-simple-decl-matchers'.
+ (when (and c-last-identifier-range
+ (not (get-text-property (car c-last-identifier-range)
+ 'face)))
+ (c-put-font-lock-face (car c-last-identifier-range)
+ (cdr c-last-identifier-range)
+ id-face)))
+
+ (goto-char next-pos)
+ (setq pos nil)
+ (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)
+ (c-forward-syntactic-ws limit)
+ (goto-char limit)))
+
+ (got-init
+ ;; Skip an initializer expression.
+ (if (c-syntactic-re-search-forward "[;,]" limit 'move t)
+ (backward-char)))
+
+ (t (c-forward-syntactic-ws limit)))
+
+ ;; If a ',' is found we set pos to the next declarator and iterate.
+ (when (and (< (point) limit) (looking-at ","))
+ (c-put-char-property (point) 'c-type separator-prop)
+ (forward-char)
+ (c-forward-syntactic-ws limit)
+ (setq pos (point))))))
+ nil)
+
+(defconst c-font-lock-maybe-decl-faces
+ ;; List of faces that might be put at the start of a type when
+ ;; `c-font-lock-declarations' runs. This needs to be evaluated to
+ ;; ensure that face name aliases in Emacs are resolved.
+ (list nil
+ font-lock-type-face
+ c-reference-face-name
+ font-lock-keyword-face))
+
+;; Macro used inside `c-font-lock-declarations'. It ought to be a
+;; defsubst or perhaps even a defun, but it contains lots of free
+;; variables that refer to things inside `c-font-lock-declarations'.
+(defmacro c-fl-shift-type-backward (&optional short)
+ ;; `c-font-lock-declarations' can consume an arbitrary length list
+ ;; of types when parsing a declaration, which means that it
+ ;; sometimes consumes the identifier in the declaration as a type.
+ ;; This is used to "backtrack" and make the last type be treated
+ ;; as an identifier instead.
+ `(progn
+ ,(unless short
+ ;; These identifiers are bound only in the inner let.
+ '(setq identifier-type at-type
+ identifier-start type-start
+ identifier-end type-end))
+ (if (setq at-type (if (eq prev-at-type 'prefix)
+ t
+ prev-at-type))
+ (setq type-start prev-type-start
+ type-end prev-type-end)
+ (setq type-start start-pos
+ type-end start-pos))
+ ,(unless short
+ ;; These identifiers are bound only in the inner let.
+ '(setq start type-end
+ got-parens nil
+ got-identifier t
+ got-suffix t
+ got-suffix-after-parens t
+ paren-depth 0))))
+
+(defun c-font-lock-declarations (limit)
+ ;; Fontify all the declarations and casts from the point to LIMIT.
+ ;; Assumes that strings and comments have been fontified already.
+ ;; Nil is always returned.
+ ;;
+ ;; This function can make hidden buffer changes, but the font-lock
+ ;; context covers that.
+
+ ;;(message "c-font-lock-declarations search from %s to %s" (point) limit)
+
+ (save-restriction
+ (let (start-pos
+ c-disallow-comma-in-<>-arglists
+ ;; Nonzero if the `c-decl-prefix-re' match is in an arglist context,
+ ;; as opposed to a statement-level context. The major difference is
+ ;; that "," works as declaration delimiter in an arglist context,
+ ;; whereas it only separates declarators in the same declaration in
+ ;; a statement context. If it's nonzero then the value is the
+ ;; matched char, e.g. ?\( or ?,.
+ arglist-match
+ ;; '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, 'other if
+ ;; it's some other arglist, or nil if not in an arglist at all.
+ arglist-type
+ ;; Set to the result of `c-forward-type'.
+ at-type
+ ;; These record the start and end of the type or possible type found
+ ;; by `c-forward-type'. `type-start' is at the start of the first
+ ;; type token, and `type-end' is at the start of the first token
+ ;; after the type (and after any specifiers).
+ type-start type-end
+ ;; These store `at-type', `type-start' and `type-end' of the
+ ;; identifier before the one in those variables. The previous
+ ;; identifier might turn out to be the real type in a declaration if
+ ;; the last one has to be the declarator in it. If `prev-at-type'
+ ;; is nil then the other variables have undefined values.
+ prev-at-type prev-type-start prev-type-end
+ ;; Whether we've found a declaration or a cast. We might know this
+ ;; before we've found the type in it.
+ at-decl-or-cast
+ ;; Set when we need to back up to parse this as a declaration but
+ ;; not as a cast.
+ backup-if-not-cast
+ ;; Set if we've found a "typedef" specifier. The identifiers in the
+ ;; declaration are then fontified as types.
+ at-typedef
+ ;; Set if we've found a specifier that can start a declaration where
+ ;; there's no type.
+ maybe-typeless
+ ;; The position of the next token after the closing paren of the
+ ;; last fontified cast.
+ last-cast-end
+ ;; The same for the currently investigated cast.
+ cast-end
+ ;; The maximum of the end positions of all the checked type decl
+ ;; expressions in the successfully identified declarations. The
+ ;; position might be either before or after the syntactic whitespace
+ ;; following the last token in the type decl expression.
+ (max-type-decl-end 0)
+ ;; Same as `max-type-decl-*', but used when we're before
+ ;; `token-pos'.
+ (max-type-decl-end-before-token 0)
+ ;; Allow recording of identifier ranges in `c-forward-type' etc for
+ ;; later fontification. Not using `c-fontify-types-and-refs' here
+ ;; since the ranges should be fontified selectively only when a
+ ;; declaration or cast has been successfully recognized.
+ c-record-type-identifiers
+ c-record-ref-identifiers
+ ;; 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))))
+
+ ;; 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
+ ;; time. That is however annoying during editing, e.g. the following is
+ ;; a common situation while the first line is being written:
+ ;;
+ ;; my_variable
+ ;; some_other_variable = 0;
+ ;;
+ ;; font-lock will put the limit at the beginning of the second line
+ ;; here, and if we go past it we'll fontify "my_variable" as a type and
+ ;; "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.
+ (when (<= 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 declaration (in
+ ;; particular the '{' that opens a function body after the header).
+ (goto-char limit)
+ (skip-chars-forward c-nonsymbol-chars)
+ (point))))
+
+ (c-find-decl-spots
+ limit
+ c-identifier-start
+ c-font-lock-maybe-decl-faces
+
+ (lambda (match-pos inside-macro)
+ (catch 'false-alarm
+ ;; Don't do anything more if we're looking at a keyword
+ ;; that can't start a declaration.
+ (when (and (eq (get-text-property (point) 'face)
+ 'font-lock-keyword-face)
+ (looking-at c-not-decl-init-keywords))
+ (throw 'false-alarm t))
+
+ ;; Set `arglist-match' and `arglist-type'. Look for "<" for the
+ ;; sake of C++-style template arglists.
+ (setq arglist-match (char-before match-pos))
+ (if (memq arglist-match '(?\( ?, ?\[ ?<))
+
+ ;; Find out the type of the arglist.
+ (if (<= match-pos (point-min))
+ (setq arglist-type 'other)
+ (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 arglist-type 'decl))
+ ((or (eq type 'c-<>-arg-sep)
+ (eq arglist-match ?<))
+ ;; Inside an angle bracket arglist.
+ (setq arglist-type '<>))
+ (type
+ ;; Got a cached hit in some other type of arglist.
+ (setq arglist-type 'other))
+ ((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 arglist-type '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 arglist-type 'other)))))
+
+ (setq arglist-match nil
+ arglist-type nil))
+
+ (setq at-type nil
+ at-decl-or-cast nil
+ backup-if-not-cast nil
+ at-typedef nil
+ maybe-typeless nil
+ c-record-type-identifiers t
+ c-record-ref-identifiers nil
+ ;; `start-pos' is used below to point to the start of the
+ ;; first type, i.e. after any leading specifiers. It might
+ ;; also point at the beginning of the preceding syntactic
+ ;; whitespace.
+ start-pos (point)
+ ;; 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.
+ c-disallow-comma-in-<>-arglists
+ (and c-recognize-<>-arglists
+ (eq arglist-type 'other)))
+
+ (when (and c-disallow-comma-in-<>-arglists
+ (/= arglist-match ?,))
+ ;; We're standing at the start of a normal arglist so remove any
+ ;; angle bracket arglists containing commas that's been
+ ;; recognized inside it by the preceding slightly opportunistic
+ ;; scan in `c-font-lock-<>-arglists'.
+ (while (and (c-syntactic-re-search-forward
+ c-opt-<>-arglist-start-in-paren nil t t)
+ (match-beginning 1))
+ (backward-char)
+ (when (save-match-data
+ (and (c-get-char-property (point) 'syntax-table)
+ (not (c-forward-<>-arglist nil t))))
+ (c-remove-font-lock-face (match-beginning 2) (match-end 2))))
+ (goto-char start-pos))
+
+ ;; Check for a type, but be prepared to skip over leading
+ ;; specifiers like "static". Unknown symbols are treated as
+ ;; possible types, but they could also be specifiers disguised
+ ;; through macros like __INLINE__, so we recognize both types and
+ ;; known specifiers after them too.
+ (while (let ((start (point))
+ (res (unless (eq at-type t)
+ ;; Don't look for a type if we already found a
+ ;; positive one; we only loop for the
+ ;; `c-specifier-key' check then.
+ (c-forward-type))))
+
+ (when res
+ ;; Found a known or possible type or a prefix of a known
+ ;; type.
+
+ (when at-type
+ ;; Got two identifiers with nothing but whitespace
+ ;; between them. That can only happen in
+ ;; declarations.
+ (setq at-decl-or-cast t)
+
+ (when (eq at-type 'found)
+ ;; If the previous identifier is a found type we
+ ;; record it as a real one; it might be some sort of
+ ;; alias for a prefix like "unsigned".
+ (save-excursion
+ (goto-char type-start)
+ (let ((c-promote-possible-types t))
+ (c-forward-type)))))
+
+ (setq prev-at-type at-type
+ prev-type-start type-start
+ prev-type-end type-end
+ at-type res
+ type-start start
+ type-end (point))
+
+ ;; If the type isn't known we continue so that we'll
+ ;; jump over all specifiers and type identifiers. The
+ ;; reason to do this for a known type prefix is to make
+ ;; things like "unsigned INT16" work.
+ (setq res (not (eq res t))))
+
+ (if (looking-at c-specifier-key)
+ ;; Found a known specifier keyword. The specifier
+ ;; keywords are restrictive, so we check for them
+ ;; anywhere inside or around the type(s). We thereby
+ ;; avoid having special cases for specifiers like MSVC
+ ;; '__declspec' which can come after the type.
+ (progn
+ (setq at-decl-or-cast t)
+ (let ((kwd-sym (c-keyword-sym (match-string 1))))
+ (when (c-keyword-member
+ kwd-sym 'c-typedef-decl-kwds)
+ (setq at-typedef t))
+ (when (c-keyword-member
+ kwd-sym 'c-typeless-decl-kwds)
+ (setq maybe-typeless t)))
+ (c-forward-keyword-clause)
+ ;; Move type-end forward if we've passed a type,
+ ;; otherwise move start-pos forward.
+ (if at-type
+ (setq type-end (point))
+ (setq start-pos (point))))
+
+ res)))
+
+ (cond
+ ((eq at-type 'prefix)
+ ;; A prefix type is itself a primitive type when it's not
+ ;; followed by another type.
+ (setq at-type t))
+
+ ((not at-type)
+ ;; Got no type but set things up to continue anyway to handle the
+ ;; various cases when a declaration doesn't start with a type.
+ (setq type-end start-pos))
+
+ ((and (eq at-type 'maybe)
+ (c-major-mode-is 'c++-mode))
+ ;; If it's C++ then check if the last "type" ends on the form
+ ;; "foo::foo" or "foo::~foo", i.e. if it's the name of a
+ ;; (con|de)structor.
+ (save-excursion
+ (let (name end-2 end-1)
+ (goto-char type-end)
+ (c-backward-syntactic-ws)
+ (setq end-2 (point))
+ (when (and
+ (c-simple-skip-symbol-backward)
+ (progn
+ (setq name
+ (buffer-substring-no-properties (point) end-2))
+ ;; Cheating in the handling of syntactic ws below.
+ (< (skip-chars-backward ":~ \t\n\r\v\f") 0))
+ (progn
+ (setq end-1 (point))
+ (c-simple-skip-symbol-backward))
+ (>= (point) type-start)
+ (equal (buffer-substring-no-properties (point) end-1)
+ name))
+ ;; It is a (con|de)structor name. In that case the
+ ;; declaration is typeless so zap out any preceding
+ ;; identifier(s) that we might have taken as types.
+ (goto-char type-start)
+ (setq at-type nil
+ prev-at-type nil
+ type-end type-start))))))
+
+ ;; Check for and step over a type decl expression after the thing
+ ;; that is or might be a type. This can't be skipped since we need
+ ;; the correct end position of the declarator for
+ ;; `max-type-decl-end-*'.
+ (let ((start (point)) (paren-depth 0) pos
+ ;; True if there's a non-open-paren match of
+ ;; `c-type-decl-prefix-key'.
+ got-prefix
+ ;; True if the declarator is surrounded by a parenthesis pair.
+ got-parens
+ ;; True if there is an identifier in the declarator.
+ got-identifier
+ ;; True if there's a non-close-paren match of
+ ;; `c-type-decl-suffix-key'.
+ got-suffix
+ ;; True if there's a prefix or suffix match outside the
+ ;; outermost paren pair that surrounds the declarator.
+ got-prefix-before-parens
+ got-suffix-after-parens
+ ;; True if we've parsed the type decl to a token that
+ ;; is known to end declarations in this context.
+ at-decl-end
+ ;; The earlier values of `at-type', `type-start' and
+ ;; `type-end' if we've shifted the type backwards.
+ identifier-type identifier-start identifier-end)
+ (goto-char type-end)
+
+ ;; Skip over type decl prefix operators. (Note similar code in
+ ;; `c-font-lock-declarators'.)
+ (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
+ ;; we're looking at an identifier that's a prefix
+ ;; only if it specifies a member pointer.
+ (when (setq got-identifier (c-forward-name))
+ (if (looking-at "\\(::\\)")
+ ;; We only check for a trailing "::" and
+ ;; let the "*" that should follow be
+ ;; matched in the next round.
+ (progn (setq got-identifier nil) t)
+ ;; It turned out to be the real identifier,
+ ;; so stop.
+ nil))
+ t))
+ (if (eq (char-after) ?\()
+ (progn
+ (setq paren-depth (1+ paren-depth))
+ (forward-char))
+ (unless got-prefix-before-parens
+ (setq got-prefix-before-parens (= paren-depth 0)))
+ (setq got-prefix t)
+ (goto-char (match-end 1)))
+ (c-forward-syntactic-ws))
+ (setq got-parens (> paren-depth 0))
+
+ ;; Skip over an identifier.
+ (or got-identifier
+ (and (looking-at c-identifier-start)
+ (setq got-identifier (c-forward-name))))
+
+ ;; Skip over type decl suffix operators.
+ (while (if (looking-at c-type-decl-suffix-key)
+ (if (eq (char-after) ?\))
+ (when (> paren-depth 0)
+ (setq paren-depth (1- paren-depth))
+ (forward-char)
+ t)
+ (when (if (save-match-data (looking-at "\\s\("))
+ (c-safe (c-forward-sexp 1) t)
+ (goto-char (match-end 1))
+ t)
+ (unless got-suffix-after-parens
+ (setq got-suffix-after-parens (= paren-depth 0)))
+ (setq got-suffix t)))
+ ;; No suffix matched. We might have matched the
+ ;; identifier as a type and the open paren of a function
+ ;; arglist as a type decl prefix. In that case we
+ ;; should "backtrack": Reinterpret the last type as the
+ ;; identifier, move out of the arglist and continue
+ ;; searching for suffix operators.
+ ;;
+ ;; Do this even if there's no preceding type, to cope
+ ;; with old style function declarations in K&R C,
+ ;; (con|de)structors in C++ and `c-typeless-decl-kwds'
+ ;; style declarations. That isn't applicable in an
+ ;; arglist context, though.
+ (when (and (= paren-depth 1)
+ (not got-prefix-before-parens)
+ (not (eq at-type t))
+ (or prev-at-type
+ maybe-typeless
+ (when c-recognize-typeless-decls
+ (not arglist-type)))
+ (setq pos (c-up-list-forward (point)))
+ (eq (char-before pos) ?\)))
+ (c-fl-shift-type-backward)
+ (goto-char pos)
+ t))
+ (c-forward-syntactic-ws))
+
+ (when (and maybe-typeless
+ (not got-identifier)
+ (not got-prefix)
+ at-type
+ (not (eq at-type t)))
+ ;; Have found no identifier but `c-typeless-decl-kwds' has
+ ;; matched so we know we're inside a declaration. The
+ ;; preceding type must be the identifier instead.
+ (c-fl-shift-type-backward))
+
+ (setq
+ at-decl-or-cast
+ (catch 'at-decl-or-cast
+
+ (when (> paren-depth 0)
+ ;; Encountered something inside parens that isn't matched by
+ ;; the `c-type-decl-*' regexps, so it's not a type decl
+ ;; expression. Try to skip out to the same paren depth to
+ ;; not confuse the cast check below.
+ (c-safe (goto-char (scan-lists (point) 1 paren-depth)))
+ (throw 'at-decl-or-cast nil))
+
+ (setq at-decl-end
+ (looking-at (cond ((eq arglist-type '<>) "[,>]")
+ (arglist-type "[,\)]")
+ (t "[,;]"))))
+
+ ;; Now we've collected info about various characteristics of
+ ;; the construct we're looking at. Below follows a decision
+ ;; tree based on that. It's ordered to check more certain
+ ;; signs before less certain ones.
+
+ (if got-identifier
+ (progn
+
+ (when (and (or at-type maybe-typeless)
+ (not (or got-prefix got-parens)))
+ ;; Got another identifier directly after the type, so
+ ;; it's a declaration.
+ (throw 'at-decl-or-cast t))
+
+ (when (and got-parens
+ (not got-prefix)
+ (not got-suffix-after-parens)
+ (or prev-at-type maybe-typeless))
+ ;; Got a declaration of the form "foo bar (gnu);"
+ ;; where we've recognized "bar" as the type and "gnu"
+ ;; as the declarator. In this case it's however more
+ ;; likely that "bar" is the declarator and "gnu" a
+ ;; function argument or initializer (if
+ ;; `c-recognize-paren-inits' is set), since the parens
+ ;; around "gnu" would be superfluous if it's a
+ ;; declarator. Shift the type one step backward.
+ (c-fl-shift-type-backward)))
+
+ ;; Found no identifier.
+
+ (if prev-at-type
+ (when (or (= (point) start)
+ (and got-suffix
+ (not got-prefix)
+ (not got-parens)))
+ ;; Got two types after each other, so if this isn't a
+ ;; cast then the latter probably is the identifier and
+ ;; we should back up to the previous type.
+ (setq backup-if-not-cast t)
+ (throw 'at-decl-or-cast t))
+
+ (when (eq at-type t)
+ ;; If the type is known we know that there can't be any
+ ;; identifier somewhere else, and it's only in
+ ;; declarations in e.g. function prototypes and in casts
+ ;; that the identifier may be left out.
+ (throw 'at-decl-or-cast t))
+
+ (when (= (point) start)
+ ;; Only got a single identifier (parsed as a type so
+ ;; far).
+ (if (and
+ ;; Check that the identifier isn't at the start of
+ ;; an expression.
+ at-decl-end
+ (cond
+ ((eq arglist-type 'decl)
+ ;; Inside an arglist that contains declarations.
+ ;; If K&R style declarations and parenthesis
+ ;; style initializers aren't allowed then the
+ ;; single identifier must be a type, else we
+ ;; require that it's known or found (primitive
+ ;; types are handled above).
+ (or (and (not c-recognize-knr-p)
+ (not c-recognize-paren-inits))
+ (memq at-type '(known found))))
+ ((eq arglist-type '<>)
+ ;; Inside a template arglist. Accept known and
+ ;; found types; other identifiers could just as
+ ;; well be constants in C++.
+ (memq at-type '(known found)))))
+ (throw 'at-decl-or-cast t)
+ (throw 'at-decl-or-cast nil))))
+
+ (if (and
+ got-parens
+ (not got-prefix)
+ (not arglist-type)
+ (not (eq at-type t))
+ (or
+ prev-at-type
+ maybe-typeless
+ (when c-recognize-typeless-decls
+ (or (not got-suffix)
+ (not (looking-at
+ c-after-suffixed-type-maybe-decl-key))))))
+ ;; Got an empty paren pair and a preceding type that
+ ;; probably really is the identifier. Shift the type
+ ;; backwards to make the last one the identifier. This
+ ;; is analogous to the "backtracking" done inside the
+ ;; `c-type-decl-suffix-key' loop above.
+ ;;
+ ;; Exception: In addition to the conditions in that
+ ;; "backtracking" code, do not shift backward if we're
+ ;; not looking at either `c-after-suffixed-type-decl-key'
+ ;; or "[;,]". Since there's no preceding type, the
+ ;; shift would mean that the declaration is typeless.
+ ;; But if the regexp doesn't match then we will simply
+ ;; fall through in the tests below and not recognize it
+ ;; at all, so it's better to try it as an abstract
+ ;; declarator instead.
+ (c-fl-shift-type-backward)
+
+ ;; Still no identifier.
+
+ (when (and got-prefix (or got-parens got-suffix))
+ ;; Require `got-prefix' together with either
+ ;; `got-parens' or `got-suffix' to recognize it as an
+ ;; abstract declarator: `got-parens' only is probably an
+ ;; empty function call. `got-suffix' only can build an
+ ;; ordinary expression together with the preceding
+ ;; identifier which we've taken as a type. We could
+ ;; actually accept on `got-prefix' only, but that can
+ ;; easily occur temporarily while writing an expression
+ ;; so we avoid that case anyway. We could do a better
+ ;; job if we knew the point when the fontification was
+ ;; invoked.
+ (throw 'at-decl-or-cast t))))
+
+ (when at-decl-or-cast
+ ;; By now we've located the type in the declaration that we
+ ;; know we're in.
+ (throw 'at-decl-or-cast t))
+
+ (when (and got-identifier
+ (not arglist-type)
+ (looking-at c-after-suffixed-type-decl-key)
+ (if (and got-parens
+ (not got-prefix)
+ (not got-suffix)
+ (not (eq at-type t)))
+ ;; Shift the type backward in the case that
+ ;; there's a single identifier inside parens.
+ ;; That can only occur in K&R style function
+ ;; declarations so it's more likely that it
+ ;; really is a function call. Therefore we
+ ;; only do this after
+ ;; `c-after-suffixed-type-decl-key' has
+ ;; matched.
+ (progn (c-fl-shift-type-backward) t)
+ got-suffix-after-parens))
+ ;; A declaration according to
+ ;; `c-after-suffixed-type-decl-key'.
+ (throw 'at-decl-or-cast t))
+
+ (when (and (or got-prefix (not got-parens))
+ (memq at-type '(t known)))
+ ;; It's a declaration if a known type precedes it and it
+ ;; can't be a function call.
+ (throw 'at-decl-or-cast t))
+
+ ;; If we get here we can't tell if this is a type decl or a
+ ;; normal expression by looking at it alone. (That's under
+ ;; the assumption that normal expressions always can look like
+ ;; type decl expressions, which isn't really true but the
+ ;; cases where it doesn't hold are so uncommon (e.g. some
+ ;; placements of "const" in C++) it's not worth the effort to
+ ;; look for them.)
+
+ (unless (or at-decl-end (looking-at "=[^=]"))
+ ;; If this is a declaration it should end here or its
+ ;; initializer(*) should start here, so check for allowed
+ ;; separation tokens. Note that this rule doesn't work
+ ;; e.g. with a K&R arglist after a function header.
+ ;;
+ ;; *) Don't check for C++ style initializers using parens
+ ;; since those already have been matched as suffixes.
+ (throw 'at-decl-or-cast nil))
+
+ ;; Below are tests that only should be applied when we're
+ ;; certain to not have parsed halfway through an expression.
+
+ (when (memq at-type '(t known))
+ ;; The expression starts with a known type so treat it as a
+ ;; declaration.
+ (throw 'at-decl-or-cast t))
+
+ (when (and (c-major-mode-is 'c++-mode)
+ ;; In C++ we check if the identifier is a known
+ ;; type, since (con|de)structors use the class name
+ ;; as identifier. We've always shifted over the
+ ;; identifier as a type and then backed up again in
+ ;; this case.
+ identifier-type
+ (or (eq identifier-type 'found)
+ (and (eq (char-after identifier-start) ?~)
+ ;; `at-type' probably won't be 'found for
+ ;; destructors since the "~" is then part
+ ;; of the type name being checked against
+ ;; the list of known types, so do a check
+ ;; without that operator.
+ (c-check-type (1+ identifier-start)
+ identifier-end))))
+ (throw 'at-decl-or-cast t))
+
+ (if got-identifier
+ (progn
+ (when (and got-prefix-before-parens
+ at-type
+ (or at-decl-end (looking-at "=[^=]"))
+ (not arglist-type)
+ (not got-suffix))
+ ;; Got something like "foo * bar;". Since we're not
+ ;; inside an arglist it would be a meaningless
+ ;; expression because the result isn't used. We
+ ;; therefore choose to recognize it as a declaration.
+ ;; Do not allow a suffix since it could then be a
+ ;; function call.
+ (throw 'at-decl-or-cast t))
+
+ (when (and (or got-suffix-after-parens
+ (looking-at "=[^=]"))
+ (eq at-type 'found)
+ (not (eq arglist-type 'other)))
+ ;; Got something like "a (*b) (c);" or "a (b) = c;".
+ ;; It could be an odd expression or it could be a
+ ;; declaration. Treat it as a declaration if "a" has
+ ;; been used as a type somewhere else (if it's a known
+ ;; type we won't get here).
+ (throw 'at-decl-or-cast t)))
+
+ (when (and arglist-type
+ (or got-prefix
+ (and (eq arglist-type 'decl)
+ (not c-recognize-paren-inits)
+ (or got-parens got-suffix))))
+ ;; Got a type followed by an abstract declarator. If
+ ;; `got-prefix' is set it's something like "a *" without
+ ;; anything after it. If `got-parens' or `got-suffix' is
+ ;; set it's "a()", "a[]", "a()[]", or similar, which we
+ ;; accept only if the context rules out expressions.
+ (throw 'at-decl-or-cast t)))
+
+ ;; If we had a complete symbol table here (which rules out
+ ;; `c-found-types') we should return t due to the
+ ;; disambiguation rule (in at least C++) that anything that
+ ;; can be parsed as a declaration is a declaration. Now we're
+ ;; being more defensive and prefer to highlight things like
+ ;; "foo (bar);" as a declaration only if we're inside an
+ ;; arglist that contains declarations.
+ (eq arglist-type 'decl))))
+
+ ;; Point is now after the type decl expression.
+
+ (cond
+ ;; Check for a cast.
+ ((save-excursion
+ (and
+ c-cast-parens
+
+ ;; Should be the first type/identifier in a cast paren.
+ (memq arglist-match c-cast-parens)
+
+ ;; The closing paren should follow.
+ (progn
+ (c-forward-syntactic-ws)
+ (looking-at "\\s\)"))
+
+ ;; There should be a primary expression after it.
+ (let (pos)
+ (forward-char)
+ (c-forward-syntactic-ws)
+ (setq cast-end (point))
+ (and (looking-at c-primary-expr-regexp)
+ (progn
+ (setq pos (match-end 0))
+ (or
+ ;; Check if the expression begins with a prefix
+ ;; keyword.
+ (match-beginning 2)
+ (if (match-beginning 1)
+ ;; Expression begins with an ambiguous operator.
+ ;; Treat it as a cast if it's a type decl or if
+ ;; we've recognized the type somewhere else.
+ (or at-decl-or-cast
+ (memq at-type '(t known found)))
+ ;; Unless it's a keyword, it's the beginning of a
+ ;; primary expression.
+ (not (looking-at c-keywords-regexp)))))
+ ;; If `c-primary-expr-regexp' matched a nonsymbol
+ ;; token, check that it matched a whole one so that we
+ ;; don't e.g. confuse the operator '-' with '->'. It's
+ ;; ok if it matches further, though, since it e.g. can
+ ;; match the float '.5' while the operator regexp only
+ ;; matches '.'.
+ (or (not (looking-at c-nonsymbol-token-regexp))
+ (<= (match-end 0) pos))))
+
+ ;; There should either be a cast before it or something that
+ ;; isn't an identifier or close paren.
+ (/= match-pos 0)
+ (progn
+ (goto-char (1- match-pos))
+ (or (eq (point) last-cast-end)
+ (progn
+ (c-backward-syntactic-ws)
+ (if (< (skip-syntax-backward "w_") 0)
+ ;; It's a symbol. Accept it only if it's one of
+ ;; the keywords that can precede an expression
+ ;; (without surrounding parens).
+ (looking-at c-simple-stmt-key)
+ (and
+ ;; Check that it isn't a close paren (block close
+ ;; is ok, though).
+ (not (memq (char-before) '(?\) ?\])))
+ ;; Check that it isn't a nonsymbol identifier.
+ (not (c-on-identifier)))))))))
+
+ ;; Handle the cast.
+ (setq last-cast-end cast-end)
+ (when (and at-type (not (eq at-type t)))
+ (let ((c-promote-possible-types t))
+ (goto-char type-start)
+ (c-forward-type))))
+
+ (at-decl-or-cast
+ ;; We're at a declaration. Highlight the type and the following
+ ;; declarators.
+
+ (when backup-if-not-cast
+ (c-fl-shift-type-backward t))
+
+ (when (and (eq arglist-type 'decl) (looking-at ","))
+ ;; Make sure to propagate the `c-decl-arg-start' property to
+ ;; the next argument if it's set in this one, to cope with
+ ;; interactive refontification.
+ (c-put-char-property (point) 'c-type 'c-decl-arg-start))
+
+ ;; 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))))
+
+ (when (and at-type (not (eq at-type t)))
+ (let ((c-promote-possible-types t))
+ (goto-char type-start)
+ (c-forward-type)))
+
+ (goto-char type-end)
+
+ (let ((decl-list
+ (if arglist-type
+ ;; 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 (and (eq arglist-match ?\() (/= match-pos 0))
+ (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 at-typedef
+ 'c-decl-type-start
+ 'c-decl-id-start)))))
+
+ (c-font-lock-declarators (point-max) decl-list at-typedef)))
+
+ (t
+ ;; False alarm. Skip the fontification done below.
+ (throw 'false-alarm t)))
+
+ ;; A cast or declaration has been successfully identified, so do
+ ;; all the fontification of types and refs that's been recorded by
+ ;; the calls to `c-forward-type' and `c-forward-name' above.
+ (c-fontify-recorded-types-and-refs)
+ nil)))
+
+ nil)))
+
+(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'."
+
+ t `(;; Objective-C methods.
+ ,@(when (c-major-mode-is 'objc-mode)
+ `((,(c-lang-const c-opt-method-key)
+ (,(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))))
+ (save-restriction
+ (narrow-to-region (point-min) limit)
+ (c-font-lock-objc-method)))
+ nil))
+ (goto-char (match-end 1))))))
+
+ ;; Fontify all type names and the identifiers in the
+ ;; declarations they might start. Use eval here since
+ ;; `c-known-type-key' gets its value from
+ ;; `*-font-lock-extra-types' on mode init.
+ (eval . (list ,(c-make-font-lock-search-function
+ 'c-known-type-key
+ '(1 'font-lock-type-face t)
+ '((c-font-lock-declarators limit t nil)
+ (save-match-data
+ (goto-char (match-end 1))
+ (c-forward-syntactic-ws))
+ (goto-char (match-end 1))))))
+
+ ;; Fontify types preceded by `c-type-prefix-kwds' and the
+ ;; identifiers in the declarations they might start.
+ ,@(when (c-lang-const c-type-prefix-kwds)
+ (let ((prefix-re (c-make-keywords-re nil
+ (c-lang-const c-type-prefix-kwds))))
+ `((,(c-make-font-lock-search-function
+ (concat "\\<\\(" prefix-re "\\)"
+ "[ \t\n\r\f\v]+"
+ "\\(" (c-lang-const c-symbol-key) "\\)")
+ `(,(+ (c-regexp-opt-depth prefix-re) 2)
+ 'font-lock-type-face t)
+ '((c-font-lock-declarators limit t nil)
+ (save-match-data
+ (goto-char (match-end 2))
+ (c-forward-syntactic-ws))
+ (goto-char (match-end 2))))))))
+
+ ;; Fontify special declarations that lacks a type.
+ ,@(when (c-lang-const c-typeless-decl-kwds)
+ `((,(c-make-font-lock-search-function
+ (concat "\\<\\("
+ (c-regexp-opt (c-lang-const c-typeless-decl-kwds))
+ "\\)\\>")
+ '((c-font-lock-declarators limit t nil)
+ (save-match-data
+ (goto-char (match-end 1))
+ (c-forward-syntactic-ws))
+ (goto-char (match-end 1)))))))
+ ))
+
+(c-lang-defconst c-complex-decl-matchers
+ "Complex font lock matchers for types and declarations. Used on level
+3 and higher."
+
+ t `(;; Initialize some things before the search functions below.
+ c-font-lock-complex-decl-prepare
+
+ ;; Fontify angle bracket arglists like templates in C++.
+ ,@(when (c-lang-const c-recognize-<>-arglists)
+ `(c-font-lock-<>-arglists))
+
+ ,@(if (c-major-mode-is 'objc-mode)
+ ;; Fontify method declarations in Objective-C, but first
+ ;; we have to put the `c-decl-end' `c-type' property on
+ ;; all the @-style directives that haven't been handled in
+ ;; `c-basic-matchers-before'.
+ `(,(c-make-font-lock-search-function
+ (c-make-keywords-re t
+ ;; Exclude "@class" since that directive ends with a
+ ;; semicolon anyway.
+ (delete "@class"
+ (append (c-lang-const c-protection-kwds)
+ (c-lang-const c-other-decl-kwds)
+ nil)))
+ '((c-put-char-property (1- (match-end 1))
+ 'c-type 'c-decl-end)))
+
+ c-font-lock-objc-methods)
+
+ (when (c-lang-const c-opt-access-key)
+ `(,(c-make-font-lock-search-function
+ (c-lang-const c-opt-access-key)
+ '((c-put-char-property (1- (match-end 0))
+ 'c-type 'c-decl-end))))))
+
+ ;; Fontify all declarations and casts.
+ c-font-lock-declarations
+
+ ;; The first two rules here mostly find occurences that
+ ;; `c-font-lock-declarations' has found already, but not
+ ;; declarations containing blocks in the type (see note below).
+ ;; It's also useful to fontify these everywhere to show e.g. when
+ ;; a type keyword is accidentally used as an identifier.
+
+ ;; Fontify basic types.
+ ,(let ((re (c-make-keywords-re nil
+ (c-lang-const c-primitive-type-kwds))))
+ (if (c-major-mode-is 'pike-mode)
+ ;; No symbol is a keyword after "->" in Pike.
+ `(,(concat "\\(\\=\\|\\(\\=\\|[^-]\\)[^>]\\)"
+ "\\<\\(" re "\\)\\>")
+ 3 font-lock-type-face)
+ `(,(concat "\\<\\(" re "\\)\\>")
+ 1 'font-lock-type-face)))
+
+ ;; Fontify types preceded by `c-type-prefix-kwds'.
+ ,@(when (c-lang-const c-type-prefix-kwds)
+ `((,(byte-compile
+ `(lambda (limit)
+ (c-fontify-types-and-refs
+ ((c-promote-possible-types t)
+ ;; 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))))
+ (save-restriction
+ ;; Narrow to avoid going past the limit in
+ ;; `c-forward-type'.
+ (narrow-to-region (point) limit)
+ (while (re-search-forward
+ ,(concat "\\<\\("
+ (c-make-keywords-re nil
+ (c-lang-const c-type-prefix-kwds))
+ "\\)\\>")
+ limit t)
+ (unless (c-skip-comments-and-strings limit)
+ (c-forward-syntactic-ws)
+ ;; Handle prefix declaration specifiers.
+ (when (looking-at c-specifier-key)
+ (c-forward-keyword-clause))
+ ,(if (c-major-mode-is 'c++-mode)
+ `(when (and (c-forward-type)
+ (eq (char-after) ?=))
+ ;; In C++ we additionally check for a "class
+ ;; X = Y" construct which is used in
+ ;; templates, to fontify Y as a type.
+ (forward-char)
+ (c-forward-syntactic-ws)
+ (c-forward-type))
+ `(c-forward-type))
+ )))))))))
+
+ ;; Fontify symbols after closing braces as declaration
+ ;; identifiers under the assumption that they are part of
+ ;; declarations like "class Foo { ... } foo;". It's too
+ ;; expensive to check this accurately by skipping past the
+ ;; brace block, so we use the heuristic that it's such a
+ ;; declaration if the first identifier is on the same line as
+ ;; the closing brace. `c-font-lock-declarations' will later
+ ;; 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)))))))
+
+ ;; Fontify the type in C++ "new" expressions.
+ ,@(when (c-major-mode-is 'c++-mode)
+ `(("\\<new\\>"
+ (c-font-lock-c++-new))))
+ ))
+
+(defun c-font-lock-labels (limit)
+ ;; Fontify all the declarations from the point to LIMIT. Assumes
+ ;; that strings and comments have been fontified already. Nil is
+ ;; always returned.
+ ;;
+ ;; This function can make hidden buffer changes, but the font-lock
+ ;; context covers that.
+
+ (let (continue-pos id-start
+ ;; 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 ":[^:]" limit t)
+ (setq continue-pos (point))
+ (goto-char (match-beginning 0))
+ (unless (c-skip-comments-and-strings limit)
+
+ (c-backward-syntactic-ws)
+ (and (setq id-start (c-on-identifier))
+
+ (not (get-text-property id-start 'face))
+
+ (progn
+ (goto-char id-start)
+ (c-backward-syntactic-ws)
+ (or
+ ;; Check for a char that precedes a statement.
+ (memq (char-before) '(?\} ?\{ ?\;))
+ ;; Check for a preceding label. We exploit the font
+ ;; locking made earlier by this function.
+ (and (eq (char-before) ?:)
+ (progn
+ (backward-char)
+ (c-backward-syntactic-ws)
+ (not (bobp)))
+ (eq (get-text-property (1- (point)) 'face)
+ c-label-face-name))
+ ;; Check for a keyword that precedes a statement.
+ (c-after-conditional)))
+
+ (progn
+ ;; Got a label.
+ (goto-char id-start)
+ (looking-at c-symbol-key)
+ (c-put-font-lock-face (match-beginning 0) (match-end 0)
+ c-label-face-name)))
+
+ (goto-char continue-pos))))
+ nil)
+
+(c-lang-defconst c-basic-matchers-after
+ "Font lock matchers for various things that should be fontified after
+generic casts and declarations are fontified. Used on level 2 and
+higher."
+
+ t `(;; 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
+ (concat
+ "\\<\\("
+ (c-make-keywords-re nil (c-lang-const c-brace-id-list-kwds))
+ "\\)\\>"
+ ;; 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
+ (goto-char (match-end 0))
+ (c-put-char-property (1- (point)) 'c-type
+ 'c-decl-id-start)
+ (c-forward-syntactic-ws))
+ (goto-char (match-end 0)))))))
+
+ ;; Fontify labels in languages that supports them.
+ ,@(when (c-lang-const c-label-key)
+
+ `(;; Fontify labels after goto etc.
+ ;; (Got three different interpretation levels here,
+ ;; which makes it a bit complicated: 1) The backquote
+ ;; stuff is expanded when compiled or loaded, 2) the
+ ;; eval form is evaluated at font-lock setup (to
+ ;; substitute c-label-face-name correctly), and 3) the
+ ;; resulting structure is interpreted during
+ ;; fontification.)
+ (eval
+ . ,(let* ((c-before-label-re
+ (c-make-keywords-re nil
+ (c-lang-const c-before-label-kwds))))
+ `(list
+ ,(concat "\\<\\(" c-before-label-re "\\)\\>"
+ "\\s *"
+ "\\(" ; identifier-offset
+ (c-lang-const c-symbol-key)
+ "\\)")
+ (list ,(+ (c-regexp-opt-depth c-before-label-re) 2)
+ c-label-face-name nil t))))
+
+ ;; Fontify normal labels.
+ c-font-lock-labels))
+
+ ;; 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)
+ (if (> (point) limit) (goto-char limit))))))))
+ ))
+
+(c-lang-defconst c-matchers-1
+ t (c-lang-const c-cpp-matchers))
+
+(c-lang-defconst c-matchers-2
+ t (append (c-lang-const c-matchers-1)
+ (c-lang-const c-basic-matchers-before)
+ (c-lang-const c-simple-decl-matchers)
+ (c-lang-const c-basic-matchers-after)))
+
+(c-lang-defconst c-matchers-3
+ t (append (c-lang-const c-matchers-1)
+ (c-lang-const c-basic-matchers-before)
+ (c-lang-const c-complex-decl-matchers)
+ (c-lang-const c-basic-matchers-after)))
+
+(defun c-compose-keywords-list (base-list)
+ ;; Incorporate the font lock keyword lists according to
+ ;; `c-doc-comment-style' on the given keyword list and return it.
+ ;; This is used in the function bindings of the
+ ;; `*-font-lock-keywords-*' symbols since we have to build the list
+ ;; when font-lock is initialized.
+
+ (unless (memq c-doc-face-name c-literal-faces)
+ (setq c-literal-faces (cons c-doc-face-name c-literal-faces)))
+
+ (let* ((doc-keywords
+ (if (consp (car-safe c-doc-comment-style))
+ (cdr-safe (or (assq c-buffer-is-cc-mode c-doc-comment-style)
+ (assq 'other c-doc-comment-style)))
+ c-doc-comment-style))
+ (list (nconc (apply 'nconc
+ (mapcar
+ (lambda (doc-style)
+ (let ((sym (intern
+ (concat (symbol-name doc-style)
+ "-font-lock-keywords"))))
+ (cond ((fboundp sym)
+ (funcall sym))
+ ((boundp sym)
+ (append (eval sym) nil)))))
+ (if (listp doc-keywords)
+ doc-keywords
+ (list doc-keywords))))
+ base-list)))
+
+ ;; Kludge: If `c-font-lock-complex-decl-prepare' is on the list we
+ ;; move it first since the doc comment font lockers might add
+ ;; `c-type' text properties so they have to be cleared before that.
+ (when (memq 'c-font-lock-complex-decl-prepare list)
+ (setq list (cons 'c-font-lock-complex-decl-prepare
+ (delq 'c-font-lock-complex-decl-prepare
+ (append list nil)))))
+
+ list))
+
+(defun c-override-default-keywords (def-var)
+ ;; This is used to override the value on a `*-font-lock-keywords'
+ ;; variable only if it's nil or has the same value as one of the
+ ;; `*-font-lock-keywords-*' variables. Older font-lock packages
+ ;; define a default value for `*-font-lock-keywords' which we want
+ ;; to override, but we should otoh avoid clobbering a user setting.
+ ;; This heuristic for that isn't perfect, but I can't think of any
+ ;; better. /mast
+ ;;
+ ;; This function does not do any hidden buffer changes.
+ (when (and (boundp def-var)
+ (memq (symbol-value def-var)
+ (cons nil
+ (mapcar
+ (lambda (suffix)
+ (let ((sym (intern (concat (symbol-name def-var)
+ suffix))))
+ (and (boundp sym) (symbol-value sym))))
+ '("-1" "-2" "-3")))))
+ ;; The overriding is done by unbinding the variable so that the normal
+ ;; defvar will install its default value later on.
+ (makunbound def-var)))
+
+
+;;; C.
+
+(c-override-default-keywords 'c-font-lock-keywords)
+
+(defconst c-font-lock-keywords-1 (c-lang-const c-matchers-1 c)
+ "Minimal font locking for C mode.
+Fontifies only preprocessor directives (in addition to the syntactic
+fontification of strings and comments).")
+
+(defconst c-font-lock-keywords-2 (c-lang-const c-matchers-2 c)
+ "Fast normal font locking for C mode.
+In addition to `c-font-lock-keywords-1', this adds fontification of
+keywords, simple types, declarations that are easy to recognize, the
+user defined types on `c-font-lock-extra-types', and the doc comment
+styles specified by `c-doc-comment-style'.")
+
+(defconst c-font-lock-keywords-3 (c-lang-const c-matchers-3 c)
+ "Accurate normal font locking for C mode.
+Like `c-font-lock-keywords-2' but detects declarations in a more
+accurate way that works in most cases for arbitrary types without the
+need for `c-font-lock-extra-types'.")
+
+(defvar c-font-lock-keywords c-font-lock-keywords-3
+ "Default expressions to highlight in C mode.")
+
+(defun c-font-lock-keywords-2 ()
+ (c-compose-keywords-list c-font-lock-keywords-2))
+(defun c-font-lock-keywords-3 ()
+ (c-compose-keywords-list c-font-lock-keywords-3))
+(defun c-font-lock-keywords ()
+ (c-compose-keywords-list c-font-lock-keywords))
+
+
+;;; C++.
+
+(defun c-font-lock-c++-new (limit)
+ ;; 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.
+ ;;
+ ;; As usual, C++ takes the prize in coming up with a hard to parse
+ ;; syntax. :P
+
+ (unless (c-skip-comments-and-strings limit)
+ (save-excursion
+ (catch 'false-alarm
+ ;; A "new" keyword is followed by one to three expressions, where
+ ;; the type is the middle one, and the only required part.
+ (let (expr1-pos expr2-pos
+ ;; Enable recording of identifier ranges in `c-forward-type'
+ ;; etc for later fontification. Not using
+ ;; `c-fontify-types-and-refs' here since the ranges should
+ ;; be fontified selectively only when an allocation
+ ;; expression is successfully recognized.
+ (c-record-type-identifiers t)
+ c-record-ref-identifiers
+ ;; 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))))
+ (c-forward-syntactic-ws)
+
+ ;; The first placement arglist is always parenthesized, if it
+ ;; exists.
+ (when (eq (char-after) ?\()
+ (setq expr1-pos (1+ (point)))
+ (condition-case nil
+ (c-forward-sexp)
+ (scan-error (throw 'false-alarm t)))
+ (c-forward-syntactic-ws))
+
+ ;; The second expression is either a type followed by some "*" or
+ ;; "[...]" or similar, or a parenthesized type followed by a full
+ ;; identifierless declarator.
+ (setq expr2-pos (1+ (point)))
+ (cond ((eq (char-after) ?\())
+ ((let ((c-promote-possible-types t))
+ (c-forward-type)))
+ (t (setq expr2-pos nil)))
+
+ (when expr1-pos
+ (cond
+ ((not expr2-pos)
+ ;; No second expression, so the first has to be a
+ ;; parenthesized type.
+ (goto-char expr1-pos)
+ (let ((c-promote-possible-types t))
+ (c-forward-type)))
+
+ ((eq (char-before expr2-pos) ?\()
+ ;; Got two parenthesized expressions, so we have to look
+ ;; closer at them to decide which is the type. No need to
+ ;; handle `c-record-ref-identifiers' since all references
+ ;; has already been handled by other fontification rules.
+ (let (expr1-res expr2-res)
+
+ (goto-char expr1-pos)
+ (when (setq expr1-res (c-forward-type))
+ (unless (looking-at
+ (cc-eval-when-compile
+ (concat (c-lang-const c-symbol-start c++)
+ "\\|[*:\)\[]")))
+ ;; There's something after the would-be type that
+ ;; can't be there, so this is a placement arglist.
+ (setq expr1-res nil)))
+
+ (goto-char expr2-pos)
+ (when (setq expr2-res (c-forward-type))
+ (unless (looking-at
+ (cc-eval-when-compile
+ (concat (c-lang-const c-symbol-start c++)
+ "\\|[*:\)\[]")))
+ ;; There's something after the would-be type that can't
+ ;; be there, so this is an initialization expression.
+ (setq expr2-res nil))
+ (when (and (c-go-up-list-forward)
+ (progn (c-forward-syntactic-ws)
+ (eq (char-after) ?\()))
+ ;; If there's a third initialization expression
+ ;; then the second one is the type, so demote the
+ ;; first match.
+ (setq expr1-res nil)))
+
+ ;; We fontify the most likely type, with a preference for
+ ;; the first argument since a placement arglist is more
+ ;; unusual than an initializer.
+ (cond ((memq expr1-res '(t known prefix)))
+ ((memq expr2-res '(t known prefix)))
+ ((eq expr1-res 'found)
+ (let ((c-promote-possible-types t))
+ (goto-char expr1-pos)
+ (c-forward-type)))
+ ((eq expr2-res 'found)
+ (let ((c-promote-possible-types t))
+ (goto-char expr2-pos)
+ (c-forward-type)))
+ ((and (eq expr1-res 'maybe) (not expr2-res))
+ (let ((c-promote-possible-types t))
+ (goto-char expr1-pos)
+ (c-forward-type)))
+ ((and (not expr1-res) (eq expr2-res 'maybe))
+ (let ((c-promote-possible-types t))
+ (goto-char expr2-pos)
+ (c-forward-type)))
+ ;; If both type matches are 'maybe then we're
+ ;; too uncertain to promote either of them.
+ )))))
+
+ ;; Fontify the type that now is recorded in
+ ;; `c-record-type-identifiers', if any.
+ (c-fontify-recorded-types-and-refs)))))
+ nil)
+
+(c-override-default-keywords 'c++-font-lock-keywords)
+
+(defconst c++-font-lock-keywords-1 (c-lang-const c-matchers-1 c++)
+ "Minimal font locking for C++ mode.
+Fontifies only preprocessor directives (in addition to the syntactic
+fontification of strings and comments).")
+
+(defconst c++-font-lock-keywords-2 (c-lang-const c-matchers-2 c++)
+ "Fast normal font locking for C++ mode.
+In addition to `c++-font-lock-keywords-1', this adds fontification of
+keywords, simple types, declarations that are easy to recognize, the
+user defined types on `c++-font-lock-extra-types', and the doc comment
+styles specified by `c-doc-comment-style'.")
+
+(defconst c++-font-lock-keywords-3 (c-lang-const c-matchers-3 c++)
+ "Accurate normal font locking for C++ mode.
+Like `c++-font-lock-keywords-2' but detects declarations in a more
+accurate way that works in most cases for arbitrary types without the
+need for `c++-font-lock-extra-types'.")
+
+(defvar c++-font-lock-keywords c++-font-lock-keywords-3
+ "Default expressions to highlight in C++ mode.")
+
+(defun c++-font-lock-keywords-2 ()
+ (c-compose-keywords-list c++-font-lock-keywords-2))
+(defun c++-font-lock-keywords-3 ()
+ (c-compose-keywords-list c++-font-lock-keywords-3))
+(defun c++-font-lock-keywords ()
+ (c-compose-keywords-list c++-font-lock-keywords))
+
+
+;;; Objective-C.
+
+(defun c-font-lock-objc-iip-decl ()
+ ;; Assuming the point is after an "@interface", "@implementation",
+ ;; "@protocol" declaration, fontify all the types in the directive.
+ ;; Return t if the directive was fully recognized. Point will then
+ ;; be at the end of it.
+
+ (c-fontify-types-and-refs
+ (start-char
+ (c-promote-possible-types t)
+ ;; Turn off recognition of angle bracket arglists while parsing
+ ;; types here since the protocol reference list might then be
+ ;; considered part of the preceding name or superclass-name.
+ c-recognize-<>-arglists)
+ (catch 'break
+
+ ;; Handle the name of the class itself.
+ (c-forward-syntactic-ws)
+ (unless (c-forward-type) (throw 'break nil))
+
+ ;; Look for ": superclass-name" or "( category-name )".
+ (when (looking-at "[:\(]")
+ (setq start-char (char-after))
+ (forward-char)
+ (c-forward-syntactic-ws)
+ (unless (c-forward-type) (throw 'break nil))
+ (when (eq start-char ?\()
+ (unless (eq (char-after) ?\)) (throw 'break nil))
+ (forward-char)
+ (c-forward-syntactic-ws)))
+
+ ;; Look for a protocol reference list.
+ (when (if (eq (char-after) ?<)
+ (progn
+ (setq c-recognize-<>-arglists t)
+ (c-forward-<>-arglist t t))
+ t)
+ (c-put-char-property (1- (point)) 'c-type 'c-decl-end)
+ t))))
+
+(defun c-font-lock-objc-method ()
+ ;; Assuming the point is after the + or - that starts an Objective-C
+ ;; method declaration, fontify it. This must be done before normal
+ ;; casts, declarations and labels are fontified since they will get
+ ;; false matches in these things.
+
+ (c-fontify-types-and-refs
+ ((first t)
+ (c-promote-possible-types t))
+
+ (while (and
+ (progn
+ (c-forward-syntactic-ws)
+
+ ;; An optional method type.
+ (if (eq (char-after) ?\()
+ (progn
+ (forward-char)
+ (c-forward-syntactic-ws)
+ (c-forward-type)
+ (prog1 (c-go-up-list-forward)
+ (c-forward-syntactic-ws)))
+ t))
+
+ ;; The name. The first time it's the first part of
+ ;; the function name, the rest of the time it's an
+ ;; argument name.
+ (looking-at c-symbol-key)
+ (progn
+ (goto-char (match-end 0))
+ (c-put-font-lock-face (match-beginning 0)
+ (point)
+ (if first
+ 'font-lock-function-name-face
+ 'font-lock-variable-name-face))
+ (c-forward-syntactic-ws)
+
+ ;; Another optional part of the function name.
+ (when (looking-at c-symbol-key)
+ (goto-char (match-end 0))
+ (c-put-font-lock-face (match-beginning 0)
+ (point)
+ 'font-lock-function-name-face)
+ (c-forward-syntactic-ws))
+
+ ;; There's another argument if a colon follows.
+ (eq (char-after) ?:)))
+ (forward-char)
+ (setq first nil))))
+
+(defun c-font-lock-objc-methods (limit)
+ ;; Fontify method declarations in Objective-C. Nil is always
+ ;; returned.
+
+ (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))))
+
+ (c-find-decl-spots
+ limit
+ "[-+]"
+ nil
+ (lambda (match-pos inside-macro)
+ (forward-char)
+ (c-font-lock-objc-method))))
+ nil)
+
+(c-override-default-keywords 'objc-font-lock-keywords)
+
+(defconst objc-font-lock-keywords-1 (c-lang-const c-matchers-1 objc)
+ "Minimal font locking for Objective-C mode.
+Fontifies only compiler directives (in addition to the syntactic
+fontification of strings and comments).")
+
+(defconst objc-font-lock-keywords-2 (c-lang-const c-matchers-2 objc)
+ "Fast normal font locking for Objective-C mode.
+In addition to `objc-font-lock-keywords-1', this adds fontification of
+keywords, simple types, declarations that are easy to recognize, the
+user defined types on `objc-font-lock-extra-types', and the doc
+comment styles specified by `c-doc-comment-style'.")
+
+(defconst objc-font-lock-keywords-3 (c-lang-const c-matchers-3 objc)
+ "Accurate normal font locking for Objective-C mode.
+Like `objc-font-lock-keywords-2' but detects declarations in a more
+accurate way that works in most cases for arbitrary types without the
+need for `objc-font-lock-extra-types'.")
+
+(defvar objc-font-lock-keywords objc-font-lock-keywords-3
+ "Default expressions to highlight in Objective-C mode.")
+
+(defun objc-font-lock-keywords-2 ()
+ (c-compose-keywords-list objc-font-lock-keywords-2))
+(defun objc-font-lock-keywords-3 ()
+ (c-compose-keywords-list objc-font-lock-keywords-3))
+(defun objc-font-lock-keywords ()
+ (c-compose-keywords-list objc-font-lock-keywords))
+
+;; Kludge to override the default value that
+;; `objc-font-lock-extra-types' might have gotten from the font-lock
+;; package. The value replaced here isn't relevant now anyway since
+;; those types are builtin and therefore listed directly in
+;; `c-primitive-type-kwds'.
+(when (equal (sort (append objc-font-lock-extra-types nil) 'string-lessp)
+ '("BOOL" "Class" "IMP" "SEL"))
+ (setq objc-font-lock-extra-types
+ (cc-eval-when-compile (list (concat "[" c-upper "]\\sw*")))))
+
+
+;;; Java.
+
+(c-override-default-keywords 'java-font-lock-keywords)
+
+(defconst java-font-lock-keywords-1 (c-lang-const c-matchers-1 java)
+ "Minimal font locking for Java mode.
+Fontifies nothing except the syntactic fontification of strings and
+comments.")
+
+(defconst java-font-lock-keywords-2 (c-lang-const c-matchers-2 java)
+ "Fast normal font locking for Java mode.
+In addition to `java-font-lock-keywords-1', this adds fontification of
+keywords, simple types, declarations that are easy to recognize, the
+user defined types on `java-font-lock-extra-types', and the doc
+comment styles specified by `c-doc-comment-style'.")
+
+(defconst java-font-lock-keywords-3 (c-lang-const c-matchers-3 java)
+ "Accurate normal font locking for Java mode.
+Like `java-font-lock-keywords-2' but detects declarations in a more
+accurate way that works in most cases for arbitrary types without the
+need for `java-font-lock-extra-types'.")
+
+(defvar java-font-lock-keywords java-font-lock-keywords-3
+ "Default expressions to highlight in Java mode.")
+
+(defun java-font-lock-keywords-2 ()
+ (c-compose-keywords-list java-font-lock-keywords-2))
+(defun java-font-lock-keywords-3 ()
+ (c-compose-keywords-list java-font-lock-keywords-3))
+(defun java-font-lock-keywords ()
+ (c-compose-keywords-list java-font-lock-keywords))
+
+
+;;; CORBA IDL.
+
+(c-override-default-keywords 'idl-font-lock-keywords)
+
+(defconst idl-font-lock-keywords-1 (c-lang-const c-matchers-1 idl)
+ "Minimal font locking for CORBA IDL mode.
+Fontifies nothing except the syntactic fontification of strings and
+comments.")
+
+(defconst idl-font-lock-keywords-2 (c-lang-const c-matchers-2 idl)
+ "Fast normal font locking for CORBA IDL mode.
+In addition to `idl-font-lock-keywords-1', this adds fontification of
+keywords, simple types, declarations that are easy to recognize, the
+user defined types on `idl-font-lock-extra-types', and the doc comment
+styles specified by `c-doc-comment-style'.")
+
+(defconst idl-font-lock-keywords-3 (c-lang-const c-matchers-3 idl)
+ "Accurate normal font locking for CORBA IDL mode.
+Like `idl-font-lock-keywords-2' but detects declarations in a more
+accurate way that works in most cases for arbitrary types without the
+need for `idl-font-lock-extra-types'.")
+
+(defvar idl-font-lock-keywords idl-font-lock-keywords-3
+ "Default expressions to highlight in CORBA IDL mode.")
+
+(defun idl-font-lock-keywords-2 ()
+ (c-compose-keywords-list idl-font-lock-keywords-2))
+(defun idl-font-lock-keywords-3 ()
+ (c-compose-keywords-list idl-font-lock-keywords-3))
+(defun idl-font-lock-keywords ()
+ (c-compose-keywords-list idl-font-lock-keywords))
+
+
+;;; Pike.
+
+(c-override-default-keywords 'pike-font-lock-keywords)
+
+(defconst pike-font-lock-keywords-1 (c-lang-const c-matchers-1 pike)
+ "Minimal font locking for Pike mode.
+Fontifies only preprocessor directives (in addition to the syntactic
+fontification of strings and comments).")
+
+(defconst pike-font-lock-keywords-2 (c-lang-const c-matchers-2 pike)
+ "Fast normal font locking for Pike mode.
+In addition to `pike-font-lock-keywords-1', this adds fontification of
+keywords, simple types, declarations that are easy to recognize, the
+user defined types on `pike-font-lock-extra-types', and the doc
+comment styles specified by `c-doc-comment-style'.")
+
+(defconst pike-font-lock-keywords-3 (c-lang-const c-matchers-3 pike)
+ "Accurate normal font locking for Pike mode.
+Like `pike-font-lock-keywords-2' but detects declarations in a more
+accurate way that works in most cases for arbitrary types without the
+need for `pike-font-lock-extra-types'.")
+
+(defvar pike-font-lock-keywords pike-font-lock-keywords-3
+ "Default expressions to highlight in Pike mode.")
+
+(defun pike-font-lock-keywords-2 ()
+ (c-compose-keywords-list pike-font-lock-keywords-2))
+(defun pike-font-lock-keywords-3 ()
+ (c-compose-keywords-list pike-font-lock-keywords-3))
+(defun pike-font-lock-keywords ()
+ (c-compose-keywords-list pike-font-lock-keywords))
+
+
+;;; Doc comments.
+
+(defun c-font-lock-doc-comments (prefix limit keywords)
+ ;; Fontify the comments between the point and LIMIT whose start
+ ;; matches PREFIX with `c-doc-face-name'. Assumes comments have been
+ ;; fontified with `font-lock-comment-face' already. nil is always
+ ;; returned.
+ ;;
+ ;; After the fontification of a matching comment, fontification
+ ;; according to KEYWORDS is applied inside it. It's a list like
+ ;; `font-lock-keywords' except that anchored matches and eval
+ ;; clauses aren't supported and that some abbreviated forms can't be
+ ;; used. The buffer is narrowed to the comment while KEYWORDS is
+ ;; applied; leading comment starters are included but trailing
+ ;; comment enders for block comment are not.
+ ;;
+ ;; Note that faces added through KEYWORDS should never replace the
+ ;; existing `c-doc-face-name' face since the existence of that face
+ ;; is used as a flag in other code to skip comments.
+
+ (let (comment-beg region-beg)
+ (if (eq (get-text-property (point) 'face)
+ 'font-lock-comment-face)
+ ;; Handle the case when the fontified region starts inside a
+ ;; comment.
+ (let ((range (c-literal-limits)))
+ (setq region-beg (point))
+ (when range
+ (goto-char (car range)))
+ (when (looking-at prefix)
+ (setq comment-beg (point)))))
+
+ (while (or
+ comment-beg
+
+ ;; Search for the prefix until a match is found at the start
+ ;; of a comment.
+ (while (when (re-search-forward prefix limit t)
+ (setq comment-beg (match-beginning 0))
+ (or (not (c-got-face-at comment-beg
+ c-literal-faces))
+ (and (/= comment-beg (point-min))
+ (c-got-face-at (1- comment-beg)
+ c-literal-faces))))
+ (setq comment-beg nil))
+ (setq region-beg comment-beg))
+
+ (if (eq (elt (parse-partial-sexp comment-beg (+ comment-beg 2)) 7) t)
+ ;; Collect a sequence of doc style line comments.
+ (progn
+ (goto-char comment-beg)
+ (while (and (progn
+ (c-forward-single-comment)
+ (skip-syntax-forward " ")
+ (< (point) limit))
+ (looking-at prefix))))
+ (goto-char comment-beg)
+ (c-forward-single-comment))
+ (if (> (point) limit) (goto-char limit))
+ (setq comment-beg nil)
+
+ (let ((region-end (point))
+ (keylist keywords) keyword matcher highlights)
+ (c-put-font-lock-face region-beg region-end c-doc-face-name)
+ (save-restriction
+ ;; Narrow to the doc comment. Among other things, this
+ ;; helps by making "^" match at the start of the comment.
+ ;; Do not include a trailing block comment ender, though.
+ (and (> region-end (1+ region-beg))
+ (progn (goto-char region-end)
+ (backward-char 2)
+ (looking-at "\\*/"))
+ (setq region-end (point)))
+ (narrow-to-region region-beg region-end)
+
+ (while keylist
+ (setq keyword (car keylist)
+ keylist (cdr keylist)
+ matcher (car keyword))
+ (goto-char region-beg)
+ (while (if (stringp matcher)
+ (re-search-forward matcher region-end t)
+ (funcall matcher region-end))
+ (setq highlights (cdr keyword))
+ (if (consp (car highlights))
+ (while highlights
+ (font-lock-apply-highlight (car highlights))
+ (setq highlights (cdr highlights)))
+ (font-lock-apply-highlight highlights))))
+
+ (goto-char region-end)))))
+ nil)
+(put 'c-font-lock-doc-comments 'lisp-indent-function 2)
+
+(defun c-find-invalid-doc-markup (regexp limit)
+ ;; Used to fontify invalid markup in doc comments after the correct
+ ;; ones have been fontified: Find the first occurence of REGEXP
+ ;; between the point and LIMIT that only is fontified with
+ ;; `c-doc-face-name'. If a match is found then submatch 0 surrounds
+ ;; the first char and t is returned, otherwise nil is returned.
+ (let (start)
+ (while (if (re-search-forward regexp limit t)
+ (not (eq (get-text-property
+ (setq start (match-beginning 0)) 'face)
+ c-doc-face-name))
+ (setq start nil)))
+ (when start
+ (store-match-data (list (copy-marker start)
+ (copy-marker (1+ start))))
+ t)))
+
+(defun javadoc-font-lock-keywords ()
+ (list
+ (byte-compile
+ `(lambda (limit)
+ (c-font-lock-doc-comments "/\\*\\*" limit
+ '(("{@[a-z]+[^}\n\r]*}" ; "{@foo ...}" markup.
+ 0 ,c-doc-markup-face-name prepend nil)
+ ("^\\(/\\*\\)?[ \t*]*\\(@[a-z]+\\)" ; "@foo ..." markup.
+ 2 ,c-doc-markup-face-name prepend nil)
+ (,(concat "</?\\sw" ; HTML tags.
+ "\\("
+ (concat "\\sw\\|\\s \\|[=\n\r*.:]\\|"
+ "\"[^\"]*\"\\|'[^']*'")
+ "\\)*>")
+ 0 ,c-doc-markup-face-name prepend nil)
+ ("&\\(\\sw\\|[.:]\\)+;" ; HTML entities.
+ 0 ,c-doc-markup-face-name prepend nil)
+ ;; Fontify remaining markup characters as invalid. Note
+ ;; that the Javadoc spec is hazy about when "@" is allowed
+ ;; in non-markup use.
+ (,(lambda (limit)
+ (c-find-invalid-doc-markup "[<>&]\\|{@" limit))
+ 0 ,c-invalid-face-name prepend nil)
+ ))))))
+
+(defconst autodoc-decl-keywords
+ ;; Adorned regexp matching the keywords that introduce declarations
+ ;; in Pike Autodoc.
+ (cc-eval-when-compile
+ (c-make-keywords-re t '("@decl" "@elem" "@index" "@member") 'pike-mode)))
+
+(defconst autodoc-decl-type-keywords
+ ;; Adorned regexp matching the keywords that are followed by a type.
+ (cc-eval-when-compile
+ (c-make-keywords-re t '("@elem" "@member") 'pike-mode)))
+
+(defun autodoc-font-lock-line-markup (limit)
+ ;; Fontify all line oriented keywords between the point and LIMIT.
+ ;; Nil is always returned.
+
+ (let ((line-re (concat "^\\(\\(/\\*!\\|\\s *\\("
+ c-current-comment-prefix
+ "\\)\\)\\s *\\)@[A-Za-z_-]+\\(\\s \\|$\\)"))
+ (markup-faces (list c-doc-markup-face-name c-doc-face-name)))
+
+ (while (re-search-forward line-re limit t)
+ (goto-char (match-end 1))
+
+ (if (looking-at autodoc-decl-keywords)
+ (let* ((kwd-pos (point))
+ (start (match-end 1))
+ (pos start)
+ end)
+
+ (c-put-font-lock-face (point) pos markup-faces)
+
+ ;; Put a declaration end mark at the markup keyword and
+ ;; remove the faces from the rest of the line so that it
+ ;; gets refontified as a declaration later on by
+ ;; `c-font-lock-declarations'.
+ (c-put-char-property (1- pos) 'c-type 'c-decl-end)
+ (goto-char pos)
+ (while (progn
+ (end-of-line)
+ (setq end (point))
+ (and (eq (char-before) ?@)
+ (not (eobp))
+ (progn (forward-char)
+ (skip-chars-forward " \t")
+ (looking-at c-current-comment-prefix))))
+ (goto-char (match-end 0))
+ (c-remove-font-lock-face pos (1- end))
+ (c-put-font-lock-face (1- end) end markup-faces)
+ (setq pos (point)))
+
+ ;; Include the final newline in the removed area. This
+ ;; has no visual effect but it avoids some tricky special
+ ;; cases in the testsuite wrt the differences in string
+ ;; fontification in Emacs vs XEmacs.
+ (c-remove-font-lock-face pos (min (1+ (point)) (point-max)))
+
+ ;; Must handle string literals explicitly inside the declaration.
+ (goto-char start)
+ (while (re-search-forward
+ "\"\\([^\\\"]\\|\\\\.\\)*\"\\|'\\([^\\']\\|\\\\.\\)*'"
+ end 'move)
+ (c-put-font-lock-string-face (match-beginning 0)
+ (point)))
+
+ ;; Fontify types after keywords that always are followed
+ ;; by them.
+ (goto-char kwd-pos)
+ (when (looking-at autodoc-decl-type-keywords)
+ (c-fontify-types-and-refs ((c-promote-possible-types t))
+ (goto-char start)
+ (c-forward-syntactic-ws)
+ (c-forward-type))))
+
+ ;; Mark each whole line as markup, as long as the logical line
+ ;; continues.
+ (while (progn
+ (c-put-font-lock-face (point)
+ (progn (end-of-line) (point))
+ markup-faces)
+ (and (eq (char-before) ?@)
+ (not (eobp))
+ (progn (forward-char)
+ (skip-chars-forward " \t")
+ (looking-at c-current-comment-prefix))))
+ (goto-char (match-end 0))))))
+
+ nil)
+
+(defun autodoc-font-lock-keywords ()
+ ;; Note that we depend on that `c-current-comment-prefix' has got
+ ;; its proper value here.
+
+ ;; The `c-type' text property with `c-decl-end' is used to mark the
+ ;; end of the `autodoc-decl-keywords' occurrences to fontify the
+ ;; following declarations.
+ (setq c-type-decl-end-used t)
+
+ (list
+ (byte-compile
+ `(lambda (limit)
+ (c-font-lock-doc-comments "/[*/]!" limit
+ '(("@\\(\\w+{\\|\\[\\([^\]@\n\r]\\|@@\\)*\\]\\|[@}]\\|$\\)"
+ ;; In-text markup.
+ 0 ,c-doc-markup-face-name prepend nil)
+ (autodoc-font-lock-line-markup)
+ ;; Fontify remaining markup characters as invalid.
+ (,(lambda (limit)
+ (c-find-invalid-doc-markup "@" limit))
+ 0 ,c-invalid-face-name prepend nil)
+ ))))))
+
+
+;; AWK.
+
+;; Awk regexps written with help from Peter Galbraith
+;; Take GNU Emacs's 'words out of the following regexp-opts. They dont work
+;; in Xemacs 21.4.4. acm 2002/9/19.
+(eval-after-load "cc-awk" ; Evaluate while loading cc-fonts
+ `(defconst awk-font-lock-keywords ; Evaluate after loading cc-awk
+ ',(eval-when-compile ; Evaluate while compiling cc-fonts
+ (list
+ ;; Function names.
+ '("^[ \t]*\\(func\\(tion\\)?\\)\\>[ \t]*\\(\\sw+\\)?"
+ (1 font-lock-keyword-face) (3 font-lock-function-name-face nil t))
+ ;;
+ ;; Variable names.
+ (cons
+ (concat "\\<"
+ (c-regexp-opt
+ '("ARGC" "ARGIND" "ARGV" "BINMODE" "CONVFMT" "ENVIRON"
+ "ERRNO" "FIELDWIDTHS" "FILENAME" "FNR" "FS" "IGNORECASE"
+ "LINT" "NF" "NR" "OFMT" "OFS" "ORS" "PROCINFO" "RLENGTH"
+ "RS" "RSTART" "RT" "SUBSEP" "TEXTDOMAIN") t) "\\>")
+ 'font-lock-variable-name-face)
+
+ ;; Special file names. (acm, 2002/7/22)
+ ;; The following regexp was created by first evaluating this in GNU Emacs 21.1:
+ ;; (c-regexp-opt '("/dev/stdin" "/dev/stdout" "/dev/stderr" "/dev/fd/n" "/dev/pid"
+ ;; "/dev/ppid" "/dev/pgrpid" "/dev/user") 'words)
+ ;; , removing the "?:" from each "\\(?:" (for backward compatibility with older Emacsen)
+ ;; , replacing the "n" in "dev/fd/n" with "[0-9]+"
+ ;; , removing the unwanted \\< at the beginning, and finally filling out the
+ ;; regexp so that a " must come before, and either a " or heuristic stuff after.
+ ;; The surrounding quotes are fontified along with the filename, since, semantically,
+ ;; they are an indivisible unit.
+ '("\\(\"/dev/\\(fd/[0-9]+\\|p\\(\\(\\(gr\\)?p\\)?id\\)\\|\
+std\\(err\\|in\\|out\\)\\|user\\)\\)\\>\
+\\(\\(\"\\)\\|\\([^\"/\n\r][^\"\n\r]*\\)?$\\)"
+ (1 font-lock-variable-name-face t)
+ (8 font-lock-variable-name-face t t))
+ ;; Do the same (almost) with
+ ;; (c-regexp-opt '("/inet/tcp/lport/rhost/rport" "/inet/udp/lport/rhost/rport"
+ ;; "/inet/raw/lport/rhost/rport") 'words)
+ ;; This cannot be combined with the above pattern, because the match number
+ ;; for the (optional) closing \" would then exceed 9.
+ '("\\(\"/inet/\\(\\(raw\\|\\(tc\\|ud\\)p\\)/lport/rhost/rport\\)\\)\\>\
+\\(\\(\"\\)\\|\\([^\"/\n\r][^\"\n\r]*\\)?$\\)"
+ (1 font-lock-variable-name-face t)
+ (6 font-lock-variable-name-face t t))
+
+ ;; Keywords.
+ (concat "\\<"
+ (c-regexp-opt
+ '("BEGIN" "END" "break" "continue" "delete" "do" "else"
+ "exit" "for" "getline" "if" "in" "next" "nextfile"
+ "return" "while")
+ t) "\\>")
+
+ ;; Builtins.
+ `(eval . (list
+ ,(concat
+ "\\<"
+ (c-regexp-opt
+ '("adump" "and" "asort" "atan2" "bindtextdomain" "close"
+ "compl" "cos" "dcgettext" "exp" "extension" "fflush"
+ "gensub" "gsub" "index" "int" "length" "log" "lshift"
+ "match" "mktime" "or" "print" "printf" "rand" "rshift"
+ "sin" "split" "sprintf" "sqrt" "srand" "stopme"
+ "strftime" "strtonum" "sub" "substr" "system"
+ "systime" "tolower" "toupper" "xor") t)
+ "\\>")
+ 0 c-preprocessor-face-name))
+
+ ;; gawk debugging keywords. (acm, 2002/7/21)
+ ;; (Removed, 2003/6/6. These functions are now fontified as built-ins)
+;; (list (concat "\\<" (c-regexp-opt '("adump" "stopme") t) "\\>")
+;; 0 'font-lock-warning-face)
+
+ ;; User defined functions with an apparent spurious space before the
+ ;; opening parenthesis. acm, 2002/5/30.
+ `(,(concat "\\(\\w\\|_\\)" c-awk-escaped-nls* "[ \t]"
+ c-awk-escaped-nls*-with-space* "(")
+ (0 'font-lock-warning-face))
+
+ ;; Space after \ in what looks like an escaped newline. 2002/5/31
+ '("\\\\[ \t]+$" 0 font-lock-warning-face t)
+
+ ;; Unbalanced string (") or regexp (/) delimiters. 2002/02/16.
+ '("\\s|" 0 font-lock-warning-face t nil)
+ ;; gawk 3.1 localizable strings ( _"translate me!"). 2002/5/21
+ '("\\(_\\)\\s|" 1 font-lock-warning-face)
+ '("\\(_\\)\\s\"" 1 font-lock-string-face) ; FIXME! not for XEmacs. 2002/10/6
+ ))
+ "Default expressions to highlight in AWK mode."))
+
+
+(cc-provide 'cc-fonts)
+
+;;; cc-fonts.el ends here