cc-fonts.el 98.6 KB
Newer Older
1 2
;;; cc-fonts.el --- font lock support for CC Mode

3
;; Copyright (C) 2002-2011 Free Software Foundation, Inc.
4 5 6 7 8

;; Authors:    2003- Alan Mackenzie
;;             2002- Martin Stjernholm
;; Maintainer: bug-cc-mode@gnu.org
;; Created:    07-Jan-2002
9 10
;; Keywords:   c languages
;; Package:    cc-mode
11 12 13

;; This file is part of GNU Emacs.

14
;; GNU Emacs is free software: you can redistribute it and/or modify
15
;; it under the terms of the GNU General Public License as published by
16 17
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
18 19 20 21 22 23 24

;; 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
25
;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
26 27 28 29 30

;;; Commentary:

;; Some comments on the use of faces:
;;
31 32
;; o  `c-label-face-name' is either `font-lock-constant-face' (in
;;    Emacs), or `font-lock-reference-face'.
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
;;
;; 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).
;;
;; 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-method)
(cc-bytecomp-defun c-font-lock-invalid-string)


;; 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)
113 114
	 ;; In Emacs font-lock-builtin-face has traditionally been
	 ;; used for preprocessor directives.
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
	 '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))
139
      ;; This doesn't exist in some earlier versions of XEmacs 21.
140 141 142 143
      'font-lock-constant-face
    c-label-face-name))

(defconst c-reference-face-name
144 145 146 147 148 149 150 151
  (with-no-warnings
   (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, 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)))
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172

;; 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))

173 174 175 176
(defconst c-negation-char-face-name
  (if (c-face-name-p 'font-lock-negation-char-face)
      ;; Emacs 22 has a special face for negation chars.
      'font-lock-negation-char-face))
177 178 179 180 181 182 183 184 185

(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
  (copy-face oldface newface)
  (cond ((fboundp 'face-inverse-video-p)
186 187 188 189
	 ;; Emacs.  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.
190 191 192 193 194
	 (unless (face-inverse-video-p oldface)
	   (invert-face newface)))
	((fboundp 'face-property-instance)
	 ;; XEmacs.  Same pitfall here.
	 (unless (face-property-instance oldface 'reverse)
195
	   (invert-face newface)))))
196

197 198 199 200
(defvar c-annotation-face (make-face 'c-annotation-face)
  "Face used to highlight annotations in java-mode and other modes that may wish to use it.")
(set-face-foreground 'c-annotation-face "blue")

201
(eval-and-compile
202 203 204 205 206 207 208 209 210 211
  ;; We need the following definitions during compilation since they're
  ;; used when the `c-lang-defconst' initializers are evaluated.  Define
  ;; them at runtime too for the sake of derived modes.

  ;; This indicates the "font locking context", and is set just before
  ;; fontification is done.  If non-nil, it says, e.g., point starts
  ;; from within a #if preprocessor construct.
  (defvar c-font-lock-context nil)
  (make-variable-buffer-local 'c-font-lock-context)
  
212 213 214 215 216 217
  (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.
218 219
    ;;
    ;; This function does a hidden buffer change.
220 221 222 223 224 225 226 227
    (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'.
228 229
    ;;
    ;; This function does a hidden buffer change.
230 231 232 233 234 235 236 237
    (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.
238 239
    ;;
    ;; This function does a hidden buffer change.
240 241 242 243 244 245 246 247
    (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.
248 249
    ;;
    ;; This function does hidden buffer changes.
250 251 252 253 254 255 256 257 258 259 260 261
    `(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)

  (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.
262 263
    ;;
    ;; This function might do hidden buffer changes.
264 265 266 267 268 269 270 271
    (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))

272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291
  (defun c-make-syntactic-matcher (regexp)
    ;; Returns a byte compiled function suitable for use in place of a
    ;; regexp string in a `font-lock-keywords' matcher, except that
    ;; only matches outside comments and string literals count.
    ;;
    ;; 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.)
    (byte-compile
     `(lambda (limit)
	(let (res)
	  (while (and (setq res (re-search-forward ,regexp limit t))
		      (progn
			(goto-char (match-beginning 0))
			(or (c-skip-comments-and-strings limit)
			    (progn
			      (goto-char (match-end 0))
			      nil)))))
	  res))))

292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330
  (defun c-make-font-lock-search-form (regexp highlights)
    ;; Return a lisp form which will fontify every occurence of REGEXP
    ;; (a regular expression, NOT a function) between POINT and `limit'
    ;; with HIGHLIGHTS, a list of highlighters as specified on page
    ;; "Search-based Fontification" in the elisp manual.
    `(while (re-search-forward ,regexp limit t)
       (unless (progn
		 (goto-char (match-beginning 0))
		 (c-skip-comments-and-strings limit))
	 (goto-char (match-end 0))
	 ,@(mapcar
	    (lambda (highlight)
	      (if (integerp (car highlight))
		  ;; e.g. highlight is (1 font-lock-type-face t)
		  (progn
		    (unless (eq (nth 2 highlight) t)
		      (error
		       "The override flag must currently be t in %s"
		       highlight))
		    (when (nth 3 highlight)
		      (error
		       "The laxmatch flag may currently not be set in %s"
		       highlight))
		    `(save-match-data
		       (c-put-font-lock-face
			(match-beginning ,(car highlight))
			(match-end ,(car highlight))
			,(elt highlight 1))))
		;; highlight is an "ANCHORED HIGHLIGHER" of the form
		;; (ANCHORED-MATCHER PRE-FORM POST-FORM SUBEXP-HIGHLIGHTERS...)
		(when (nth 3 highlight)
		  (error "Match highlights currently not supported in %s"
			 highlight))
		`(progn
		   ,(nth 1 highlight)
		   (save-match-data ,(car highlight))
		   ,(nth 2 highlight))))
	    highlights))))

331 332 333 334 335 336
  (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
337
    ;; arbitrarily limit anchored matchers to the same line, and also
338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353
    ;; 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
354 355
    ;; generated functions will.  (They are however used in places
    ;; covered by the font-lock context.)
356 357

    ;; Note: Replace `byte-compile' with `eval' to debug the generated
358
    ;; lambda more easily.
359 360
    (byte-compile
     `(lambda (limit)
361
	(let ( ;; The font-lock package in Emacs is known to clobber
362 363 364 365
	      ;; `parse-sexp-lookup-properties' (when it exists).
	      (parse-sexp-lookup-properties
	       (cc-eval-when-compile
		 (boundp 'parse-sexp-lookup-properties))))
366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398

	  ;; (while (re-search-forward ,regexp limit t)
	  ;;   (unless (progn
	  ;; 	      (goto-char (match-beginning 0))
	  ;; 	      (c-skip-comments-and-strings limit))
	  ;;     (goto-char (match-end 0))
	  ;;     ,@(mapcar
	  ;; 	 (lambda (highlight)
	  ;; 	   (if (integerp (car highlight))
	  ;; 	       (progn
	  ;; 		 (unless (eq (nth 2 highlight) t)
	  ;; 		   (error
	  ;; 		    "The override flag must currently be t in %s"
	  ;; 		    highlight))
	  ;; 		 (when (nth 3 highlight)
	  ;; 		   (error
	  ;; 		    "The laxmatch flag may currently not be set in %s"
	  ;; 		    highlight))
	  ;; 		 `(save-match-data
	  ;; 		    (c-put-font-lock-face
	  ;; 		     (match-beginning ,(car highlight))
	  ;; 		     (match-end ,(car highlight))
	  ;; 		     ,(elt highlight 1))))
	  ;; 	     (when (nth 3 highlight)
	  ;; 	       (error "Match highlights currently not supported in %s"
	  ;; 		      highlight))
	  ;; 	     `(progn
	  ;; 		,(nth 1 highlight)
	  ;; 		(save-match-data ,(car highlight))
	  ;; 		,(nth 2 highlight))))
	  ;; 	 highlights)))
	  ,(c-make-font-lock-search-form regexp highlights))

399 400
	nil)))

401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453
  (defun c-make-font-lock-BO-decl-search-function (regexp &rest highlights)
    ;; This function makes a byte compiled function that first moves back
    ;; to the beginning of the current declaration (if any), then searches
    ;; forward for matcher elements (as in `font-lock-keywords') and
    ;; fontifies them.
    ;;
    ;; The motivation for moving back to the declaration start is to
    ;; establish a context for the current text when, e.g., a character
    ;; is typed on a C++ inheritance continuation line, or a jit-lock
    ;; chunk starts there.
    ;; 
    ;; The new function works much like a matcher element in
    ;; `font-lock-keywords'.  It cuts out a little bit of the overhead
    ;; compared to a real matcher.  The main reason is however to pass the
    ;; real search limit to the anchored matcher(s), since most (if not
    ;; all) font-lock implementations arbitrarily limit anchored matchers
    ;; to the same line, and also to insulate against various other
    ;; irritating differences between the different (X)Emacs font-lock
    ;; packages.
    ;;
    ;; REGEXP is the matcher, which must be a regexp.  Only matches
    ;; where the beginning is outside any comment or string literal are
    ;; significant.
    ;;
    ;; HIGHLIGHTS is a list of highlight specs, just like in
    ;; `font-lock-keywords', with these limitations: The face is always
    ;; overridden (no big disadvantage, since hits in comments etc are
    ;; filtered anyway), there is no "laxmatch", and an anchored matcher
    ;; is always a form which must do all the fontification directly.
    ;; `limit' is a variable bound to the real limit in the context of
    ;; the anchored matcher forms.
    ;;
    ;; This function does not do any hidden buffer changes, but the
    ;; generated functions will.  (They are however used in places
    ;; covered by the font-lock context.)

    ;; Note: Replace `byte-compile' with `eval' to debug the generated
    ;; lambda more easily.
    (byte-compile
     `(lambda (limit)
	(let ( ;; The font-lock package in Emacs is known to clobber
	      ;; `parse-sexp-lookup-properties' (when it exists).
	      (parse-sexp-lookup-properties
	       (cc-eval-when-compile
		 (boundp 'parse-sexp-lookup-properties))))
	  (goto-char
	   (let ((here (point)))
	     (if (eq (car (c-beginning-of-decl-1)) 'same)
		 (point)
	       here)))
	  ,(c-make-font-lock-search-form regexp highlights))
	nil)))

454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508
  (defun c-make-font-lock-context-search-function (normal &rest state-stanzas)
    ;; This function makes a byte compiled function that works much like
    ;; a matcher element in `font-lock-keywords', with the following
    ;; enhancement: the generated function will test for particular "font
    ;; lock contexts" at the start of the region, i.e. is this point in
    ;; the middle of some particular construct?  if so the generated
    ;; function will first fontify the tail of the construct, before
    ;; going into the main loop and fontify full constructs up to limit.
    ;;
    ;; The generated function takes one parameter called `limit', and
    ;; will fontify the region between POINT and LIMIT.
    ;;
    ;; NORMAL is a list of the form (REGEXP HIGHLIGHTS .....), and is
    ;; used to fontify the "regular" bit of the region.
    ;; STATE-STANZAS is list of elements of the form (STATE LIM REGEXP
    ;; HIGHLIGHTS), each element coding one possible font lock context.

    ;; o - REGEXP is a font-lock regular expression (NOT a function),
    ;; o - HIGHLIGHTS is a list of zero or more highlighters as defined
    ;;   on page "Search-based Fontification" in the elisp manual.  As
    ;;   yet (2009-06), they must have OVERRIDE set, and may not have
    ;;   LAXMATCH set.
    ;;
    ;; o - STATE is the "font lock context" (e.g. in-cpp-expr) and is
    ;;   not quoted.
    ;; o - LIM is a lisp form whose evaluation will yield the limit
    ;;   position in the buffer for fontification by this stanza.
    ;;
    ;; This function does not do any hidden buffer changes, but the
    ;; generated functions will.  (They are however used in places
    ;; covered by the font-lock context.)
    ;; 
    ;; Note: Replace `byte-compile' with `eval' to debug the generated
    ;; lambda more easily.
    (byte-compile
     `(lambda (limit)
	(let ( ;; The font-lock package in Emacs is known to clobber
	      ;; `parse-sexp-lookup-properties' (when it exists).
	      (parse-sexp-lookup-properties
	       (cc-eval-when-compile
		 (boundp 'parse-sexp-lookup-properties))))
	  ,@(mapcar
	     (lambda (stanza)
	       (let ((state (car stanza))
		     (lim (nth 1 stanza))
		     (regexp (nth 2 stanza))
		     (highlights (cdr (cddr stanza))))
		 `(if (eq c-font-lock-context ',state)
		      (let ((limit ,lim))
			,(c-make-font-lock-search-form
			  regexp highlights)))))
	     state-stanzas)
	  ,(c-make-font-lock-search-form (car normal) (cdr normal))
	  nil))))

509 510 511 512 513 514 515 516 517
;  (eval-after-load "edebug" ; 2006-07-09: def-edebug-spec is now in subr.el.
;    '(progn
  (def-edebug-spec c-fontify-types-and-refs let*)
  (def-edebug-spec c-make-syntactic-matcher t)
  ;; If there are literal quoted or backquoted highlight specs in
  ;; the call to `c-make-font-lock-search-function' then let's
  ;; instrument the forms in them.
  (def-edebug-spec c-make-font-lock-search-function
    (form &rest &or ("quote" (&rest form)) ("`" (&rest form)) form)));))
518 519

(defun c-fontify-recorded-types-and-refs ()
520
  ;; Convert the ranges recorded on `c-record-type-identifiers' and
521
  ;; `c-record-ref-identifiers' to fontification.
522 523
  ;;
  ;; This function does hidden buffer changes.
524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547
  (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]\\)")
548 549 550 551
		 (ncle-depth (regexp-opt-depth noncontinued-line-end))
		 (sws-depth (c-lang-const c-syntactic-ws-depth))
		 (nsws-depth (c-lang-const c-nonempty-syntactic-ws-depth)))

552 553
	    `(;; The stuff after #error and #warning is a message, so
	      ;; fontify it as a string.
554
	      ,@(when (c-lang-const c-cpp-message-directives)
555
		  (let* ((re (c-make-keywords-re 'appendable ; nil
556 557 558 559 560 561
			       (c-lang-const c-cpp-message-directives)))
			 (re-depth (regexp-opt-depth re)))
		    `((,(concat noncontinued-line-end
				(c-lang-const c-opt-cpp-prefix)
				re
				"\\s +\\(.*\\)$")
562
		       ,(+ ncle-depth re-depth 1) font-lock-string-face t))))
563 564

	      ;; Fontify filenames in #include <...> as strings.
565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588
	      ,@(when (c-lang-const c-cpp-include-directives)
		  (let* ((re (c-make-keywords-re nil
			       (c-lang-const c-cpp-include-directives)))
			 (re-depth (regexp-opt-depth re)))
		    `((,(concat noncontinued-line-end
				(c-lang-const c-opt-cpp-prefix)
				re
				(c-lang-const c-syntactic-ws)
				"\\(<[^>\n\r]*>?\\)")
		       (,(+ ncle-depth re-depth sws-depth 1)
			font-lock-string-face)

		       ;; Use an anchored matcher to put paren syntax
		       ;; on the brackets.
		       (,(byte-compile
			  `(lambda (limit)
			     (let ((beg (match-beginning
					 ,(+ ncle-depth re-depth sws-depth 1)))
				   (end (1- (match-end ,(+ ncle-depth re-depth
							   sws-depth 1)))))
			       (if (eq (char-after end) ?>)
				   (progn
				     (c-mark-<-as-paren beg)
				     (c-mark->-as-paren end))
589 590
				 ;; (c-clear-char-property beg 'syntax-table)
				 (c-clear-char-property beg 'category)))
591
			     nil)))))))
592 593

	      ;; #define.
594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643
	      ,@(when (c-lang-const c-opt-cpp-macro-define)
		  `((,(c-make-font-lock-search-function
		       (concat
			noncontinued-line-end
			(c-lang-const c-opt-cpp-prefix)
			(c-lang-const c-opt-cpp-macro-define)
			(c-lang-const c-nonempty-syntactic-ws)
			"\\(" (c-lang-const ; 1 + ncle + nsws
			       c-symbol-key) "\\)"
			(concat "\\("	; 2 + ncle + nsws + c-sym-key
				;; Macro with arguments - a "function".
				"\\(\(\\)" ; 3 + ncle + nsws + c-sym-key
				"\\|"
				;; Macro without arguments - a "variable".
				"\\([^\(]\\|$\\)"
				"\\)"))
		       `((if (match-beginning
			      ,(+ 3 ncle-depth nsws-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 nsws-depth))
				(match-end ,(+ 1 ncle-depth nsws-depth))
				'font-lock-function-name-face)
			       (goto-char
				(match-end
				 ,(+ 3 ncle-depth nsws-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 nsws-depth))
			    (match-end ,(+ 1 ncle-depth nsws-depth))
			    'font-lock-variable-name-face)))))))
644 645 646

	      ;; Fontify cpp function names in preprocessor
	      ;; expressions in #if and #elif.
647 648 649 650 651 652
	      ,@(when (and (c-lang-const c-cpp-expr-directives)
			   (c-lang-const c-cpp-expr-functions))
		  (let ((ced-re (c-make-keywords-re t
				  (c-lang-const c-cpp-expr-directives)))
			(cef-re (c-make-keywords-re t
				  (c-lang-const c-cpp-expr-functions))))
653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670

		    `((,(c-make-font-lock-context-search-function
			 `(,(concat noncontinued-line-end
				    (c-lang-const c-opt-cpp-prefix)
				    ced-re ; 1 + ncle-depth
				    ;; Match the whole logical line to look
				    ;; for the functions in.
				    "\\(\\\\\\(.\\|[\n\r]\\)\\|[^\n\r]\\)*")
			   ((let ((limit (match-end 0)))
			      (while (re-search-forward ,cef-re limit 'move)
				(c-put-font-lock-face (match-beginning 1)
						      (match-end 1)
						      c-preprocessor-face-name)))
			    (goto-char (match-end ,(1+ ncle-depth)))))
			 `(in-cpp-expr
			   (save-excursion (c-end-of-macro) (point))
			   ,cef-re
			   (1 c-preprocessor-face-name t)))))))
671 672 673 674 675 676 677 678 679

	      ;; 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)))
680

681 682 683 684 685 686 687
	      (eval . (list ,(c-make-syntactic-matcher
			      (concat noncontinued-line-end
				      (c-lang-const c-opt-cpp-prefix)
				      "if\\(n\\)def\\>"))
			    ,(+ ncle-depth 1)
			    c-negation-char-face-name
			    'append))
688 689 690
	      )))

      ,@(when (c-major-mode-is 'pike-mode)
691
	  ;; Recognize hashbangs in Pike.
692 693 694
	  `((eval . (list "\\`#![^\n\r]*"
			  0 c-preprocessor-face-name))))

695
      ;; Make hard spaces visible through an inverted `font-lock-warning-face'.
696 697 698
      (eval . (list
	       "\240"
	       0 (progn
699 700 701 702
		   (unless (c-face-name-p 'c-nonbreakable-space-face)
		     (c-make-inverse-face 'font-lock-warning-face
					  'c-nonbreakable-space-face))
		   ''c-nonbreakable-space-face)))
703 704 705 706
      ))

(defun c-font-lock-invalid-string ()
  ;; Assuming the point is after the opening character of a string,
707
  ;; fontify that char with `font-lock-warning-face' if the string
708
  ;; decidedly isn't terminated properly.
709 710
  ;;
  ;; This function does hidden buffer changes.
711 712
  (let ((start (1- (point))))
    (save-excursion
713 714 715 716 717 718 719 720 721
      (and (eq (elt (parse-partial-sexp start (c-point 'eol)) 8) start)
	   (if (integerp c-multiline-string-start-char)
	       ;; There's no multiline string start char before the
	       ;; string, so newlines aren't allowed.
	       (not (eq (char-before start) c-multiline-string-start-char))
	     ;; Multiline strings are allowed anywhere if
	     ;; c-multiline-string-start-char is t.
	     (not c-multiline-string-start-char))
	   (if c-string-escaped-newlines
722 723
	       ;; There's no \ before the newline.
	       (not (eq (char-before (point)) ?\\))
724
	     ;; Escaped newlines aren't supported.
725
	     t)
726
	   (c-put-font-lock-face start (1+ start) 'font-lock-warning-face)))))
727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753

(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.
754
		`((eval . (list ,(concat "\\(\\=.?\\|[^>]\\|[^-]>\\)"
755
					 "\\<\\(" re "\\)\\>")
756
				2 c-constant-face-name)))
757 758 759 760 761 762
	      `((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.
763
	   `(,(concat "\\(\\=.?\\|[^>]\\|[^-]>\\)"
764
		      "\\<" (c-lang-const c-regular-keywords-regexp))
765
	     2 font-lock-keyword-face)
766 767 768 769 770 771
	 `(,(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)
Martin Stjernholm's avatar
Martin Stjernholm committed
772 773 774 775 776 777 778 779 780 781 782 783
	  (if (c-major-mode-is 'java-mode)
	      ;; Java needs special treatment since "." is used both to
	      ;; qualify names and in normal indexing.  Here we look for
	      ;; capital characters at the beginning of an identifier to
	      ;; recognize the class.  "*" is also recognized to cover
	      ;; wildcard import declarations.  All preceding dot separated
	      ;; identifiers are taken as package names and therefore
	      ;; fontified as references.
	      `(,(c-make-font-lock-search-function
		  ;; Search for class identifiers preceded by ".".  The
		  ;; anchored matcher takes it from there.
		  (concat (c-lang-const c-opt-identifier-concat-key)
784
			  (c-lang-const c-simple-ws) "*"
Martin Stjernholm's avatar
Martin Stjernholm committed
785
			  (concat "\\("
786 787
				  "[" c-upper "]"
				  "[" (c-lang-const c-symbol-chars) "]*"
Martin Stjernholm's avatar
Martin Stjernholm committed
788 789 790 791 792 793 794 795 796 797 798 799 800
				  "\\|"
				  "\\*"
				  "\\)"))
		  `((let (id-end)
		      (goto-char (1+ (match-beginning 0)))
		      (while (and (eq (char-before) ?.)
				  (progn
				    (backward-char)
				    (c-backward-syntactic-ws)
				    (setq id-end (point))
				    (< (skip-chars-backward
					,(c-lang-const c-symbol-chars)) 0))
				  (not (get-text-property (point) 'face)))
801 802
			(c-put-font-lock-face (point) id-end
					      c-reference-face-name)
Martin Stjernholm's avatar
Martin Stjernholm committed
803 804 805 806 807
			(c-backward-syntactic-ws)))
		    nil
		    (goto-char (match-end 0)))))

	    `((,(byte-compile
808 809 810 811 812 813
		 ;; 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 since it restarts the
		 ;; search from the end of the first highlighted
		 ;; submatch (something that causes problems in other
		 ;; places).
Martin Stjernholm's avatar
Martin Stjernholm committed
814 815 816 817
		 `(lambda (limit)
		    (while (re-search-forward
			    ,(concat "\\(\\<" ; 1
				     "\\(" (c-lang-const c-symbol-key) "\\)" ; 2
818
				     (c-lang-const c-simple-ws) "*"
Martin Stjernholm's avatar
Martin Stjernholm committed
819
				     (c-lang-const c-opt-identifier-concat-key)
820
				     (c-lang-const c-simple-ws) "*"
Martin Stjernholm's avatar
Martin Stjernholm committed
821 822 823 824 825 826 827 828 829 830 831 832 833
				     "\\)"
				     "\\("
				     (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))))))))))
834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850

      ;; 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.
851 852 853
	    ,(c-make-font-lock-search-function
	      (concat "\\<"
		      (regexp-opt
854 855 856
		       '("@interface" "@implementation" "@protocol")
		       t)
		      "\\>")
857 858 859 860 861 862 863 864 865 866 867
	      '((c-fontify-types-and-refs
		    (;; 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-objc-directive)
		  nil)
		(goto-char (match-beginning 0))))))

      (eval . (list "\\(!\\)[^=]" 1 c-negation-char-face-name))
868 869 870
      ))

(defun c-font-lock-complex-decl-prepare (limit)
871 872 873 874 875 876
  ;; This function will be called from font-lock for a region bounded by POINT
  ;; and LIMIT, as though it were to identify a keyword for
  ;; font-lock-keyword-face.  It always returns NIL to inhibit this and
  ;; prevent a repeat invocation.  See elisp/lispref page "Search-based
  ;; Fontification".
  ;;
877
  ;; Called before any of the matchers in `c-complex-decl-matchers'.
878 879
  ;;
  ;; This function does hidden buffer changes.
880 881 882 883 884

  ;;(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
885
  ;; variables that have gotten recognized as types in malformed code.
886 887 888
  (when (bobp)
    (c-clear-found-types))

889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904
  ;; Clear the c-type char properties which mark the region, to recalculate
  ;; them properly.  The most interesting properties are those put on the
  ;; closest token before the region.
  (save-excursion
    (let ((pos (point)))
      (c-backward-syntactic-ws)
      (c-clear-char-properties
       (if (and (not (bobp))
		(memq (c-get-char-property (1- (point)) 'c-type)
		      '(c-decl-arg-start
			c-decl-end
			c-decl-id-start
			c-decl-type-start)))
	   (1- (point))
	 pos)
       limit 'c-type)))
905 906 907 908 909 910 911 912

  ;; 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.
913 914
  ;; The declared identifiers are font-locked correctly as types, if
  ;; that is what they are.
915 916 917 918 919 920 921 922
  (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))))

923 924 925 926 927 928
  (setq c-font-lock-context ;; (c-guess-font-lock-context)
	(save-excursion
	  (if (and c-cpp-expr-intro-re
		   (c-beginning-of-macro)
		   (looking-at c-cpp-expr-intro-re))
	      'in-cpp-expr)))
929 930 931
  nil)

(defun c-font-lock-<>-arglists (limit)
932 933 934 935 936 937
  ;; This function will be called from font-lock for a region bounded by POINT
  ;; and LIMIT, as though it were to identify a keyword for
  ;; font-lock-keyword-face.  It always returns NIL to inhibit this and
  ;; prevent a repeat invocation.  See elisp/lispref page "Search-based
  ;; Fontification".
  ;;
938
  ;; Fontify types and references in names containing angle bracket
939
  ;; arglists from the point to LIMIT.  Note that
940
  ;; `c-font-lock-declarations' already has handled many of them.
941 942
  ;;
  ;; This function might do hidden buffer changes.
943 944 945 946 947 948

  (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)))
949 950 951
	(c-parse-and-markup-<>-arglists t)
	c-restricted-<>-arglists
	id-start id-end id-face pos kwd-sym)
952 953 954 955 956 957 958 959 960 961

    (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)
962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989
	(setq kwd-sym nil
	      c-restricted-<>-arglists nil
	      id-face (get-text-property id-start 'face))

	(if (cond
	     ((eq id-face 'font-lock-type-face)
	      ;; The identifier got the type face so it has already been
	      ;; handled in `c-font-lock-declarations'.
	      nil)

	     ((eq id-face 'font-lock-keyword-face)
	      (when (looking-at c-opt-<>-sexp-key)
		;; There's a special keyword before the "<" that tells
		;; that it's an angle bracket arglist.
		(setq kwd-sym (c-keyword-sym (match-string 1)))))

	     (t
	      ;; There's a normal identifier before the "<".  If we're not in
	      ;; a declaration context then we set `c-restricted-<>-arglists'
	      ;; to avoid recognizing templates in function calls like "foo (a
	      ;; < b, c > d)".
	      (c-backward-syntactic-ws)
	      (when (and (memq (char-before) '(?\( ?,))
			 (not (eq (get-text-property (1- (point)) 'c-type)
				  'c-decl-arg-start)))
		(setq c-restricted-<>-arglists t))
	      t))

990 991 992 993 994 995
	    (progn
	      (goto-char (1- pos))
	      ;; Check for comment/string both at the identifier and
	      ;; at the "<".
	      (unless (c-skip-comments-and-strings limit)

996 997 998 999 1000 1001 1002 1003 1004
		(c-fontify-types-and-refs ()
		  (when (c-forward-<>-arglist (c-keyword-member
					       kwd-sym 'c-<>-type-kwds))
		    (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)
1005
			(c-put-font-lock-face id-start id-end
1006
					      'font-lock-type-face)))))
1007 1008 1009 1010 1011 1012

		(goto-char pos)))
	  (goto-char pos)))))
  nil)

(defun c-font-lock-declarators (limit list types)
1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025
  ;; Assuming the point is at the start of a declarator in a declaration,
  ;; fontify the identifier it declares.  (If TYPES is set, it does this via
  ;; the macro `c-fontify-types-and-refs'.)
  ;;
  ;; If LIST is non-nil, also fontify the ids in any following declarators in
  ;; a comma separated list (e.g.  "foo" and "*bar" in "int foo = 17, *bar;");
  ;; additionally, mark the commas with c-type property 'c-decl-id-start or
  ;; 'c-decl-type-start (according to TYPES).  Stop at LIMIT.
  ;;
  ;; If TYPES is non-nil, fontify all identifiers as types.
  ;;
  ;; Nil is always returned.  The function leaves point at the delimiter after
  ;; the last declarator it processes.
1026 1027
  ;;
  ;; This function might do hidden buffer changes.
1028 1029 1030 1031 1032 1033 1034 1035 1036

  ;;(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)))

1037 1038 1039 1040 1041 1042 1043 1044 1045
    ;; The following `while' fontifies a single declarator id each time round.
    ;; It loops only when LIST is non-nil.
    (while
	;; Inside the following "condition form", we move forward over the
	;; declarator's identifier up as far as any opening bracket (for array
	;; size) or paren (for parameters of function-type) or brace (for
	;; array/struct initialisation) or "=" or terminating delimiter
	;; (e.g. "," or ";" or "}").
	(and
1046 1047 1048
	    pos
	    (< (point) limit)

1049 1050 1051
	    ;; The following form moves forward over the declarator's
	    ;; identifier (and what precedes it), returning t.  If there
	    ;; wasn't one, it returns nil, terminating the `while'.
1052 1053
	    (let (got-identifier)
	      (setq paren-depth 0)
1054 1055 1056 1057
	      ;; Skip over type decl prefix operators, one for each iteration
	      ;; of the while.  These are, e.g. "*" in "int *foo" or "(" and
	      ;; "*" in "int (*foo) (void)" (Note similar code in
	      ;; `c-forward-decl-or-cast-1'.)
1058 1059
	      (while (and (looking-at c-type-decl-prefix-key)
			  (if (and (c-major-mode-is 'c++-mode)
1060 1061
				   (match-beginning 3))
			      ;; If the third submatch matches in C++ then
1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083
			      ;; 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))

1084
	      ;; If we haven't passed the identifier already, do it now.
1085 1086 1087 1088 1089 1090 1091
	      (unless got-identifier
		(setq id-start (point))
		(c-forward-name))
	      (setq id-end (point))

	      (/= id-end pos))

1092 1093
	    ;; Skip out of the parens surrounding the identifier.  If closing
	    ;; parens are missing, this form returns nil.
1094 1095 1096 1097 1098
	    (or (= paren-depth 0)
		(c-safe (goto-char (scan-lists (point) 1 paren-depth))))

	    (<= (point) limit)

1099
	    ;; Skip over any trailing bit, such as "__attribute__".
1100 1101 1102 1103 1104
	    (progn
	      (when (looking-at c-decl-hangon-key)
		(c-forward-keyword-clause 1))
	      (<= (point) limit))

1105
	    ;; Search syntactically to the end of the declarator (";",
Martin Stjernholm's avatar
Martin Stjernholm committed
1106 1107 1108 1109
	    ;; ",", a closen paren, eob etc) or to the beginning of an
	    ;; initializer or function prototype ("=" or "\\s\(").
	    ;; Note that the open paren will match array specs in
	    ;; square brackets, and we treat them as initializers too.
1110
	    (c-syntactic-re-search-forward
Martin Stjernholm's avatar
Martin Stjernholm committed
1111
	     "[;,]\\|\\s)\\|\\'\\|\\(=\\|\\s(\\)" limit t t))
1112 1113

      (setq next-pos (match-beginning 0)
1114 1115 1116 1117 1118
	    id-face (if (and (eq (char-after next-pos) ?\()
			     (let (c-last-identifier-range)
			       (save-excursion
				 (goto-char next-pos)
				 (c-at-toplevel-p))))
1119 1120
			'font-lock-function-name-face
		      'font-lock-variable-name-face)
Martin Stjernholm's avatar
Martin Stjernholm committed
1121 1122
	    got-init (and (match-beginning 1)
			  (char-after (match-beginning 1))))
1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139

      (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)
1140
      (setq pos nil)	      ; So as to terminate the enclosing `while' form.
1141 1142 1143 1144 1145 1146 1147
      (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.
1148
	       (if (c-safe (c-forward-sexp 1) t) ; over the parameter list.
1149
		   (c-forward-syntactic-ws limit)
1150
		 (goto-char limit)))	; unbalanced parens
1151

1152
	      (got-init	; "=" sign OR opening "(", "[", or "{"
Martin Stjernholm's avatar
Martin Stjernholm committed
1153 1154 1155 1156 1157
	       ;; Skip an initializer expression.  If we're at a '='
	       ;; then accept a brace list directly after it to cope
	       ;; with array initializers.  Otherwise stop at braces
	       ;; to avoid going past full function and class blocks.
	       (and (if (and (eq got-init ?=)
1158
			     (= (c-forward-token-2 1 nil limit) 0)
Martin Stjernholm's avatar
Martin Stjernholm committed
1159
			     (looking-at "{"))
1160
			(c-safe (c-forward-sexp) t) ; over { .... }
Martin Stjernholm's avatar
Martin Stjernholm committed
1161
		      t)
1162 1163 1164
		    ;; FIXME: Should look for c-decl-end markers here;
		    ;; we might go far into the following declarations
		    ;; in e.g. ObjC mode (see e.g. methods-4.m).
Martin Stjernholm's avatar
Martin Stjernholm committed
1165 1166
		    (c-syntactic-re-search-forward "[;,{]" limit 'move t)
		    (backward-char)))
1167 1168 1169 1170 1171 1172 1173 1174

	      (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)
1175
	  (setq pos (point))))))     ; acts to make the `while' form continue.
1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187
  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))

(defun c-font-lock-declarations (limit)
1188 1189 1190
  ;; Fontify all the declarations, casts and labels from the point to LIMIT.
  ;; Assumes that strings and comments have been fontified already.
  ;;
1191 1192 1193 1194 1195 1196
  ;; This function will be called from font-lock for a region bounded by POINT
  ;; and LIMIT, as though it were to identify a keyword for
  ;; font-lock-keyword-face.  It always returns NIL to inhibit this and
  ;; prevent a repeat invocation.  See elisp/lispref page "Search-based
  ;; Fontification".
  ;;
1197
  ;; This function might do hidden buffer changes.
1198 1199 1200 1201

  ;;(message "c-font-lock-declarations search from %s to %s" (point) limit)

  (save-restriction
1202
    (let (;; The position where `c-find-decl-spots' last stopped.
1203
	  start-pos
1204 1205 1206 1207 1208 1209 1210
	  ;; o - 'decl if we're in an arglist containing declarations
	  ;;   (but if `c-recognize-paren-inits' is set it might also be
	  ;;   an initializer arglist);
	  ;; o - '<> if the arglist is of angle bracket type;
	  ;; o - 'arglist if it's some other arglist;
	  ;; o - nil, if not in an arglist at all.  This includes the
	  ;;   parenthesised condition which follows "if", "while", etc.
1211 1212 1213
	  context
	  ;; The position of the next token after the closing paren of
	  ;; the last detected cast.
1214
	  last-cast-end
1215 1216 1217 1218 1219 1220 1221
	  ;; The result from `c-forward-decl-or-cast-1'.
	  decl-or-cast
	  ;; 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.
1222 1223 1224 1225
	  (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)
1226 1227 1228 1229 1230 1231 1232
	  ;; Set according to the context to direct the heuristics for
	  ;; recognizing C++ templates.
	  c-restricted-<>-arglists
	  ;; Turn on recording of identifier ranges in
	  ;; `c-forward-decl-or-cast-1' and `c-forward-label' for
	  ;; later fontification.
	  (c-record-type-identifiers t)
1233
	  label-type
1234
	  c-record-ref-identifiers
1235 1236 1237 1238
	  ;; Make `c-forward-type' calls mark up template arglists if
	  ;; it finds any.  That's necessary so that we later will
	  ;; stop inside them to fontify types there.
	  (c-parse-and-markup-<>-arglists t)
1239 1240 1241 1242 1243 1244 1245
	  ;; 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,
1246
      ;; to avoid gaps when jit/lazy-lock fontifies the file a block at a
1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257
      ;; 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.
1258 1259 1260
      (if (<= limit (c-point 'bonl))
	  (narrow-to-region
	   (point-min)
1261 1262 1263 1264 1265 1266 1267
	   (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)
1268
	     (point))))
1269 1270 1271

      (c-find-decl-spots
       limit
1272
       c-decl-start-re
1273 1274 1275
       c-font-lock-maybe-decl-faces

       (lambda (match-pos inside-macro)
1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286
	 (setq start-pos (point))
	 (when
	  ;; The result of the form below is true when we don't recognize a
	  ;; declaration or cast.
	  (if (and (eq (get-text-property (point) 'face)
		       'font-lock-keyword-face)
		   (looking-at c-not-decl-init-keywords))
	      ;; Don't do anything more if we're looking at a keyword that
	      ;; can't start a declaration.
	      t

1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348
	    ;; Set `context' and `c-restricted-<>-arglists'.  Look for
	    ;; "<" for the sake of C++-style template arglists.
	    ;; Ignore "(" when it's part of a control flow construct
	    ;; (e.g. "for (").
	    (let ((type (and (> match-pos (point-min))
			     (c-get-char-property (1- match-pos) 'c-type))))
	      (cond ((not (memq (char-before match-pos) '(?\( ?, ?\[ ?<)))
		     (setq context nil
			   c-restricted-<>-arglists nil))
		    ;; A control flow expression
		    ((and (eq (char-before match-pos) ?\()
			  (save-excursion
			    (goto-char match-pos)
			    (backward-char)
			    (c-backward-token-2)
			    (looking-at c-block-stmt-2-key)))
		     (setq context nil
			   c-restricted-<>-arglists t))
		    ;; Near BOB.
		    ((<= match-pos (point-min))
		     (setq context 'arglist
			   c-restricted-<>-arglists t))
		    ;; Got a cached hit in a declaration arglist.
		    ((eq type 'c-decl-arg-start)
		     (setq context 'decl
			   c-restricted-<>-arglists nil))
		    ;; Inside an angle bracket arglist.
		    ((or (eq type 'c-<>-arg-sep)
			 (eq (char-before match-pos) ?<))
		     (setq context '<>
			   c-restricted-<>-arglists nil))
		    ;; Got a cached hit in some other type of arglist.
		    (type
		     (setq context 'arglist
			   c-restricted-<>-arglists t))
		    ((if inside-macro
			 (< match-pos max-type-decl-end-before-token)
		       (< match-pos max-type-decl-end))
		     ;; The point is within the range of a previously
		     ;; encountered type decl expression, so the arglist
		     ;; is probably one that contains declarations.
		     ;; However, if `c-recognize-paren-inits' is set it
		     ;; might also be an initializer arglist.
		     (setq context 'decl
			   c-restricted-<>-arglists nil)
		     ;; The result of this check is cached with a char
		     ;; property on the match token, so that we can look
		     ;; it up again when refontifying single lines in a
		     ;; multiline declaration.
		     (c-put-char-property (1- match-pos)
					  'c-type 'c-decl-arg-start))
		    (t (setq context 'arglist
			     c-restricted-<>-arglists t))))

	    ;; Check we haven't missed a preceding "typedef".
	    (when (not (looking-at c-typedef-key))
	      (c-backward-syntactic-ws)
	      (c-backward-token-2)
	      (or (looking-at c-typedef-key)
		  (goto-char start-pos)))

	    ;; Now analyze the construct.
1349 1350 1351 1352 1353 1354 1355 1356
	    ;; In QT, "more" is an irritating keyword that expands to nothing.
	    ;; We skip over it to prevent recognition of "more slots: <symbol>"
	    ;; as a bitfield declaration.
	    (when (and (c-major-mode-is 'c++-mode)
		       (looking-at
			(concat "\\(more\\)\\([^" c-symbol-chars "]\\|$\\)")))
	      (goto-char (match-end 1))
	      (c-forward-syntactic-ws))
1357
	    (setq decl-or-cast (c-forward-decl-or-cast-1
1358 1359
				match-pos context last-cast-end))

1360 1361 1362 1363 1364 1365 1366 1367
	    (cond
	     ((eq decl-or-cast 'cast)
	      ;; Save the position after the previous cast so we can feed
	      ;; it to `c-forward-decl-or-cast-1' in the next round.  That
	      ;; helps it discover cast chains like "(a) (b) c".
	      (setq last-cast-end (point))
	      (c-fontify-recorded-types-and-refs)
	      nil)
1368

1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408
	     (decl-or-cast
	      ;; We've found a declaration.

	      ;; Set `max-type-decl-end' or `max-type-decl-end-before-token'
	      ;; under the assumption that we're after the first type decl
	      ;; expression in the declaration now.  That's not really true;
	      ;; we could also be after a parenthesized initializer
	      ;; expression in C++, but this is only used as a last resort
	      ;; to slant ambiguous expression/declarations, and overall
	      ;; it's worth the risk to occasionally fontify an expression
	      ;; as a declaration in an initializer expression compared to
	      ;; getting ambiguous things in normal function prototypes
	      ;; fontified as expressions.
	      (if inside-macro
		  (when (> (point) max-type-decl-end-before-token)
		    (setq max-type-decl-end-before-token (point)))
		(when (> (point) max-type-decl-end)
		  (setq max-type-decl-end (point))))

	      ;; Back up to the type to fontify the declarator(s).
	      (goto-char (car decl-or-cast))

	      (let ((decl-list
		     (if context
			 ;; Should normally not fontify a list of
			 ;; declarators inside an arglist, but the first
			 ;; argument in the ';' separated list of a "for"
			 ;; statement is an exception.
			 (when (eq (char-before match-pos) ?\()
			   (save-excursion
			     (goto-char (1- match-pos))
			     (c-backward-syntactic-ws)
			     (and (c-simple-skip-symbol-backward)
				  (looking-at c-paren-stmt-key))))
		       t)))

		;; Fix the `c-decl-id-start' or `c-decl-type-start' property
		;; before the first declarator if it's a list.
		;; `c-font-lock-declarators' handles the rest.
		(when decl-list
1409
		  (save-excursion
1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421
		    (c-backward-syntactic-ws)
		    (unless (bobp)
		      (c-put-char-property (1- (point)) 'c-type
					   (if (cdr decl-or-cast)
					       'c-decl-type-start
					     'c-decl-id-start)))))

		(c-font-lock-declarators
		 (point-max) decl-list (cdr decl-or-cast)))

	      ;; A declaration has been successfully identified, so do all the
	      ;; fontification of types and refs that've been recorded.
1422
	      (c-fontify-recorded-types-and-refs)
1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460
	      nil)

	     (t
	      ;; Are we at a declarator?  Try to go back to the declaration
	      ;; to check this.  If we get there, check whether a "typedef"
	      ;; is there, then fontify the declarators accordingly.
	      (let ((decl-search-lim (max (- (point) 50000) (point-min)))
		    paren-state bod-res encl-pos is-typedef 
		    c-recognize-knr-p) ; Strictly speaking, bogus, but it
				       ; speeds up lisp.h tremendously.
		(save-excursion
		  (setq bod-res (car (c-beginning-of-decl