From d9e94c22736810b8bd61964a322ecc9664e09e14 Mon Sep 17 00:00:00 2001 From: Martin Stjernholm Date: Thu, 3 Jul 2003 12:30:59 +0000 Subject: Updated CC Mode to version 5.30. --- lisp/progmodes/cc-fonts.el | 2879 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 2879 insertions(+) create mode 100644 lisp/progmodes/cc-fonts.el (limited to 'lisp/progmodes/cc-fonts.el') 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: bug-cc-mode@gnu.org +;; 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) + `(("\\" + (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 "") + 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 -- cgit v1.2.3