1;;; cc-fonts.el --- font lock support for CC Mode 2 3;; Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. 4 5;; Authors: 2003- Alan Mackenzie 6;; 2002- Martin Stjernholm 7;; Maintainer: bug-cc-mode@gnu.org 8;; Created: 07-Jan-2002 9;; Version: See cc-mode.el 10;; Keywords: c languages oop 11 12;; This file is part of GNU Emacs. 13 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;; the Free Software Foundation; either version 2, or (at your option) 17;; any later version. 18 19;; GNU Emacs is distributed in the hope that it will be useful, 20;; but WITHOUT ANY WARRANTY; without even the implied warranty of 21;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22;; GNU General Public License for more details. 23 24;; You should have received a copy of the GNU General Public License 25;; along with this program; see the file COPYING. If not, write to 26;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 27;; Boston, MA 02110-1301, USA. 28 29;;; Commentary: 30 31;; Some comments on the use of faces: 32;; 33;; o `c-label-face-name' is either `font-lock-constant-face' (in 34;; Emacs), or `font-lock-reference-face'. 35;; 36;; o `c-constant-face-name', `c-reference-face-name' and 37;; `c-doc-markup-face-name' are essentially set up like 38;; `c-label-face-name'. 39;; 40;; o `c-preprocessor-face-name' is `font-lock-preprocessor-face' in 41;; XEmacs and - in lack of a closer equivalent - 42;; `font-lock-builtin-face' or `font-lock-reference-face' in Emacs. 43;; 44;; o `c-doc-face-name' is `font-lock-doc-string-face' in XEmacs, 45;; `font-lock-doc-face' in Emacs 21 and later, or 46;; `font-lock-comment-face' in older Emacs (that since source 47;; documentation are actually comments in these languages, as opposed 48;; to elisp). 49;; 50;; TBD: We should probably provide real faces for the above uses and 51;; instead initialize them from the standard faces. 52 53;;; Code: 54 55;; The faces that already have been put onto the text is tested in 56;; various places to direct further fontifications. For this to work, 57;; the following assumptions regarding the faces must hold (apart from 58;; the dependencies on the font locking order): 59;; 60;; o `font-lock-comment-face' and the face in `c-doc-face-name' is 61;; not used in anything but comments. 62;; o If any face (e.g. `c-doc-markup-face-name') but those above is 63;; used in comments, it doesn't replace them. 64;; o `font-lock-string-face' is not used in anything but string 65;; literals (single or double quoted). 66;; o `font-lock-keyword-face' and the face in `c-label-face-name' are 67;; never overlaid with other faces. 68 69(eval-when-compile 70 (let ((load-path 71 (if (and (boundp 'byte-compile-dest-file) 72 (stringp byte-compile-dest-file)) 73 (cons (file-name-directory byte-compile-dest-file) load-path) 74 load-path))) 75 (load "cc-bytecomp" nil t))) 76 77(cc-require 'cc-defs) 78(cc-require-when-compile 'cc-langs) 79(cc-require 'cc-vars) 80(cc-require 'cc-engine) 81(cc-require-when-compile 'cc-awk) ; Change from cc-require, 2003/6/18 to 82;; prevent cc-awk being loaded when it's not needed. There is now a (require 83;; 'cc-awk) in (defun awk-mode ..). 84 85;; Avoid repeated loading through the eval-after-load directive in 86;; cc-mode.el. 87(provide 'cc-fonts) 88 89(cc-external-require 'font-lock) 90 91(cc-bytecomp-defvar parse-sexp-lookup-properties) ; Emacs only. 92 93;; Need to declare these local symbols during compilation since 94;; they're referenced from lambdas in `byte-compile' calls that are 95;; executed at compile time. They don't need to have the proper 96;; definitions, though, since the generated functions aren't called 97;; during compilation. 98(cc-bytecomp-defvar c-preprocessor-face-name) 99(cc-bytecomp-defvar c-reference-face-name) 100(cc-bytecomp-defun c-fontify-recorded-types-and-refs) 101(cc-bytecomp-defun c-font-lock-declarators) 102(cc-bytecomp-defun c-font-lock-objc-method) 103(cc-bytecomp-defun c-font-lock-invalid-string) 104 105 106;; Note that font-lock in XEmacs doesn't expand face names as 107;; variables, so we have to use the (eval . FORM) in the font lock 108;; matchers wherever we use these alias variables. 109 110(defconst c-preprocessor-face-name 111 (cond ((c-face-name-p 'font-lock-preprocessor-face) 112 ;; XEmacs has a font-lock-preprocessor-face. 113 'font-lock-preprocessor-face) 114 ((c-face-name-p 'font-lock-builtin-face) 115 ;; In Emacs font-lock-builtin-face has traditionally been 116 ;; used for preprocessor directives. 117 'font-lock-builtin-face) 118 (t 119 'font-lock-reference-face))) 120 121(cc-bytecomp-defvar font-lock-constant-face) 122 123(defconst c-label-face-name 124 (cond ((c-face-name-p 'font-lock-label-face) 125 ;; If it happens to occur in the future. (Well, the more 126 ;; pragmatic reason is to get unique faces for the test 127 ;; suite.) 128 'font-lock-label-face) 129 ((and (c-face-name-p 'font-lock-constant-face) 130 (eq font-lock-constant-face 'font-lock-constant-face)) 131 ;; Test both if font-lock-constant-face exists and that it's 132 ;; not an alias for something else. This is important since 133 ;; we compare already set faces in various places. 134 'font-lock-constant-face) 135 (t 136 'font-lock-reference-face))) 137 138(defconst c-constant-face-name 139 (if (and (c-face-name-p 'font-lock-constant-face) 140 (eq font-lock-constant-face 'font-lock-constant-face)) 141 ;; This doesn't exist in some earlier versions of XEmacs 21. 142 'font-lock-constant-face 143 c-label-face-name)) 144 145(defconst c-reference-face-name 146 (with-no-warnings 147 (if (and (c-face-name-p 'font-lock-reference-face) 148 (eq font-lock-reference-face 'font-lock-reference-face)) 149 ;; This is considered obsolete in Emacs, but it still maps well 150 ;; to this use. (Another reason to do this is to get unique 151 ;; faces for the test suite.) 152 'font-lock-reference-face 153 c-label-face-name))) 154 155;; This should not mapped to a face that also is used to fontify things 156;; that aren't comments or string literals. 157(defconst c-doc-face-name 158 (cond ((c-face-name-p 'font-lock-doc-string-face) 159 ;; XEmacs. 160 'font-lock-doc-string-face) 161 ((c-face-name-p 'font-lock-doc-face) 162 ;; Emacs 21 and later. 163 'font-lock-doc-face) 164 (t 165 'font-lock-comment-face))) 166 167(defconst c-doc-markup-face-name 168 (if (c-face-name-p 'font-lock-doc-markup-face) 169 ;; If it happens to occur in the future. (Well, the more 170 ;; pragmatic reason is to get unique faces for the test 171 ;; suite.) 172 'font-lock-doc-markup-face 173 c-label-face-name)) 174 175(defconst c-negation-char-face-name 176 (if (c-face-name-p 'font-lock-negation-char-face) 177 ;; Emacs 22 has a special face for negation chars. 178 'font-lock-negation-char-face)) 179 180(cc-bytecomp-defun face-inverse-video-p) ; Only in Emacs. 181(cc-bytecomp-defun face-property-instance) ; Only in XEmacs. 182 183(defun c-make-inverse-face (oldface newface) 184 ;; Emacs and XEmacs have completely different face manipulation 185 ;; routines. :P 186 (copy-face oldface newface) 187 (cond ((fboundp 'face-inverse-video-p) 188 ;; Emacs. This only looks at the inverse flag in the current 189 ;; frame. Other display configurations might be different, 190 ;; but it can only show if the same Emacs has frames on 191 ;; e.g. a color and a monochrome display simultaneously. 192 (unless (face-inverse-video-p oldface) 193 (invert-face newface))) 194 ((fboundp 'face-property-instance) 195 ;; XEmacs. Same pitfall here. 196 (unless (face-property-instance oldface 'reverse) 197 (invert-face newface))))) 198 199(eval-and-compile 200 ;; We need the following functions during compilation since they're 201 ;; called when the `c-lang-defconst' initializers are evaluated. 202 ;; Define them at runtime too for the sake of derived modes. 203 204 (defmacro c-put-font-lock-face (from to face) 205 ;; Put a face on a region (overriding any existing face) in the way 206 ;; font-lock would do it. In XEmacs that means putting an 207 ;; additional font-lock property, or else the font-lock package 208 ;; won't recognize it as fontified and might override it 209 ;; incorrectly. 210 ;; 211 ;; This function does a hidden buffer change. 212 (if (fboundp 'font-lock-set-face) 213 ;; Note: This function has no docstring in XEmacs so it might be 214 ;; considered internal. 215 `(font-lock-set-face ,from ,to ,face) 216 `(put-text-property ,from ,to 'face ,face))) 217 218 (defmacro c-remove-font-lock-face (from to) 219 ;; This is the inverse of `c-put-font-lock-face'. 220 ;; 221 ;; This function does a hidden buffer change. 222 (if (fboundp 'font-lock-remove-face) 223 `(font-lock-remove-face ,from ,to) 224 `(remove-text-properties ,from ,to '(face nil)))) 225 226 (defmacro c-put-font-lock-string-face (from to) 227 ;; Put `font-lock-string-face' on a string. The surrounding 228 ;; quotes are included in Emacs but not in XEmacs. The passed 229 ;; region should include them. 230 ;; 231 ;; This function does a hidden buffer change. 232 (if (featurep 'xemacs) 233 `(c-put-font-lock-face (1+ ,from) (1- ,to) 'font-lock-string-face) 234 `(c-put-font-lock-face ,from ,to 'font-lock-string-face))) 235 236 (defmacro c-fontify-types-and-refs (varlist &rest body) 237 ;; Like `let', but additionally activates `c-record-type-identifiers' 238 ;; and `c-record-ref-identifiers', and fontifies the recorded ranges 239 ;; accordingly on exit. 240 ;; 241 ;; This function does hidden buffer changes. 242 `(let ((c-record-type-identifiers t) 243 c-record-ref-identifiers 244 ,@varlist) 245 (prog1 (progn ,@body) 246 (c-fontify-recorded-types-and-refs)))) 247 (put 'c-fontify-types-and-refs 'lisp-indent-function 1) 248 249 (defun c-skip-comments-and-strings (limit) 250 ;; If the point is within a region fontified as a comment or 251 ;; string literal skip to the end of it or to LIMIT, whichever 252 ;; comes first, and return t. Otherwise return nil. The match 253 ;; data is not clobbered. 254 ;; 255 ;; This function might do hidden buffer changes. 256 (when (c-got-face-at (point) c-literal-faces) 257 (while (progn 258 (goto-char (next-single-property-change 259 (point) 'face nil limit)) 260 (and (< (point) limit) 261 (c-got-face-at (point) c-literal-faces)))) 262 t)) 263 264 (defun c-make-syntactic-matcher (regexp) 265 ;; Returns a byte compiled function suitable for use in place of a 266 ;; regexp string in a `font-lock-keywords' matcher, except that 267 ;; only matches outside comments and string literals count. 268 ;; 269 ;; This function does not do any hidden buffer changes, but the 270 ;; generated functions will. (They are however used in places 271 ;; covered by the font-lock context.) 272 (byte-compile 273 `(lambda (limit) 274 (let (res) 275 (while (and (setq res (re-search-forward ,regexp limit t)) 276 (progn 277 (goto-char (match-beginning 0)) 278 (or (c-skip-comments-and-strings limit) 279 (progn 280 (goto-char (match-end 0)) 281 nil))))) 282 res)))) 283 284 (defun c-make-font-lock-search-function (regexp &rest highlights) 285 ;; This function makes a byte compiled function that works much like 286 ;; a matcher element in `font-lock-keywords'. It cuts out a little 287 ;; bit of the overhead compared to a real matcher. The main reason 288 ;; is however to pass the real search limit to the anchored 289 ;; matcher(s), since most (if not all) font-lock implementations 290 ;; arbitrarily limits anchored matchers to the same line, and also 291 ;; to insulate against various other irritating differences between 292 ;; the different (X)Emacs font-lock packages. 293 ;; 294 ;; REGEXP is the matcher, which must be a regexp. Only matches 295 ;; where the beginning is outside any comment or string literal are 296 ;; significant. 297 ;; 298 ;; HIGHLIGHTS is a list of highlight specs, just like in 299 ;; `font-lock-keywords', with these limitations: The face is always 300 ;; overridden (no big disadvantage, since hits in comments etc are 301 ;; filtered anyway), there is no "laxmatch", and an anchored matcher 302 ;; is always a form which must do all the fontification directly. 303 ;; `limit' is a variable bound to the real limit in the context of 304 ;; the anchored matcher forms. 305 ;; 306 ;; This function does not do any hidden buffer changes, but the 307 ;; generated functions will. (They are however used in places 308 ;; covered by the font-lock context.) 309 310 ;; Note: Replace `byte-compile' with `eval' to debug the generated 311 ;; lambda easier. 312 (byte-compile 313 `(lambda (limit) 314 (let (;; The font-lock package in Emacs is known to clobber 315 ;; `parse-sexp-lookup-properties' (when it exists). 316 (parse-sexp-lookup-properties 317 (cc-eval-when-compile 318 (boundp 'parse-sexp-lookup-properties)))) 319 (while (re-search-forward ,regexp limit t) 320 (unless (progn 321 (goto-char (match-beginning 0)) 322 (c-skip-comments-and-strings limit)) 323 (goto-char (match-end 0)) 324 ,@(mapcar 325 (lambda (highlight) 326 (if (integerp (car highlight)) 327 (progn 328 (unless (eq (nth 2 highlight) t) 329 (error 330 "The override flag must currently be t in %s" 331 highlight)) 332 (when (nth 3 highlight) 333 (error 334 "The laxmatch flag may currently not be set in %s" 335 highlight)) 336 `(save-match-data 337 (c-put-font-lock-face 338 (match-beginning ,(car highlight)) 339 (match-end ,(car highlight)) 340 ,(elt highlight 1)))) 341 (when (nth 3 highlight) 342 (error "Match highlights currently not supported in %s" 343 highlight)) 344 `(progn 345 ,(nth 1 highlight) 346 (save-match-data ,(car highlight)) 347 ,(nth 2 highlight)))) 348 highlights)))) 349 nil))) 350 351; (eval-after-load "edebug" ; 2006-07-09: def-edebug-spec is now in subr.el. 352; '(progn 353 (def-edebug-spec c-fontify-types-and-refs let*) 354 (def-edebug-spec c-make-syntactic-matcher t) 355 ;; If there are literal quoted or backquoted highlight specs in 356 ;; the call to `c-make-font-lock-search-function' then let's 357 ;; instrument the forms in them. 358 (def-edebug-spec c-make-font-lock-search-function 359 (form &rest &or ("quote" (&rest form)) ("`" (&rest form)) form)));)) 360 361(defun c-fontify-recorded-types-and-refs () 362 ;; Convert the ranges recorded on `c-record-type-identifiers' and 363 ;; `c-record-ref-identifiers' to fontification. 364 ;; 365 ;; This function does hidden buffer changes. 366 (let (elem) 367 (while (consp c-record-type-identifiers) 368 (setq elem (car c-record-type-identifiers) 369 c-record-type-identifiers (cdr c-record-type-identifiers)) 370 (c-put-font-lock-face (car elem) (cdr elem) 371 'font-lock-type-face)) 372 (while c-record-ref-identifiers 373 (setq elem (car c-record-ref-identifiers) 374 c-record-ref-identifiers (cdr c-record-ref-identifiers)) 375 ;; Note that the reference face is a variable that is 376 ;; dereferenced, since it's an alias in Emacs. 377 (c-put-font-lock-face (car elem) (cdr elem) 378 c-reference-face-name)))) 379 380(c-lang-defconst c-cpp-matchers 381 "Font lock matchers for preprocessor directives and purely lexical 382stuff. Used on level 1 and higher." 383 384 ;; Note: `c-font-lock-declarations' assumes that no matcher here 385 ;; sets `font-lock-type-face' in languages where 386 ;; `c-recognize-<>-arglists' is set. 387 388 t `(,@(when (c-lang-const c-opt-cpp-prefix) 389 (let* ((noncontinued-line-end "\\(\\=\\|\\(\\=\\|[^\\]\\)[\n\r]\\)") 390 (ncle-depth (regexp-opt-depth noncontinued-line-end)) 391 (sws-depth (c-lang-const c-syntactic-ws-depth)) 392 (nsws-depth (c-lang-const c-nonempty-syntactic-ws-depth))) 393 394 `(;; The stuff after #error and #warning is a message, so 395 ;; fontify it as a string. 396 ,@(when (c-lang-const c-cpp-message-directives) 397 (let* ((re (c-make-keywords-re nil 398 (c-lang-const c-cpp-message-directives))) 399 (re-depth (regexp-opt-depth re))) 400 `((,(concat noncontinued-line-end 401 (c-lang-const c-opt-cpp-prefix) 402 re 403 "\\s +\\(.*\\)$") 404 ,(+ ncle-depth re-depth 1) font-lock-string-face)))) 405 406 ;; Fontify filenames in #include <...> as strings. 407 ,@(when (c-lang-const c-cpp-include-directives) 408 (let* ((re (c-make-keywords-re nil 409 (c-lang-const c-cpp-include-directives))) 410 (re-depth (regexp-opt-depth re))) 411 `((,(concat noncontinued-line-end 412 (c-lang-const c-opt-cpp-prefix) 413 re 414 (c-lang-const c-syntactic-ws) 415 "\\(<[^>\n\r]*>?\\)") 416 (,(+ ncle-depth re-depth sws-depth 1) 417 font-lock-string-face) 418 419 ;; Use an anchored matcher to put paren syntax 420 ;; on the brackets. 421 (,(byte-compile 422 `(lambda (limit) 423 (let ((beg (match-beginning 424 ,(+ ncle-depth re-depth sws-depth 1))) 425 (end (1- (match-end ,(+ ncle-depth re-depth 426 sws-depth 1))))) 427 (if (eq (char-after end) ?>) 428 (progn 429 (c-mark-<-as-paren beg) 430 (c-mark->-as-paren end)) 431 (c-clear-char-property beg 'syntax-table))) 432 nil))))))) 433 434 ;; #define. 435 ,@(when (c-lang-const c-opt-cpp-macro-define) 436 `((,(c-make-font-lock-search-function 437 (concat 438 noncontinued-line-end 439 (c-lang-const c-opt-cpp-prefix) 440 (c-lang-const c-opt-cpp-macro-define) 441 (c-lang-const c-nonempty-syntactic-ws) 442 "\\(" (c-lang-const ; 1 + ncle + nsws 443 c-symbol-key) "\\)" 444 (concat "\\(" ; 2 + ncle + nsws + c-sym-key 445 ;; Macro with arguments - a "function". 446 "\\(\(\\)" ; 3 + ncle + nsws + c-sym-key 447 "\\|" 448 ;; Macro without arguments - a "variable". 449 "\\([^\(]\\|$\\)" 450 "\\)")) 451 `((if (match-beginning 452 ,(+ 3 ncle-depth nsws-depth 453 (c-lang-const c-symbol-key-depth))) 454 455 ;; "Function". Fontify the name and the arguments. 456 (save-restriction 457 (c-put-font-lock-face 458 (match-beginning ,(+ 1 ncle-depth nsws-depth)) 459 (match-end ,(+ 1 ncle-depth nsws-depth)) 460 'font-lock-function-name-face) 461 (goto-char 462 (match-end 463 ,(+ 3 ncle-depth nsws-depth 464 (c-lang-const c-symbol-key-depth)))) 465 466 (narrow-to-region (point-min) limit) 467 (while (and 468 (progn 469 (c-forward-syntactic-ws) 470 (looking-at c-symbol-key)) 471 (progn 472 (c-put-font-lock-face 473 (match-beginning 0) (match-end 0) 474 'font-lock-variable-name-face) 475 (goto-char (match-end 0)) 476 (c-forward-syntactic-ws) 477 (eq (char-after) ?,))) 478 (forward-char))) 479 480 ;; "Variable". 481 (c-put-font-lock-face 482 (match-beginning ,(+ 1 ncle-depth nsws-depth)) 483 (match-end ,(+ 1 ncle-depth nsws-depth)) 484 'font-lock-variable-name-face))))))) 485 486 ;; Fontify cpp function names in preprocessor 487 ;; expressions in #if and #elif. 488 ,@(when (and (c-lang-const c-cpp-expr-directives) 489 (c-lang-const c-cpp-expr-functions)) 490 (let ((ced-re (c-make-keywords-re t 491 (c-lang-const c-cpp-expr-directives))) 492 (cef-re (c-make-keywords-re t 493 (c-lang-const c-cpp-expr-functions)))) 494 `((,(c-make-font-lock-search-function 495 (concat noncontinued-line-end 496 (c-lang-const c-opt-cpp-prefix) 497 ced-re ; 1 + ncle-depth 498 ;; Match the whole logical line to look 499 ;; for the functions in. 500 "\\(\\\\\\(.\\|[\n\r]\\)\\|[^\n\r]\\)*") 501 `((let ((limit (match-end 0))) 502 (while (re-search-forward ,cef-re limit 'move) 503 (c-put-font-lock-face (match-beginning 1) 504 (match-end 1) 505 c-preprocessor-face-name))) 506 (goto-char (match-end ,(1+ ncle-depth))))))))) 507 508 ;; Fontify the directive names. 509 (,(c-make-font-lock-search-function 510 (concat noncontinued-line-end 511 "\\(" 512 (c-lang-const c-opt-cpp-prefix) 513 "[" (c-lang-const c-symbol-chars) "]+" 514 "\\)") 515 `(,(1+ ncle-depth) c-preprocessor-face-name t))) 516 517 (eval . (list ,(c-make-syntactic-matcher 518 (concat noncontinued-line-end 519 (c-lang-const c-opt-cpp-prefix) 520 "if\\(n\\)def\\>")) 521 ,(+ ncle-depth 1) 522 c-negation-char-face-name 523 'append)) 524 ))) 525 526 ,@(when (c-major-mode-is 'pike-mode) 527 ;; Recognize hashbangs in Pike. 528 `((eval . (list "\\`#![^\n\r]*" 529 0 c-preprocessor-face-name)))) 530 531 ;; Make hard spaces visible through an inverted `font-lock-warning-face'. 532 (eval . (list 533 "\240" 534 0 (progn 535 (unless (c-face-name-p 'c-nonbreakable-space-face) 536 (c-make-inverse-face 'font-lock-warning-face 537 'c-nonbreakable-space-face)) 538 ''c-nonbreakable-space-face))) 539 )) 540 541(defun c-font-lock-invalid-string () 542 ;; Assuming the point is after the opening character of a string, 543 ;; fontify that char with `font-lock-warning-face' if the string 544 ;; decidedly isn't terminated properly. 545 ;; 546 ;; This function does hidden buffer changes. 547 (let ((start (1- (point)))) 548 (save-excursion 549 (and (eq (elt (parse-partial-sexp start (c-point 'eol)) 8) start) 550 (if (integerp c-multiline-string-start-char) 551 ;; There's no multiline string start char before the 552 ;; string, so newlines aren't allowed. 553 (not (eq (char-before start) c-multiline-string-start-char)) 554 ;; Multiline strings are allowed anywhere if 555 ;; c-multiline-string-start-char is t. 556 (not c-multiline-string-start-char)) 557 (if c-string-escaped-newlines 558 ;; There's no \ before the newline. 559 (not (eq (char-before (point)) ?\\)) 560 ;; Escaped newlines aren't supported. 561 t) 562 (c-put-font-lock-face start (1+ start) 'font-lock-warning-face))))) 563 564(c-lang-defconst c-basic-matchers-before 565 "Font lock matchers for basic keywords, labels, references and various 566other easily recognizable things that should be fontified before generic 567casts and declarations are fontified. Used on level 2 and higher." 568 569 ;; Note: `c-font-lock-declarations' assumes that no matcher here 570 ;; sets `font-lock-type-face' in languages where 571 ;; `c-recognize-<>-arglists' is set. 572 573 t `(;; Put a warning face on the opener of unclosed strings that 574 ;; can't span lines. Later font 575 ;; lock packages have a `font-lock-syntactic-face-function' for 576 ;; this, but it doesn't give the control we want since any 577 ;; fontification done inside the function will be 578 ;; unconditionally overridden. 579 ,(c-make-font-lock-search-function 580 ;; Match a char before the string starter to make 581 ;; `c-skip-comments-and-strings' work correctly. 582 (concat ".\\(" c-string-limit-regexp "\\)") 583 '((c-font-lock-invalid-string))) 584 585 ;; Fontify keyword constants. 586 ,@(when (c-lang-const c-constant-kwds) 587 (let ((re (c-make-keywords-re nil (c-lang-const c-constant-kwds)))) 588 (if (c-major-mode-is 'pike-mode) 589 ;; No symbol is a keyword after "->" in Pike. 590 `((eval . (list ,(concat "\\(\\=.?\\|[^>]\\|[^-]>\\)" 591 "\\<\\(" re "\\)\\>") 592 2 c-constant-face-name))) 593 `((eval . (list ,(concat "\\<\\(" re "\\)\\>") 594 1 c-constant-face-name)))))) 595 596 ;; Fontify all keywords except the primitive types. 597 ,(if (c-major-mode-is 'pike-mode) 598 ;; No symbol is a keyword after "->" in Pike. 599 `(,(concat "\\(\\=.?\\|[^>]\\|[^-]>\\)" 600 "\\<" (c-lang-const c-regular-keywords-regexp)) 601 2 font-lock-keyword-face) 602 `(,(concat "\\<" (c-lang-const c-regular-keywords-regexp)) 603 1 font-lock-keyword-face)) 604 605 ;; Fontify leading identifiers in fully qualified names like 606 ;; "foo::bar" in languages that supports such things. 607 ,@(when (c-lang-const c-opt-identifier-concat-key) 608 (if (c-major-mode-is 'java-mode) 609 ;; Java needs special treatment since "." is used both to 610 ;; qualify names and in normal indexing. Here we look for 611 ;; capital characters at the beginning of an identifier to 612 ;; recognize the class. "*" is also recognized to cover 613 ;; wildcard import declarations. All preceding dot separated 614 ;; identifiers are taken as package names and therefore 615 ;; fontified as references. 616 `(,(c-make-font-lock-search-function 617 ;; Search for class identifiers preceded by ".". The 618 ;; anchored matcher takes it from there. 619 (concat (c-lang-const c-opt-identifier-concat-key) 620 (c-lang-const c-simple-ws) "*" 621 (concat "\\(" 622 "[" c-upper "]" 623 "[" (c-lang-const c-symbol-chars) "]*" 624 "\\|" 625 "\\*" 626 "\\)")) 627 `((let (id-end) 628 (goto-char (1+ (match-beginning 0))) 629 (while (and (eq (char-before) ?.) 630 (progn 631 (backward-char) 632 (c-backward-syntactic-ws) 633 (setq id-end (point)) 634 (< (skip-chars-backward 635 ,(c-lang-const c-symbol-chars)) 0)) 636 (not (get-text-property (point) 'face))) 637 (c-put-font-lock-face (point) id-end 638 c-reference-face-name) 639 (c-backward-syntactic-ws))) 640 nil 641 (goto-char (match-end 0))))) 642 643 `((,(byte-compile 644 ;; Must use a function here since we match longer than 645 ;; we want to move before doing a new search. This is 646 ;; not necessary for XEmacs since it restarts the 647 ;; search from the end of the first highlighted 648 ;; submatch (something that causes problems in other 649 ;; places). 650 `(lambda (limit) 651 (while (re-search-forward 652 ,(concat "\\(\\<" ; 1 653 "\\(" (c-lang-const c-symbol-key) "\\)" ; 2 654 (c-lang-const c-simple-ws) "*" 655 (c-lang-const c-opt-identifier-concat-key) 656 (c-lang-const c-simple-ws) "*" 657 "\\)" 658 "\\(" 659 (c-lang-const c-opt-after-id-concat-key) 660 "\\)") 661 limit t) 662 (unless (progn 663 (goto-char (match-beginning 0)) 664 (c-skip-comments-and-strings limit)) 665 (or (get-text-property (match-beginning 2) 'face) 666 (c-put-font-lock-face (match-beginning 2) 667 (match-end 2) 668 c-reference-face-name)) 669 (goto-char (match-end 1)))))))))) 670 671 ;; Fontify the special declarations in Objective-C. 672 ,@(when (c-major-mode-is 'objc-mode) 673 `(;; Fontify class names in the beginning of message expressions. 674 ,(c-make-font-lock-search-function 675 "\\[" 676 '((c-fontify-types-and-refs () 677 (c-forward-syntactic-ws limit) 678 (let ((start (point))) 679 ;; In this case we accept both primitive and known types. 680 (when (eq (c-forward-type) 'known) 681 (goto-char start) 682 (let ((c-promote-possible-types t)) 683 (c-forward-type)))) 684 (if (> (point) limit) (goto-char limit))))) 685 686 ;; The @interface/@implementation/@protocol directives. 687 ,(c-make-font-lock-search-function 688 (concat "\\<" 689 (regexp-opt 690 '("@interface" "@implementation" "@protocol") 691 t) 692 "\\>") 693 '((c-fontify-types-and-refs 694 (;; The font-lock package in Emacs is known to clobber 695 ;; `parse-sexp-lookup-properties' (when it exists). 696 (parse-sexp-lookup-properties 697 (cc-eval-when-compile 698 (boundp 'parse-sexp-lookup-properties)))) 699 (c-forward-objc-directive) 700 nil) 701 (goto-char (match-beginning 0)))))) 702 703 (eval . (list "\\(!\\)[^=]" 1 c-negation-char-face-name)) 704 )) 705 706(defun c-font-lock-complex-decl-prepare (limit) 707 ;; This function will be called from font-lock for a region bounded by POINT 708 ;; and LIMIT, as though it were to identify a keyword for 709 ;; font-lock-keyword-face. It always returns NIL to inhibit this and 710 ;; prevent a repeat invocation. See elisp/lispref page "Search-based 711 ;; Fontification". 712 ;; 713 ;; Called before any of the matchers in `c-complex-decl-matchers'. 714 ;; 715 ;; This function does hidden buffer changes. 716 717 ;;(message "c-font-lock-complex-decl-prepare %s %s" (point) limit) 718 719 ;; Clear the list of found types if we start from the start of the 720 ;; buffer, to make it easier to get rid of misspelled types and 721 ;; variables that has gotten recognized as types in malformed code. 722 (when (bobp) 723 (c-clear-found-types)) 724 725 ;; Clear the c-type char properties in the region to recalculate 726 ;; them properly. This is necessary e.g. to handle constructs that 727 ;; might been required as declarations temporarily during editing. 728 ;; The interesting properties are anyway those put on the closest 729 ;; token before the region. 730 (c-clear-char-properties (point) limit 'c-type) 731 732 ;; Update `c-state-cache' to the beginning of the region. This will 733 ;; make `c-beginning-of-syntax' go faster when it's used later on, 734 ;; and it's near the point most of the time. 735 (c-parse-state) 736 737 ;; Check if the fontified region starts inside a declarator list so 738 ;; that `c-font-lock-declarators' should be called at the start. 739 (let ((prop (save-excursion 740 (c-backward-syntactic-ws) 741 (unless (bobp) 742 (c-get-char-property (1- (point)) 'c-type))))) 743 (when (memq prop '(c-decl-id-start c-decl-type-start)) 744 (c-forward-syntactic-ws limit) 745 (c-font-lock-declarators limit t (eq prop 'c-decl-type-start)))) 746 747 nil) 748 749(defun c-font-lock-<>-arglists (limit) 750 ;; This function will be called from font-lock for a region bounded by POINT 751 ;; and LIMIT, as though it were to identify a keyword for 752 ;; font-lock-keyword-face. It always returns NIL to inhibit this and 753 ;; prevent a repeat invocation. See elisp/lispref page "Search-based 754 ;; Fontification". 755 ;; 756 ;; Fontify types and references in names containing angle bracket 757 ;; arglists from the point to LIMIT. Note that 758 ;; `c-font-lock-declarations' already has handled many of them. 759 ;; 760 ;; This function might do hidden buffer changes. 761 762 (let (;; The font-lock package in Emacs is known to clobber 763 ;; `parse-sexp-lookup-properties' (when it exists). 764 (parse-sexp-lookup-properties 765 (cc-eval-when-compile 766 (boundp 'parse-sexp-lookup-properties))) 767 (c-parse-and-markup-<>-arglists t) 768 c-restricted-<>-arglists 769 id-start id-end id-face pos kwd-sym) 770 771 (while (and (< (point) limit) 772 (re-search-forward c-opt-<>-arglist-start limit t)) 773 774 (setq id-start (match-beginning 1) 775 id-end (match-end 1) 776 pos (point)) 777 778 (goto-char id-start) 779 (unless (c-skip-comments-and-strings limit) 780 (setq kwd-sym nil 781 c-restricted-<>-arglists nil 782 id-face (get-text-property id-start 'face)) 783 784 (if (cond 785 ((eq id-face 'font-lock-type-face) 786 ;; The identifier got the type face so it has already been 787 ;; handled in `c-font-lock-declarations'. 788 nil) 789 790 ((eq id-face 'font-lock-keyword-face) 791 (when (looking-at c-opt-<>-sexp-key) 792 ;; There's a special keyword before the "<" that tells 793 ;; that it's an angle bracket arglist. 794 (setq kwd-sym (c-keyword-sym (match-string 1))))) 795 796 (t 797 ;; There's a normal identifier before the "<". If we're not in 798 ;; a declaration context then we set `c-restricted-<>-arglists' 799 ;; to avoid recognizing templates in function calls like "foo (a 800 ;; < b, c > d)". 801 (c-backward-syntactic-ws) 802 (when (and (memq (char-before) '(?\( ?,)) 803 (not (eq (get-text-property (1- (point)) 'c-type) 804 'c-decl-arg-start))) 805 (setq c-restricted-<>-arglists t)) 806 t)) 807 808 (progn 809 (goto-char (1- pos)) 810 ;; Check for comment/string both at the identifier and 811 ;; at the "<". 812 (unless (c-skip-comments-and-strings limit) 813 814 (c-fontify-types-and-refs () 815 (when (c-forward-<>-arglist (c-keyword-member 816 kwd-sym 'c-<>-type-kwds)) 817 (when (and c-opt-identifier-concat-key 818 (not (get-text-property id-start 'face))) 819 (c-forward-syntactic-ws) 820 (if (looking-at c-opt-identifier-concat-key) 821 (c-put-font-lock-face id-start id-end 822 c-reference-face-name) 823 (c-put-font-lock-face id-start id-end 824 'font-lock-type-face))))) 825 826 (goto-char pos))) 827 (goto-char pos))))) 828 nil) 829 830(defun c-font-lock-declarators (limit list types) 831 ;; Assuming the point is at the start of a declarator in a 832 ;; declaration, fontify it. If LIST is non-nil, fontify also all 833 ;; following declarators in a comma separated list (e.g. "foo" and 834 ;; "bar" in "int foo = 17, bar;"). Stop at LIMIT. If TYPES is 835 ;; non-nil, fontify all identifiers as types. Nil is always 836 ;; returned. 837 ;; 838 ;; This function might do hidden buffer changes. 839 840 ;;(message "c-font-lock-declarators from %s to %s" (point) limit) 841 (c-fontify-types-and-refs 842 ((pos (point)) next-pos id-start id-end 843 paren-depth 844 id-face got-init 845 c-last-identifier-range 846 (separator-prop (if types 'c-decl-type-start 'c-decl-id-start))) 847 848 (while (and 849 pos 850 (< (point) limit) 851 852 (let (got-identifier) 853 (setq paren-depth 0) 854 ;; Skip over type decl prefix operators. (Note similar 855 ;; code in `c-forward-decl-or-cast-1'.) 856 (while (and (looking-at c-type-decl-prefix-key) 857 (if (and (c-major-mode-is 'c++-mode) 858 (match-beginning 2)) 859 ;; If the second submatch matches in C++ then 860 ;; we're looking at an identifier that's a 861 ;; prefix only if it specifies a member pointer. 862 (progn 863 (setq id-start (point)) 864 (c-forward-name) 865 (if (looking-at "\\(::\\)") 866 ;; We only check for a trailing "::" and 867 ;; let the "*" that should follow be 868 ;; matched in the next round. 869 t 870 ;; It turned out to be the real identifier, 871 ;; so flag that and stop. 872 (setq got-identifier t) 873 nil)) 874 t)) 875 (if (eq (char-after) ?\() 876 (progn 877 (setq paren-depth (1+ paren-depth)) 878 (forward-char)) 879 (goto-char (match-end 1))) 880 (c-forward-syntactic-ws)) 881 882 ;; If we didn't pass the identifier above already, do it now. 883 (unless got-identifier 884 (setq id-start (point)) 885 (c-forward-name)) 886 (setq id-end (point)) 887 888 (/= id-end pos)) 889 890 ;; Skip out of the parens surrounding the identifier. 891 (or (= paren-depth 0) 892 (c-safe (goto-char (scan-lists (point) 1 paren-depth)))) 893 894 (<= (point) limit) 895 896 (progn 897 (when (looking-at c-decl-hangon-key) 898 (c-forward-keyword-clause 1)) 899 (<= (point) limit)) 900 901 ;; Search syntactically to the end of the declarator (";", 902 ;; ",", a closen paren, eob etc) or to the beginning of an 903 ;; initializer or function prototype ("=" or "\\s\("). 904 ;; Note that the open paren will match array specs in 905 ;; square brackets, and we treat them as initializers too. 906 (c-syntactic-re-search-forward 907 "[;,]\\|\\s)\\|\\'\\|\\(=\\|\\s(\\)" limit t t)) 908 909 (setq next-pos (match-beginning 0) 910 id-face (if (and (eq (char-after next-pos) ?\() 911 (let (c-last-identifier-range) 912 (save-excursion 913 (goto-char next-pos) 914 (c-at-toplevel-p)))) 915 'font-lock-function-name-face 916 'font-lock-variable-name-face) 917 got-init (and (match-beginning 1) 918 (char-after (match-beginning 1)))) 919 920 (if types 921 ;; Register and fontify the identifer as a type. 922 (let ((c-promote-possible-types t)) 923 (goto-char id-start) 924 (c-forward-type)) 925 ;; Fontify the last symbol in the identifier if it isn't fontified 926 ;; already. The check is necessary only in certain cases where this 927 ;; function is used "sloppily", e.g. in `c-simple-decl-matchers'. 928 (when (and c-last-identifier-range 929 (not (get-text-property (car c-last-identifier-range) 930 'face))) 931 (c-put-font-lock-face (car c-last-identifier-range) 932 (cdr c-last-identifier-range) 933 id-face))) 934 935 (goto-char next-pos) 936 (setq pos nil) 937 (when list 938 ;; Jump past any initializer or function prototype to see if 939 ;; there's a ',' to continue at. 940 941 (cond ((eq id-face 'font-lock-function-name-face) 942 ;; Skip a parenthesized initializer (C++) or a function 943 ;; prototype. 944 (if (c-safe (c-forward-sexp 1) t) 945 (c-forward-syntactic-ws limit) 946 (goto-char limit))) 947 948 (got-init 949 ;; Skip an initializer expression. If we're at a '=' 950 ;; then accept a brace list directly after it to cope 951 ;; with array initializers. Otherwise stop at braces 952 ;; to avoid going past full function and class blocks. 953 (and (if (and (eq got-init ?=) 954 (= (c-forward-token-2 1 nil limit) 0) 955 (looking-at "{")) 956 (c-safe (c-forward-sexp) t) 957 t) 958 ;; FIXME: Should look for c-decl-end markers here; 959 ;; we might go far into the following declarations 960 ;; in e.g. ObjC mode (see e.g. methods-4.m). 961 (c-syntactic-re-search-forward "[;,{]" limit 'move t) 962 (backward-char))) 963 964 (t (c-forward-syntactic-ws limit))) 965 966 ;; If a ',' is found we set pos to the next declarator and iterate. 967 (when (and (< (point) limit) (looking-at ",")) 968 (c-put-char-property (point) 'c-type separator-prop) 969 (forward-char) 970 (c-forward-syntactic-ws limit) 971 (setq pos (point)))))) 972 nil) 973 974(defconst c-font-lock-maybe-decl-faces 975 ;; List of faces that might be put at the start of a type when 976 ;; `c-font-lock-declarations' runs. This needs to be evaluated to 977 ;; ensure that face name aliases in Emacs are resolved. 978 (list nil 979 font-lock-type-face 980 c-reference-face-name 981 font-lock-keyword-face)) 982 983(defun c-font-lock-declarations (limit) 984 ;; This function will be called from font-lock for a region bounded by POINT 985 ;; and LIMIT, as though it were to identify a keyword for 986 ;; font-lock-keyword-face. It always returns NIL to inhibit this and 987 ;; prevent a repeat invocation. See elisp/lispref page "Search-based 988 ;; Fontification". 989 ;; 990 ;; Fontify all the declarations, casts and labels from the point to LIMIT. 991 ;; Assumes that strings and comments have been fontified already. 992 ;; 993 ;; This function might do hidden buffer changes. 994 995 ;;(message "c-font-lock-declarations search from %s to %s" (point) limit) 996 997 (save-restriction 998 (let (;; The position where `c-find-decl-spots' stopped. 999 start-pos 1000 ;; 'decl if we're in an arglist containing declarations (but 1001 ;; if `c-recognize-paren-inits' is set it might also be an 1002 ;; initializer arglist), '<> if the arglist is of angle 1003 ;; bracket type, 'arglist if it's some other arglist, or nil 1004 ;; if not in an arglist at all. 1005 context 1006 ;; The position of the next token after the closing paren of 1007 ;; the last detected cast. 1008 last-cast-end 1009 ;; The result from `c-forward-decl-or-cast-1'. 1010 decl-or-cast 1011 ;; The maximum of the end positions of all the checked type 1012 ;; decl expressions in the successfully identified 1013 ;; declarations. The position might be either before or 1014 ;; after the syntactic whitespace following the last token 1015 ;; in the type decl expression. 1016 (max-type-decl-end 0) 1017 ;; Same as `max-type-decl-*', but used when we're before 1018 ;; `token-pos'. 1019 (max-type-decl-end-before-token 0) 1020 ;; Set according to the context to direct the heuristics for 1021 ;; recognizing C++ templates. 1022 c-restricted-<>-arglists 1023 ;; Turn on recording of identifier ranges in 1024 ;; `c-forward-decl-or-cast-1' and `c-forward-label' for 1025 ;; later fontification. 1026 (c-record-type-identifiers t) 1027 label-type 1028 c-record-ref-identifiers 1029 ;; Make `c-forward-type' calls mark up template arglists if 1030 ;; it finds any. That's necessary so that we later will 1031 ;; stop inside them to fontify types there. 1032 (c-parse-and-markup-<>-arglists t) 1033 ;; The font-lock package in Emacs is known to clobber 1034 ;; `parse-sexp-lookup-properties' (when it exists). 1035 (parse-sexp-lookup-properties 1036 (cc-eval-when-compile 1037 (boundp 'parse-sexp-lookup-properties)))) 1038 1039 ;; Below we fontify a whole declaration even when it crosses the limit, 1040 ;; to avoid gaps when lazy-lock fontifies the file a screenful at a 1041 ;; time. That is however annoying during editing, e.g. the following is 1042 ;; a common situation while the first line is being written: 1043 ;; 1044 ;; my_variable 1045 ;; some_other_variable = 0; 1046 ;; 1047 ;; font-lock will put the limit at the beginning of the second line 1048 ;; here, and if we go past it we'll fontify "my_variable" as a type and 1049 ;; "some_other_variable" as an identifier, and the latter will not 1050 ;; correct itself until the second line is changed. To avoid that we 1051 ;; narrow to the limit if the region to fontify is a single line. 1052 (narrow-to-region 1053 (point-min) 1054 (if (<= limit (c-point 'bonl)) 1055 (save-excursion 1056 ;; Narrow after any operator chars following the limit though, 1057 ;; since those characters can be useful in recognizing a 1058 ;; declaration (in particular the '{' that opens a function body 1059 ;; after the header). 1060 (goto-char limit) 1061 (skip-chars-forward c-nonsymbol-chars) 1062 (point)) 1063 limit)) 1064 1065 (c-find-decl-spots 1066 limit 1067 c-decl-start-re 1068 c-font-lock-maybe-decl-faces 1069 1070 (lambda (match-pos inside-macro) 1071 (setq start-pos (point)) 1072 (when 1073 ;; The result of the form below is true when we don't recognize a 1074 ;; declaration or cast. 1075 (if (and (eq (get-text-property (point) 'face) 1076 'font-lock-keyword-face) 1077 (looking-at c-not-decl-init-keywords)) 1078 ;; Don't do anything more if we're looking at a keyword that 1079 ;; can't start a declaration. 1080 t 1081 1082 ;; Set `context'. Look for "<" for the sake of C++-style template 1083 ;; arglists. 1084 (if (memq (char-before match-pos) '(?\( ?, ?\[ ?<)) 1085 1086 ;; Find out the type of the arglist. 1087 (if (<= match-pos (point-min)) 1088 (setq context 'arglist) 1089 (let ((type (c-get-char-property (1- match-pos) 'c-type))) 1090 (cond ((eq type 'c-decl-arg-start) 1091 ;; Got a cached hit in a declaration arglist. 1092 (setq context 'decl)) 1093 ((or (eq type 'c-<>-arg-sep) 1094 (eq (char-before match-pos) ?<)) 1095 ;; Inside an angle bracket arglist. 1096 (setq context '<>)) 1097 (type 1098 ;; Got a cached hit in some other type of arglist. 1099 (setq context 'arglist)) 1100 ((if inside-macro 1101 (< match-pos max-type-decl-end-before-token) 1102 (< match-pos max-type-decl-end)) 1103 ;; The point is within the range of a previously 1104 ;; encountered type decl expression, so the arglist 1105 ;; is probably one that contains declarations. 1106 ;; However, if `c-recognize-paren-inits' is set it 1107 ;; might also be an initializer arglist. 1108 (setq context 'decl) 1109 ;; The result of this check is cached with a char 1110 ;; property on the match token, so that we can look 1111 ;; it up again when refontifying single lines in a 1112 ;; multiline declaration. 1113 (c-put-char-property (1- match-pos) 1114 'c-type 'c-decl-arg-start)) 1115 (t 1116 (setq context 'arglist))))) 1117 1118 (setq context nil)) 1119 1120 ;; If we're in a normal arglist context we don't want to 1121 ;; recognize commas in nested angle bracket arglists since 1122 ;; those commas could be part of our own arglist. 1123 (setq c-restricted-<>-arglists (and c-recognize-<>-arglists 1124 (eq context 'arglist)) 1125 1126 ;; Now analyze the construct. 1127 decl-or-cast (c-forward-decl-or-cast-1 1128 match-pos context last-cast-end)) 1129 1130 (if (not decl-or-cast) 1131 ;; False alarm. Return t to go on to the next check. 1132 t 1133 1134 (if (eq decl-or-cast 'cast) 1135 ;; Save the position after the previous cast so we can feed 1136 ;; it to `c-forward-decl-or-cast-1' in the next round. That 1137 ;; helps it discover cast chains like "(a) (b) c". 1138 (setq last-cast-end (point)) 1139 1140 ;; Set `max-type-decl-end' or `max-type-decl-end-before-token' 1141 ;; under the assumption that we're after the first type decl 1142 ;; expression in the declaration now. That's not really true; 1143 ;; we could also be after a parenthesized initializer 1144 ;; expression in C++, but this is only used as a last resort 1145 ;; to slant ambiguous expression/declarations, and overall 1146 ;; it's worth the risk to occasionally fontify an expression 1147 ;; as a declaration in an initializer expression compared to 1148 ;; getting ambiguous things in normal function prototypes 1149 ;; fontified as expressions. 1150 (if inside-macro 1151 (when (> (point) max-type-decl-end-before-token) 1152 (setq max-type-decl-end-before-token (point))) 1153 (when (> (point) max-type-decl-end) 1154 (setq max-type-decl-end (point)))) 1155 1156 ;; Back up to the type to fontify the declarator(s). 1157 (goto-char (car decl-or-cast)) 1158 1159 (let ((decl-list 1160 (if context 1161 ;; Should normally not fontify a list of 1162 ;; declarators inside an arglist, but the first 1163 ;; argument in the ';' separated list of a "for" 1164 ;; statement is an exception. 1165 (when (eq (char-before match-pos) ?\() 1166 (save-excursion 1167 (goto-char (1- match-pos)) 1168 (c-backward-syntactic-ws) 1169 (and (c-simple-skip-symbol-backward) 1170 (looking-at c-paren-stmt-key)))) 1171 t))) 1172 1173 ;; Fix the `c-decl-id-start' or `c-decl-type-start' property 1174 ;; before the first declarator if it's a list. 1175 ;; `c-font-lock-declarators' handles the rest. 1176 (when decl-list 1177 (save-excursion 1178 (c-backward-syntactic-ws) 1179 (unless (bobp) 1180 (c-put-char-property (1- (point)) 'c-type 1181 (if (cdr decl-or-cast) 1182 'c-decl-type-start 1183 'c-decl-id-start))))) 1184 1185 (c-font-lock-declarators 1186 (point-max) decl-list (cdr decl-or-cast)))) 1187 1188 ;; A cast or declaration has been successfully identified, so do 1189 ;; all the fontification of types and refs that's been recorded. 1190 (c-fontify-recorded-types-and-refs) 1191 nil)) 1192 1193 ;; It was a false alarm. Check if we're in a label (or other 1194 ;; construct with `:' except bitfield) instead. 1195 (goto-char start-pos) 1196 (when (setq label-type (c-forward-label t match-pos nil)) 1197 ;; Can't use `c-fontify-types-and-refs' here since we 1198 ;; use the label face at times. 1199 (cond ((eq label-type 'goto-target) 1200 (c-put-font-lock-face (caar c-record-ref-identifiers) 1201 (cdar c-record-ref-identifiers) 1202 c-label-face-name)) 1203 ((eq label-type 'qt-1kwd-colon) 1204 (c-put-font-lock-face (caar c-record-ref-identifiers) 1205 (cdar c-record-ref-identifiers) 1206 'font-lock-keyword-face)) 1207 ((eq label-type 'qt-2kwds-colon) 1208 (mapc 1209 (lambda (kwd) 1210 (c-put-font-lock-face (car kwd) (cdr kwd) 1211 'font-lock-keyword-face)) 1212 c-record-ref-identifiers))) 1213 (setq c-record-ref-identifiers nil) 1214 ;; `c-forward-label' has probably added a `c-decl-end' 1215 ;; marker, so return t to `c-find-decl-spots' to signal 1216 ;; that. 1217 t)))) 1218 1219 nil))) 1220 1221(c-lang-defconst c-simple-decl-matchers 1222 "Simple font lock matchers for types and declarations. These are used 1223on level 2 only and so aren't combined with `c-complex-decl-matchers'." 1224 1225 t `(;; Objective-C methods. 1226 ,@(when (c-major-mode-is 'objc-mode) 1227 `((,(c-lang-const c-opt-method-key) 1228 (,(byte-compile 1229 (lambda (limit) 1230 (let (;; The font-lock package in Emacs is known to clobber 1231 ;; `parse-sexp-lookup-properties' (when it exists). 1232 (parse-sexp-lookup-properties 1233 (cc-eval-when-compile 1234 (boundp 'parse-sexp-lookup-properties)))) 1235 (save-restriction 1236 (narrow-to-region (point-min) limit) 1237 (c-font-lock-objc-method))) 1238 nil)) 1239 (goto-char (match-end 1)))))) 1240 1241 ;; Fontify all type names and the identifiers in the 1242 ;; declarations they might start. Use eval here since 1243 ;; `c-known-type-key' gets its value from 1244 ;; `*-font-lock-extra-types' on mode init. 1245 (eval . (list ,(c-make-font-lock-search-function 1246 'c-known-type-key 1247 '(1 'font-lock-type-face t) 1248 '((c-font-lock-declarators limit t nil) 1249 (save-match-data 1250 (goto-char (match-end 1)) 1251 (c-forward-syntactic-ws)) 1252 (goto-char (match-end 1)))))) 1253 1254 ;; Fontify types preceded by `c-type-prefix-kwds' and the 1255 ;; identifiers in the declarations they might start. 1256 ,@(when (c-lang-const c-type-prefix-kwds) 1257 (let* ((prefix-re (c-make-keywords-re nil 1258 (c-lang-const c-type-prefix-kwds))) 1259 (type-match (+ 2 1260 (regexp-opt-depth prefix-re) 1261 (c-lang-const c-simple-ws-depth)))) 1262 `((,(c-make-font-lock-search-function 1263 (concat "\\<\\(" prefix-re "\\)" ; 1 1264 (c-lang-const c-simple-ws) "+" 1265 (concat "\\(" ; 2 + prefix-re + c-simple-ws 1266 (c-lang-const c-symbol-key) 1267 "\\)")) 1268 `(,type-match 1269 'font-lock-type-face t) 1270 `((c-font-lock-declarators limit t nil) 1271 (save-match-data 1272 (goto-char (match-end ,type-match)) 1273 (c-forward-syntactic-ws)) 1274 (goto-char (match-end ,type-match)))))))) 1275 1276 ;; Fontify special declarations that lacks a type. 1277 ,@(when (c-lang-const c-typeless-decl-kwds) 1278 `((,(c-make-font-lock-search-function 1279 (concat "\\<\\(" 1280 (regexp-opt (c-lang-const c-typeless-decl-kwds)) 1281 "\\)\\>") 1282 '((c-font-lock-declarators limit t nil) 1283 (save-match-data 1284 (goto-char (match-end 1)) 1285 (c-forward-syntactic-ws)) 1286 (goto-char (match-end 1))))))) 1287 1288 ;; Fontify generic colon labels in languages that support them. 1289 ,@(when (c-lang-const c-recognize-colon-labels) 1290 `(c-font-lock-labels)))) 1291 1292(c-lang-defconst c-complex-decl-matchers 1293 "Complex font lock matchers for types and declarations. Used on level 12943 and higher." 1295 1296 ;; Note: This code in this form dumps a number of funtions into the 1297 ;; resulting constant, `c-matchers-3'. At run time, font lock will call 1298 ;; each of them as a "FUNCTION" (see Elisp page "Search-based 1299 ;; Fontification"). The font lock region is delimited by POINT and the 1300 ;; single parameter, LIMIT. Each of these functions returns NIL (thus 1301 ;; inhibiting spurious font-lock-keyword-face highlighting and another 1302 ;; call). 1303 1304 t `(;; Initialize some things before the search functions below. 1305 c-font-lock-complex-decl-prepare 1306 1307 ,@(if (c-major-mode-is 'objc-mode) 1308 ;; Fontify method declarations in Objective-C, but first 1309 ;; we have to put the `c-decl-end' `c-type' property on 1310 ;; all the @-style directives that haven't been handled in 1311 ;; `c-basic-matchers-before'. 1312 `(,(c-make-font-lock-search-function 1313 (c-make-keywords-re t 1314 ;; Exclude "@class" since that directive ends with a 1315 ;; semicolon anyway. 1316 (delete "@class" 1317 (append (c-lang-const c-protection-kwds) 1318 (c-lang-const c-other-decl-kwds) 1319 nil))) 1320 '((c-put-char-property (1- (match-end 1)) 1321 'c-type 'c-decl-end))) 1322 c-font-lock-objc-methods)) 1323 1324 ;; Fontify all declarations, casts and normal labels. 1325 c-font-lock-declarations 1326 1327 ;; Fontify angle bracket arglists like templates in C++. 1328 ,@(when (c-lang-const c-recognize-<>-arglists) 1329 `(c-font-lock-<>-arglists)) 1330 1331 ;; The first two rules here mostly find occurences that 1332 ;; `c-font-lock-declarations' has found already, but not 1333 ;; declarations containing blocks in the type (see note below). 1334 ;; It's also useful to fontify these everywhere to show e.g. when 1335 ;; a type keyword is accidentally used as an identifier. 1336 1337 ;; Fontify basic types. 1338 ,(let ((re (c-make-keywords-re nil 1339 (c-lang-const c-primitive-type-kwds)))) 1340 (if (c-major-mode-is 'pike-mode) 1341 ;; No symbol is a keyword after "->" in Pike. 1342 `(,(concat "\\(\\=.?\\|[^>]\\|[^-]>\\)" 1343 "\\<\\(" re "\\)\\>") 1344 2 font-lock-type-face) 1345 `(,(concat "\\<\\(" re "\\)\\>") 1346 1 'font-lock-type-face))) 1347 1348 ;; Fontify types preceded by `c-type-prefix-kwds'. 1349 ,@(when (c-lang-const c-type-prefix-kwds) 1350 `((,(byte-compile 1351 `(lambda (limit) 1352 (c-fontify-types-and-refs 1353 ((c-promote-possible-types t) 1354 ;; The font-lock package in Emacs is known to clobber 1355 ;; `parse-sexp-lookup-properties' (when it exists). 1356 (parse-sexp-lookup-properties 1357 (cc-eval-when-compile 1358 (boundp 'parse-sexp-lookup-properties)))) 1359 (save-restriction 1360 ;; Narrow to avoid going past the limit in 1361 ;; `c-forward-type'. 1362 (narrow-to-region (point) limit) 1363 (while (re-search-forward 1364 ,(concat "\\<\\(" 1365 (c-make-keywords-re nil 1366 (c-lang-const c-type-prefix-kwds)) 1367 "\\)\\>") 1368 limit t) 1369 (unless (c-skip-comments-and-strings limit) 1370 (c-forward-syntactic-ws) 1371 ;; Handle prefix declaration specifiers. 1372 (when (looking-at c-prefix-spec-kwds-re) 1373 (c-forward-keyword-clause 1)) 1374 ,(if (c-major-mode-is 'c++-mode) 1375 `(when (and (c-forward-type) 1376 (eq (char-after) ?=)) 1377 ;; In C++ we additionally check for a "class 1378 ;; X = Y" construct which is used in 1379 ;; templates, to fontify Y as a type. 1380 (forward-char) 1381 (c-forward-syntactic-ws) 1382 (c-forward-type)) 1383 `(c-forward-type)) 1384 ))))))))) 1385 1386 ;; Fontify symbols after closing braces as declaration 1387 ;; identifiers under the assumption that they are part of 1388 ;; declarations like "class Foo { ... } foo;". It's too 1389 ;; expensive to check this accurately by skipping past the 1390 ;; brace block, so we use the heuristic that it's such a 1391 ;; declaration if the first identifier is on the same line as 1392 ;; the closing brace. `c-font-lock-declarations' will later 1393 ;; override it if it turns out to be an new declaration, but 1394 ;; it will be wrong if it's an expression (see the test 1395 ;; decls-8.cc). 1396 ,@(when (c-lang-const c-opt-block-decls-with-vars-key) 1397 `((,(c-make-font-lock-search-function 1398 (concat "}" 1399 (c-lang-const c-single-line-syntactic-ws) 1400 "\\(" ; 1 + c-single-line-syntactic-ws-depth 1401 (c-lang-const c-type-decl-prefix-key) 1402 "\\|" 1403 (c-lang-const c-symbol-key) 1404 "\\)") 1405 `((c-font-lock-declarators limit t nil) 1406 (progn 1407 (c-put-char-property (match-beginning 0) 'c-type 1408 'c-decl-id-start) 1409 (goto-char (match-beginning 1410 ,(1+ (c-lang-const 1411 c-single-line-syntactic-ws-depth))))) 1412 (goto-char (match-end 0))))))) 1413 1414 ;; Fontify the type in C++ "new" expressions. 1415 ,@(when (c-major-mode-is 'c++-mode) 1416 ;; This pattern is a probably a "(MATCHER . ANCHORED-HIGHLIGHTER)" 1417 ;; (see Elisp page "Search-based Fontification"). 1418 `(("\\<new\\>" 1419 (c-font-lock-c++-new)))) 1420 )) 1421 1422(defun c-font-lock-labels (limit) 1423 ;; Fontify all statement labels from the point to LIMIT. Assumes 1424 ;; that strings and comments have been fontified already. Nil is 1425 ;; always returned. 1426 ;; 1427 ;; Note: This function is only used on decoration level 2; this is 1428 ;; taken care of directly by the gargantuan 1429 ;; `c-font-lock-declarations' on higher levels. 1430 ;; 1431 ;; This function might do hidden buffer changes. 1432 1433 (let (continue-pos id-start 1434 ;; The font-lock package in Emacs is known to clobber 1435 ;; `parse-sexp-lookup-properties' (when it exists). 1436 (parse-sexp-lookup-properties 1437 (cc-eval-when-compile 1438 (boundp 'parse-sexp-lookup-properties)))) 1439 1440 (while (re-search-forward ":[^:]" limit t) 1441 (setq continue-pos (point)) 1442 (goto-char (match-beginning 0)) 1443 (unless (c-skip-comments-and-strings limit) 1444 1445 (c-backward-syntactic-ws) 1446 (and (setq id-start (c-on-identifier)) 1447 1448 (not (get-text-property id-start 'face)) 1449 1450 (progn 1451 (goto-char id-start) 1452 (c-backward-syntactic-ws) 1453 (or 1454 ;; Check for a char that precedes a statement. 1455 (memq (char-before) '(?\} ?\{ ?\;)) 1456 ;; Check for a preceding label. We exploit the font 1457 ;; locking made earlier by this function. 1458 (and (eq (char-before) ?:) 1459 (progn 1460 (backward-char) 1461 (c-backward-syntactic-ws) 1462 (not (bobp))) 1463 (eq (get-text-property (1- (point)) 'face) 1464 c-label-face-name)) 1465 ;; Check for a keyword that precedes a statement. 1466 (c-after-conditional))) 1467 1468 (progn 1469 ;; Got a label. 1470 (goto-char id-start) 1471 (looking-at c-symbol-key) 1472 (c-put-font-lock-face (match-beginning 0) (match-end 0) 1473 c-label-face-name))) 1474 1475 (goto-char continue-pos)))) 1476 nil) 1477 1478(c-lang-defconst c-basic-matchers-after 1479 "Font lock matchers for various things that should be fontified after 1480generic casts and declarations are fontified. Used on level 2 and 1481higher." 1482 1483 t `(;; Fontify the identifiers inside enum lists. (The enum type 1484 ;; name is handled by `c-simple-decl-matchers' or 1485 ;; `c-complex-decl-matchers' below. 1486 ,@(when (c-lang-const c-brace-id-list-kwds) 1487 `((,(c-make-font-lock-search-function 1488 (concat 1489 "\\<\\(" 1490 (c-make-keywords-re nil (c-lang-const c-brace-id-list-kwds)) 1491 "\\)\\>" 1492 ;; Disallow various common punctuation chars that can't come 1493 ;; before the '{' of the enum list, to avoid searching too far. 1494 "[^\]\[{}();,/#=]*" 1495 "{") 1496 '((c-font-lock-declarators limit t nil) 1497 (save-match-data 1498 (goto-char (match-end 0)) 1499 (c-put-char-property (1- (point)) 'c-type 1500 'c-decl-id-start) 1501 (c-forward-syntactic-ws)) 1502 (goto-char (match-end 0))))))) 1503 1504 ;; Fontify labels after goto etc. 1505 ,@(when (c-lang-const c-before-label-kwds) 1506 `(;; (Got three different interpretation levels here, 1507 ;; which makes it a bit complicated: 1) The backquote 1508 ;; stuff is expanded when compiled or loaded, 2) the 1509 ;; eval form is evaluated at font-lock setup (to 1510 ;; substitute c-label-face-name correctly), and 3) the 1511 ;; resulting structure is interpreted during 1512 ;; fontification.) 1513 (eval 1514 . ,(let* ((c-before-label-re 1515 (c-make-keywords-re nil 1516 (c-lang-const c-before-label-kwds)))) 1517 `(list 1518 ,(concat "\\<\\(" c-before-label-re "\\)\\>" 1519 "\\s *" 1520 "\\(" ; identifier-offset 1521 (c-lang-const c-symbol-key) 1522 "\\)") 1523 (list ,(+ (regexp-opt-depth c-before-label-re) 2) 1524 c-label-face-name nil t)))))) 1525 1526 ;; Fontify the clauses after various keywords. 1527 ,@(when (or (c-lang-const c-type-list-kwds) 1528 (c-lang-const c-ref-list-kwds) 1529 (c-lang-const c-colon-type-list-kwds) 1530 (c-lang-const c-paren-type-kwds)) 1531 `((,(c-make-font-lock-search-function 1532 (concat "\\<\\(" 1533 (c-make-keywords-re nil 1534 (append (c-lang-const c-type-list-kwds) 1535 (c-lang-const c-ref-list-kwds) 1536 (c-lang-const c-colon-type-list-kwds) 1537 (c-lang-const c-paren-type-kwds))) 1538 "\\)\\>") 1539 '((c-fontify-types-and-refs ((c-promote-possible-types t)) 1540 (c-forward-keyword-clause 1) 1541 (if (> (point) limit) (goto-char limit)))))))) 1542 )) 1543 1544(c-lang-defconst c-matchers-1 1545 t (c-lang-const c-cpp-matchers)) 1546 1547(c-lang-defconst c-matchers-2 1548 t (append (c-lang-const c-matchers-1) 1549 (c-lang-const c-basic-matchers-before) 1550 (c-lang-const c-simple-decl-matchers) 1551 (c-lang-const c-basic-matchers-after))) 1552 1553(c-lang-defconst c-matchers-3 1554 t (append (c-lang-const c-matchers-1) 1555 (c-lang-const c-basic-matchers-before) 1556 (c-lang-const c-complex-decl-matchers) 1557 (c-lang-const c-basic-matchers-after))) 1558 1559(defun c-compose-keywords-list (base-list) 1560 ;; Incorporate the font lock keyword lists according to 1561 ;; `c-doc-comment-style' on the given keyword list and return it. 1562 ;; This is used in the function bindings of the 1563 ;; `*-font-lock-keywords-*' symbols since we have to build the list 1564 ;; when font-lock is initialized. 1565 1566 (unless (memq c-doc-face-name c-literal-faces) 1567 (setq c-literal-faces (cons c-doc-face-name c-literal-faces))) 1568 1569 (let* ((doc-keywords 1570 (if (consp (car-safe c-doc-comment-style)) 1571 (cdr-safe (or (assq c-buffer-is-cc-mode c-doc-comment-style) 1572 (assq 'other c-doc-comment-style))) 1573 c-doc-comment-style)) 1574 (list (nconc (apply 'nconc 1575 (mapcar 1576 (lambda (doc-style) 1577 (let ((sym (intern 1578 (concat (symbol-name doc-style) 1579 "-font-lock-keywords")))) 1580 (cond ((fboundp sym) 1581 (funcall sym)) 1582 ((boundp sym) 1583 (append (eval sym) nil))))) 1584 (if (listp doc-keywords) 1585 doc-keywords 1586 (list doc-keywords)))) 1587 base-list))) 1588 1589 ;; Kludge: If `c-font-lock-complex-decl-prepare' is on the list we 1590 ;; move it first since the doc comment font lockers might add 1591 ;; `c-type' text properties, so they have to be cleared before that. 1592 (when (memq 'c-font-lock-complex-decl-prepare list) 1593 (setq list (cons 'c-font-lock-complex-decl-prepare 1594 (delq 'c-font-lock-complex-decl-prepare 1595 (append list nil))))) 1596 1597 list)) 1598 1599(defun c-override-default-keywords (def-var) 1600 ;; This is used to override the value on a `*-font-lock-keywords' 1601 ;; variable only if it's nil or has the same value as one of the 1602 ;; `*-font-lock-keywords-*' variables. Older font-lock packages 1603 ;; define a default value for `*-font-lock-keywords' which we want 1604 ;; to override, but we should otoh avoid clobbering a user setting. 1605 ;; This heuristic for that isn't perfect, but I can't think of any 1606 ;; better. /mast 1607 (when (and (boundp def-var) 1608 (memq (symbol-value def-var) 1609 (cons nil 1610 (mapcar 1611 (lambda (suffix) 1612 (let ((sym (intern (concat (symbol-name def-var) 1613 suffix)))) 1614 (and (boundp sym) (symbol-value sym)))) 1615 '("-1" "-2" "-3"))))) 1616 ;; The overriding is done by unbinding the variable so that the normal 1617 ;; defvar will install its default value later on. 1618 (makunbound def-var))) 1619 1620 1621;;; C. 1622 1623(c-override-default-keywords 'c-font-lock-keywords) 1624 1625(defconst c-font-lock-keywords-1 (c-lang-const c-matchers-1 c) 1626 "Minimal font locking for C mode. 1627Fontifies only preprocessor directives (in addition to the syntactic 1628fontification of strings and comments).") 1629 1630(defconst c-font-lock-keywords-2 (c-lang-const c-matchers-2 c) 1631 "Fast normal font locking for C mode. 1632In addition to `c-font-lock-keywords-1', this adds fontification of 1633keywords, simple types, declarations that are easy to recognize, the 1634user defined types on `c-font-lock-extra-types', and the doc comment 1635styles specified by `c-doc-comment-style'.") 1636 1637(defconst c-font-lock-keywords-3 (c-lang-const c-matchers-3 c) 1638 "Accurate normal font locking for C mode. 1639Like `c-font-lock-keywords-2' but detects declarations in a more 1640accurate way that works in most cases for arbitrary types without the 1641need for `c-font-lock-extra-types'.") 1642 1643(defvar c-font-lock-keywords c-font-lock-keywords-3 1644 "Default expressions to highlight in C mode.") 1645 1646(defun c-font-lock-keywords-2 () 1647 (c-compose-keywords-list c-font-lock-keywords-2)) 1648(defun c-font-lock-keywords-3 () 1649 (c-compose-keywords-list c-font-lock-keywords-3)) 1650(defun c-font-lock-keywords () 1651 (c-compose-keywords-list c-font-lock-keywords)) 1652 1653 1654;;; C++. 1655 1656(defun c-font-lock-c++-new (limit) 1657 ;; Assuming point is after a "new" word, check that it isn't inside 1658 ;; a string or comment, and if so try to fontify the type in the 1659 ;; allocation expression. Nil is always returned. 1660 ;; 1661 ;; As usual, C++ takes the prize in coming up with a hard to parse 1662 ;; syntax. :P 1663 ;; 1664 ;; This function might do hidden buffer changes. 1665 1666 (unless (c-skip-comments-and-strings limit) 1667 (save-excursion 1668 (catch 'false-alarm 1669 ;; A "new" keyword is followed by one to three expressions, where 1670 ;; the type is the middle one, and the only required part. 1671 (let (expr1-pos expr2-pos 1672 ;; Enable recording of identifier ranges in `c-forward-type' 1673 ;; etc for later fontification. Not using 1674 ;; `c-fontify-types-and-refs' here since the ranges should 1675 ;; be fontified selectively only when an allocation 1676 ;; expression is successfully recognized. 1677 (c-record-type-identifiers t) 1678 c-record-ref-identifiers 1679 ;; The font-lock package in Emacs is known to clobber 1680 ;; `parse-sexp-lookup-properties' (when it exists). 1681 (parse-sexp-lookup-properties 1682 (cc-eval-when-compile 1683 (boundp 'parse-sexp-lookup-properties)))) 1684 (c-forward-syntactic-ws) 1685 1686 ;; The first placement arglist is always parenthesized, if it 1687 ;; exists. 1688 (when (eq (char-after) ?\() 1689 (setq expr1-pos (1+ (point))) 1690 (condition-case nil 1691 (c-forward-sexp) 1692 (scan-error (throw 'false-alarm t))) 1693 (c-forward-syntactic-ws)) 1694 1695 ;; The second expression is either a type followed by some "*" or 1696 ;; "[...]" or similar, or a parenthesized type followed by a full 1697 ;; identifierless declarator. 1698 (setq expr2-pos (1+ (point))) 1699 (cond ((eq (char-after) ?\()) 1700 ((let ((c-promote-possible-types t)) 1701 (c-forward-type))) 1702 (t (setq expr2-pos nil))) 1703 1704 (when expr1-pos 1705 (cond 1706 ((not expr2-pos) 1707 ;; No second expression, so the first has to be a 1708 ;; parenthesized type. 1709 (goto-char expr1-pos) 1710 (let ((c-promote-possible-types t)) 1711 (c-forward-type))) 1712 1713 ((eq (char-before expr2-pos) ?\() 1714 ;; Got two parenthesized expressions, so we have to look 1715 ;; closer at them to decide which is the type. No need to 1716 ;; handle `c-record-ref-identifiers' since all references 1717 ;; has already been handled by other fontification rules. 1718 (let (expr1-res expr2-res) 1719 1720 (goto-char expr1-pos) 1721 (when (setq expr1-res (c-forward-type)) 1722 (unless (looking-at 1723 (cc-eval-when-compile 1724 (concat (c-lang-const c-symbol-start c++) 1725 "\\|[*:\)\[]"))) 1726 ;; There's something after the would-be type that 1727 ;; can't be there, so this is a placement arglist. 1728 (setq expr1-res nil))) 1729 1730 (goto-char expr2-pos) 1731 (when (setq expr2-res (c-forward-type)) 1732 (unless (looking-at 1733 (cc-eval-when-compile 1734 (concat (c-lang-const c-symbol-start c++) 1735 "\\|[*:\)\[]"))) 1736 ;; There's something after the would-be type that can't 1737 ;; be there, so this is an initialization expression. 1738 (setq expr2-res nil)) 1739 (when (and (c-go-up-list-forward) 1740 (progn (c-forward-syntactic-ws) 1741 (eq (char-after) ?\())) 1742 ;; If there's a third initialization expression 1743 ;; then the second one is the type, so demote the 1744 ;; first match. 1745 (setq expr1-res nil))) 1746 1747 ;; We fontify the most likely type, with a preference for 1748 ;; the first argument since a placement arglist is more 1749 ;; unusual than an initializer. 1750 (cond ((memq expr1-res '(t known prefix))) 1751 ((memq expr2-res '(t known prefix))) 1752 ((eq expr1-res 'found) 1753 (let ((c-promote-possible-types t)) 1754 (goto-char expr1-pos) 1755 (c-forward-type))) 1756 ((eq expr2-res 'found) 1757 (let ((c-promote-possible-types t)) 1758 (goto-char expr2-pos) 1759 (c-forward-type))) 1760 ((and (eq expr1-res 'maybe) (not expr2-res)) 1761 (let ((c-promote-possible-types t)) 1762 (goto-char expr1-pos) 1763 (c-forward-type))) 1764 ((and (not expr1-res) (eq expr2-res 'maybe)) 1765 (let ((c-promote-possible-types t)) 1766 (goto-char expr2-pos) 1767 (c-forward-type))) 1768 ;; If both type matches are 'maybe then we're 1769 ;; too uncertain to promote either of them. 1770 ))))) 1771 1772 ;; Fontify the type that now is recorded in 1773 ;; `c-record-type-identifiers', if any. 1774 (c-fontify-recorded-types-and-refs))))) 1775 nil) 1776 1777(c-override-default-keywords 'c++-font-lock-keywords) 1778 1779(defconst c++-font-lock-keywords-1 (c-lang-const c-matchers-1 c++) 1780 "Minimal font locking for C++ mode. 1781Fontifies only preprocessor directives (in addition to the syntactic 1782fontification of strings and comments).") 1783 1784(defconst c++-font-lock-keywords-2 (c-lang-const c-matchers-2 c++) 1785 "Fast normal font locking for C++ mode. 1786In addition to `c++-font-lock-keywords-1', this adds fontification of 1787keywords, simple types, declarations that are easy to recognize, the 1788user defined types on `c++-font-lock-extra-types', and the doc comment 1789styles specified by `c-doc-comment-style'.") 1790 1791(defconst c++-font-lock-keywords-3 (c-lang-const c-matchers-3 c++) 1792 "Accurate normal font locking for C++ mode. 1793Like `c++-font-lock-keywords-2' but detects declarations in a more 1794accurate way that works in most cases for arbitrary types without the 1795need for `c++-font-lock-extra-types'.") 1796 1797(defvar c++-font-lock-keywords c++-font-lock-keywords-3 1798 "Default expressions to highlight in C++ mode.") 1799 1800(defun c++-font-lock-keywords-2 () 1801 (c-compose-keywords-list c++-font-lock-keywords-2)) 1802(defun c++-font-lock-keywords-3 () 1803 (c-compose-keywords-list c++-font-lock-keywords-3)) 1804(defun c++-font-lock-keywords () 1805 (c-compose-keywords-list c++-font-lock-keywords)) 1806 1807 1808;;; Objective-C. 1809 1810(defun c-font-lock-objc-method () 1811 ;; Assuming the point is after the + or - that starts an Objective-C 1812 ;; method declaration, fontify it. This must be done before normal 1813 ;; casts, declarations and labels are fontified since they will get 1814 ;; false matches in these things. 1815 ;; 1816 ;; This function might do hidden buffer changes. 1817 1818 (c-fontify-types-and-refs 1819 ((first t) 1820 (c-promote-possible-types t)) 1821 1822 (while (and 1823 (progn 1824 (c-forward-syntactic-ws) 1825 1826 ;; An optional method type. 1827 (if (eq (char-after) ?\() 1828 (progn 1829 (forward-char) 1830 (c-forward-syntactic-ws) 1831 (c-forward-type) 1832 (prog1 (c-go-up-list-forward) 1833 (c-forward-syntactic-ws))) 1834 t)) 1835 1836 ;; The name. The first time it's the first part of 1837 ;; the function name, the rest of the time it's an 1838 ;; argument name. 1839 (looking-at c-symbol-key) 1840 (progn 1841 (goto-char (match-end 0)) 1842 (c-put-font-lock-face (match-beginning 0) 1843 (point) 1844 (if first 1845 'font-lock-function-name-face 1846 'font-lock-variable-name-face)) 1847 (c-forward-syntactic-ws) 1848 1849 ;; Another optional part of the function name. 1850 (when (looking-at c-symbol-key) 1851 (goto-char (match-end 0)) 1852 (c-put-font-lock-face (match-beginning 0) 1853 (point) 1854 'font-lock-function-name-face) 1855 (c-forward-syntactic-ws)) 1856 1857 ;; There's another argument if a colon follows. 1858 (eq (char-after) ?:))) 1859 (forward-char) 1860 (setq first nil)))) 1861 1862(defun c-font-lock-objc-methods (limit) 1863 ;; Fontify method declarations in Objective-C. Nil is always 1864 ;; returned. 1865 ;; 1866 ;; This function might do hidden buffer changes. 1867 1868 (let (;; The font-lock package in Emacs is known to clobber 1869 ;; `parse-sexp-lookup-properties' (when it exists). 1870 (parse-sexp-lookup-properties 1871 (cc-eval-when-compile 1872 (boundp 'parse-sexp-lookup-properties)))) 1873 1874 (c-find-decl-spots 1875 limit 1876 "[-+]" 1877 nil 1878 (lambda (match-pos inside-macro) 1879 (forward-char) 1880 (c-font-lock-objc-method)))) 1881 nil) 1882 1883(c-override-default-keywords 'objc-font-lock-keywords) 1884 1885(defconst objc-font-lock-keywords-1 (c-lang-const c-matchers-1 objc) 1886 "Minimal font locking for Objective-C mode. 1887Fontifies only compiler directives (in addition to the syntactic 1888fontification of strings and comments).") 1889 1890(defconst objc-font-lock-keywords-2 (c-lang-const c-matchers-2 objc) 1891 "Fast normal font locking for Objective-C mode. 1892In addition to `objc-font-lock-keywords-1', this adds fontification of 1893keywords, simple types, declarations that are easy to recognize, the 1894user defined types on `objc-font-lock-extra-types', and the doc 1895comment styles specified by `c-doc-comment-style'.") 1896 1897(defconst objc-font-lock-keywords-3 (c-lang-const c-matchers-3 objc) 1898 "Accurate normal font locking for Objective-C mode. 1899Like `objc-font-lock-keywords-2' but detects declarations in a more 1900accurate way that works in most cases for arbitrary types without the 1901need for `objc-font-lock-extra-types'.") 1902 1903(defvar objc-font-lock-keywords objc-font-lock-keywords-3 1904 "Default expressions to highlight in Objective-C mode.") 1905 1906(defun objc-font-lock-keywords-2 () 1907 (c-compose-keywords-list objc-font-lock-keywords-2)) 1908(defun objc-font-lock-keywords-3 () 1909 (c-compose-keywords-list objc-font-lock-keywords-3)) 1910(defun objc-font-lock-keywords () 1911 (c-compose-keywords-list objc-font-lock-keywords)) 1912 1913;; Kludge to override the default value that 1914;; `objc-font-lock-extra-types' might have gotten from the font-lock 1915;; package. The value replaced here isn't relevant now anyway since 1916;; those types are builtin and therefore listed directly in 1917;; `c-primitive-type-kwds'. 1918(when (equal (sort (append objc-font-lock-extra-types nil) 'string-lessp) 1919 '("BOOL" "Class" "IMP" "SEL")) 1920 (setq objc-font-lock-extra-types 1921 (cc-eval-when-compile (list (concat "[" c-upper "]\\sw*"))))) 1922 1923 1924;;; Java. 1925 1926(c-override-default-keywords 'java-font-lock-keywords) 1927 1928(defconst java-font-lock-keywords-1 (c-lang-const c-matchers-1 java) 1929 "Minimal font locking for Java mode. 1930Fontifies nothing except the syntactic fontification of strings and 1931comments.") 1932 1933(defconst java-font-lock-keywords-2 (c-lang-const c-matchers-2 java) 1934 "Fast normal font locking for Java mode. 1935In addition to `java-font-lock-keywords-1', this adds fontification of 1936keywords, simple types, declarations that are easy to recognize, the 1937user defined types on `java-font-lock-extra-types', and the doc 1938comment styles specified by `c-doc-comment-style'.") 1939 1940(defconst java-font-lock-keywords-3 (c-lang-const c-matchers-3 java) 1941 "Accurate normal font locking for Java mode. 1942Like `java-font-lock-keywords-2' but detects declarations in a more 1943accurate way that works in most cases for arbitrary types without the 1944need for `java-font-lock-extra-types'.") 1945 1946(defvar java-font-lock-keywords java-font-lock-keywords-3 1947 "Default expressions to highlight in Java mode.") 1948 1949(defun java-font-lock-keywords-2 () 1950 (c-compose-keywords-list java-font-lock-keywords-2)) 1951(defun java-font-lock-keywords-3 () 1952 (c-compose-keywords-list java-font-lock-keywords-3)) 1953(defun java-font-lock-keywords () 1954 (c-compose-keywords-list java-font-lock-keywords)) 1955 1956 1957;;; CORBA IDL. 1958 1959(c-override-default-keywords 'idl-font-lock-keywords) 1960 1961(defconst idl-font-lock-keywords-1 (c-lang-const c-matchers-1 idl) 1962 "Minimal font locking for CORBA IDL mode. 1963Fontifies nothing except the syntactic fontification of strings and 1964comments.") 1965 1966(defconst idl-font-lock-keywords-2 (c-lang-const c-matchers-2 idl) 1967 "Fast normal font locking for CORBA IDL mode. 1968In addition to `idl-font-lock-keywords-1', this adds fontification of 1969keywords, simple types, declarations that are easy to recognize, the 1970user defined types on `idl-font-lock-extra-types', and the doc comment 1971styles specified by `c-doc-comment-style'.") 1972 1973(defconst idl-font-lock-keywords-3 (c-lang-const c-matchers-3 idl) 1974 "Accurate normal font locking for CORBA IDL mode. 1975Like `idl-font-lock-keywords-2' but detects declarations in a more 1976accurate way that works in most cases for arbitrary types without the 1977need for `idl-font-lock-extra-types'.") 1978 1979(defvar idl-font-lock-keywords idl-font-lock-keywords-3 1980 "Default expressions to highlight in CORBA IDL mode.") 1981 1982(defun idl-font-lock-keywords-2 () 1983 (c-compose-keywords-list idl-font-lock-keywords-2)) 1984(defun idl-font-lock-keywords-3 () 1985 (c-compose-keywords-list idl-font-lock-keywords-3)) 1986(defun idl-font-lock-keywords () 1987 (c-compose-keywords-list idl-font-lock-keywords)) 1988 1989 1990;;; Pike. 1991 1992(c-override-default-keywords 'pike-font-lock-keywords) 1993 1994(defconst pike-font-lock-keywords-1 (c-lang-const c-matchers-1 pike) 1995 "Minimal font locking for Pike mode. 1996Fontifies only preprocessor directives (in addition to the syntactic 1997fontification of strings and comments).") 1998 1999(defconst pike-font-lock-keywords-2 (c-lang-const c-matchers-2 pike) 2000 "Fast normal font locking for Pike mode. 2001In addition to `pike-font-lock-keywords-1', this adds fontification of 2002keywords, simple types, declarations that are easy to recognize, the 2003user defined types on `pike-font-lock-extra-types', and the doc 2004comment styles specified by `c-doc-comment-style'.") 2005 2006(defconst pike-font-lock-keywords-3 (c-lang-const c-matchers-3 pike) 2007 "Accurate normal font locking for Pike mode. 2008Like `pike-font-lock-keywords-2' but detects declarations in a more 2009accurate way that works in most cases for arbitrary types without the 2010need for `pike-font-lock-extra-types'.") 2011 2012(defvar pike-font-lock-keywords pike-font-lock-keywords-3 2013 "Default expressions to highlight in Pike mode.") 2014 2015(defun pike-font-lock-keywords-2 () 2016 (c-compose-keywords-list pike-font-lock-keywords-2)) 2017(defun pike-font-lock-keywords-3 () 2018 (c-compose-keywords-list pike-font-lock-keywords-3)) 2019(defun pike-font-lock-keywords () 2020 (c-compose-keywords-list pike-font-lock-keywords)) 2021 2022 2023;;; Doc comments. 2024 2025(defun c-font-lock-doc-comments (prefix limit keywords) 2026 ;; Fontify the comments between the point and LIMIT whose start 2027 ;; matches PREFIX with `c-doc-face-name'. Assumes comments have been 2028 ;; fontified with `font-lock-comment-face' already. nil is always 2029 ;; returned. 2030 ;; 2031 ;; After the fontification of a matching comment, fontification 2032 ;; according to KEYWORDS is applied inside it. It's a list like 2033 ;; `font-lock-keywords' except that anchored matches and eval 2034 ;; clauses aren't supported and that some abbreviated forms can't be 2035 ;; used. The buffer is narrowed to the comment while KEYWORDS is 2036 ;; applied; leading comment starters are included but trailing 2037 ;; comment enders for block comment are not. 2038 ;; 2039 ;; Note that faces added through KEYWORDS should never replace the 2040 ;; existing `c-doc-face-name' face since the existence of that face 2041 ;; is used as a flag in other code to skip comments. 2042 ;; 2043 ;; This function might do hidden buffer changes. 2044 2045 (let (comment-beg region-beg) 2046 (if (eq (get-text-property (point) 'face) 2047 'font-lock-comment-face) 2048 ;; Handle the case when the fontified region starts inside a 2049 ;; comment. 2050 (let ((range (c-literal-limits))) 2051 (setq region-beg (point)) 2052 (when range 2053 (goto-char (car range))) 2054 (when (looking-at prefix) 2055 (setq comment-beg (point))))) 2056 2057 (while (or 2058 comment-beg 2059 2060 ;; Search for the prefix until a match is found at the start 2061 ;; of a comment. 2062 (while (when (re-search-forward prefix limit t) 2063 (setq comment-beg (match-beginning 0)) 2064 (or (not (c-got-face-at comment-beg 2065 c-literal-faces)) 2066 (and (/= comment-beg (point-min)) 2067 (c-got-face-at (1- comment-beg) 2068 c-literal-faces)))) 2069 (setq comment-beg nil)) 2070 (setq region-beg comment-beg)) 2071 2072 (if (eq (elt (parse-partial-sexp comment-beg (+ comment-beg 2)) 7) t) 2073 ;; Collect a sequence of doc style line comments. 2074 (progn 2075 (goto-char comment-beg) 2076 (while (and (progn 2077 (c-forward-single-comment) 2078 (skip-syntax-forward " ") 2079 (< (point) limit)) 2080 (looking-at prefix)))) 2081 (goto-char comment-beg) 2082 (c-forward-single-comment)) 2083 (if (> (point) limit) (goto-char limit)) 2084 (setq comment-beg nil) 2085 2086 (let ((region-end (point)) 2087 (keylist keywords) keyword matcher highlights) 2088 (c-put-font-lock-face region-beg region-end c-doc-face-name) 2089 (save-restriction 2090 ;; Narrow to the doc comment. Among other things, this 2091 ;; helps by making "^" match at the start of the comment. 2092 ;; Do not include a trailing block comment ender, though. 2093 (and (> region-end (1+ region-beg)) 2094 (progn (goto-char region-end) 2095 (backward-char 2) 2096 (looking-at "\\*/")) 2097 (setq region-end (point))) 2098 (narrow-to-region region-beg region-end) 2099 2100 (while keylist 2101 (setq keyword (car keylist) 2102 keylist (cdr keylist) 2103 matcher (car keyword)) 2104 (goto-char region-beg) 2105 (while (if (stringp matcher) 2106 (re-search-forward matcher region-end t) 2107 (funcall matcher region-end)) 2108 (setq highlights (cdr keyword)) 2109 (if (consp (car highlights)) 2110 (while highlights 2111 (font-lock-apply-highlight (car highlights)) 2112 (setq highlights (cdr highlights))) 2113 (font-lock-apply-highlight highlights)))) 2114 2115 (goto-char region-end))))) 2116 nil) 2117(put 'c-font-lock-doc-comments 'lisp-indent-function 2) 2118 2119(defun c-find-invalid-doc-markup (regexp limit) 2120 ;; Used to fontify invalid markup in doc comments after the correct 2121 ;; ones have been fontified: Find the first occurence of REGEXP 2122 ;; between the point and LIMIT that only is fontified with 2123 ;; `c-doc-face-name'. If a match is found then submatch 0 surrounds 2124 ;; the first char and t is returned, otherwise nil is returned. 2125 ;; 2126 ;; This function might do hidden buffer changes. 2127 (let (start) 2128 (while (if (re-search-forward regexp limit t) 2129 (not (eq (get-text-property 2130 (setq start (match-beginning 0)) 'face) 2131 c-doc-face-name)) 2132 (setq start nil))) 2133 (when start 2134 (store-match-data (list (copy-marker start) 2135 (copy-marker (1+ start)))) 2136 t))) 2137 2138;; GtkDoc patterns contributed by Masatake YAMATO <jet@gyve.org>. 2139 2140(defconst gtkdoc-font-lock-doc-comments 2141 (let ((symbol "[a-zA-Z0-9_]+") 2142 (header "^ \\* ")) 2143 `((,(concat header "\\(" symbol "\\):[ \t]*$") 2144 1 ,c-doc-markup-face-name prepend nil) 2145 (,(concat symbol "()") 2146 0 ,c-doc-markup-face-name prepend nil) 2147 (,(concat header "\\(" "@" symbol "\\):") 2148 1 ,c-doc-markup-face-name prepend nil) 2149 (,(concat "[#%]" symbol) 2150 0 ,c-doc-markup-face-name prepend nil)) 2151 )) 2152 2153(defconst gtkdoc-font-lock-doc-protection 2154 `(("< \\(public\\|private\\|protected\\) >" 2155 1 ,c-doc-markup-face-name prepend nil))) 2156 2157(defconst gtkdoc-font-lock-keywords 2158 `((,(lambda (limit) 2159 (c-font-lock-doc-comments "/\\*\\*$" limit 2160 gtkdoc-font-lock-doc-comments) 2161 (c-font-lock-doc-comments "/\\*< " limit 2162 gtkdoc-font-lock-doc-protection) 2163 )))) 2164 2165;; Javadoc. 2166 2167(defconst javadoc-font-lock-doc-comments 2168 `(("{@[a-z]+[^}\n\r]*}" ; "{@foo ...}" markup. 2169 0 ,c-doc-markup-face-name prepend nil) 2170 ("^\\(/\\*\\)?\\(\\s \\|\\*\\)*\\(@[a-z]+\\)" ; "@foo ..." markup. 2171 3 ,c-doc-markup-face-name prepend nil) 2172 (,(concat "</?\\sw" ; HTML tags. 2173 "\\(" 2174 (concat "\\sw\\|\\s \\|[=\n\r*.:]\\|" 2175 "\"[^\"]*\"\\|'[^']*'") 2176 "\\)*>") 2177 0 ,c-doc-markup-face-name prepend nil) 2178 ("&\\(\\sw\\|[.:]\\)+;" ; HTML entities. 2179 0 ,c-doc-markup-face-name prepend nil) 2180 ;; Fontify remaining markup characters as invalid. Note 2181 ;; that the Javadoc spec is hazy about when "@" is 2182 ;; allowed in non-markup use. 2183 (,(lambda (limit) 2184 (c-find-invalid-doc-markup "[<>&]\\|{@" limit)) 2185 0 'font-lock-warning-face prepend nil))) 2186 2187(defconst javadoc-font-lock-keywords 2188 `((,(lambda (limit) 2189 (c-font-lock-doc-comments "/\\*\\*" limit 2190 javadoc-font-lock-doc-comments))))) 2191 2192;; Pike autodoc. 2193 2194(defconst autodoc-decl-keywords 2195 ;; Adorned regexp matching the keywords that introduce declarations 2196 ;; in Pike Autodoc. 2197 (cc-eval-when-compile 2198 (c-make-keywords-re t '("@decl" "@elem" "@index" "@member") 'pike-mode))) 2199 2200(defconst autodoc-decl-type-keywords 2201 ;; Adorned regexp matching the keywords that are followed by a type. 2202 (cc-eval-when-compile 2203 (c-make-keywords-re t '("@elem" "@member") 'pike-mode))) 2204 2205(defun autodoc-font-lock-line-markup (limit) 2206 ;; Fontify all line oriented keywords between the point and LIMIT. 2207 ;; Nil is always returned. 2208 ;; 2209 ;; This function might do hidden buffer changes. 2210 2211 (let ((line-re (concat "^\\(\\(/\\*!\\|\\s *\\(" 2212 c-current-comment-prefix 2213 "\\)\\)\\s *\\)@[A-Za-z_-]+\\(\\s \\|$\\)")) 2214 (markup-faces (list c-doc-markup-face-name c-doc-face-name))) 2215 2216 (while (re-search-forward line-re limit t) 2217 (goto-char (match-end 1)) 2218 2219 (if (looking-at autodoc-decl-keywords) 2220 (let* ((kwd-pos (point)) 2221 (start (match-end 1)) 2222 (pos start) 2223 end) 2224 2225 (c-put-font-lock-face (point) pos markup-faces) 2226 2227 ;; Put a declaration end mark at the markup keyword and 2228 ;; remove the faces from the rest of the line so that it 2229 ;; gets refontified as a declaration later on by 2230 ;; `c-font-lock-declarations'. 2231 (c-put-char-property (1- pos) 'c-type 'c-decl-end) 2232 (goto-char pos) 2233 (while (progn 2234 (end-of-line) 2235 (setq end (point)) 2236 (and (eq (char-before) ?@) 2237 (not (eobp)) 2238 (progn (forward-char) 2239 (skip-syntax-forward " ") 2240 (looking-at c-current-comment-prefix)))) 2241 (goto-char (match-end 0)) 2242 (c-remove-font-lock-face pos (1- end)) 2243 (c-put-font-lock-face (1- end) end markup-faces) 2244 (setq pos (point))) 2245 2246 ;; Include the final newline in the removed area. This 2247 ;; has no visual effect but it avoids some tricky special 2248 ;; cases in the testsuite wrt the differences in string 2249 ;; fontification in Emacs vs XEmacs. 2250 (c-remove-font-lock-face pos (min (1+ (point)) (point-max))) 2251 2252 ;; Must handle string literals explicitly inside the declaration. 2253 (goto-char start) 2254 (while (re-search-forward 2255 "\"\\([^\\\"]\\|\\\\.\\)*\"\\|'\\([^\\']\\|\\\\.\\)*'" 2256 end 'move) 2257 (c-put-font-lock-string-face (match-beginning 0) 2258 (point))) 2259 2260 ;; Fontify types after keywords that always are followed 2261 ;; by them. 2262 (goto-char kwd-pos) 2263 (when (looking-at autodoc-decl-type-keywords) 2264 (c-fontify-types-and-refs ((c-promote-possible-types t)) 2265 (goto-char start) 2266 (c-forward-syntactic-ws) 2267 (c-forward-type)))) 2268 2269 ;; Mark each whole line as markup, as long as the logical line 2270 ;; continues. 2271 (while (progn 2272 (c-put-font-lock-face (point) 2273 (progn (end-of-line) (point)) 2274 markup-faces) 2275 (and (eq (char-before) ?@) 2276 (not (eobp)) 2277 (progn (forward-char) 2278 (skip-syntax-forward " ") 2279 (looking-at c-current-comment-prefix)))) 2280 (goto-char (match-end 0)))))) 2281 2282 nil) 2283 2284(defconst autodoc-font-lock-doc-comments 2285 `(("@\\(\\w+{\\|\\[\\([^\]@\n\r]\\|@@\\)*\\]\\|[@}]\\|$\\)" 2286 ;; In-text markup. 2287 0 ,c-doc-markup-face-name prepend nil) 2288 (autodoc-font-lock-line-markup) 2289 ;; Fontify remaining markup characters as invalid. 2290 (,(lambda (limit) 2291 (c-find-invalid-doc-markup "@" limit)) 2292 0 'font-lock-warning-face prepend nil) 2293 )) 2294 2295(defun autodoc-font-lock-keywords () 2296 ;; Note that we depend on that `c-current-comment-prefix' has got 2297 ;; its proper value here. 2298 ;; 2299 ;; This function might do hidden buffer changes. 2300 2301 ;; The `c-type' text property with `c-decl-end' is used to mark the 2302 ;; end of the `autodoc-decl-keywords' occurrences to fontify the 2303 ;; following declarations. 2304 (setq c-type-decl-end-used t) 2305 2306 `((,(lambda (limit) 2307 (c-font-lock-doc-comments "/[*/]!" limit 2308 autodoc-font-lock-doc-comments))))) 2309 2310 2311;; 2006-07-10: awk-font-lock-keywords has been moved back to cc-awk.el. 2312(cc-provide 'cc-fonts) 2313 2314;;; arch-tag: 2f65f405-735f-4da5-8d4b-b957844c5203 2315;;; cc-fonts.el ends here 2316