Replace `iff' in doc-strings and comments.
[bpt/emacs.git] / lisp / font-lock.el
index be97ce4..6bc5fd8 100644 (file)
@@ -1,7 +1,7 @@
 ;;; font-lock.el --- Electric font lock mode
 
 ;; Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-;;   2000, 2001, 2002, 2003, 2004 2005 Free Software Foundation, Inc.
+;;   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007  Free Software Foundation, Inc.
 
 ;; Author: jwz, then rms, then sm
 ;; Maintainer: FSF
@@ -11,7 +11,7 @@
 
 ;; GNU Emacs is free software; you can redistribute it and/or modify
 ;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
+;; the Free Software Foundation; either version 3, or (at your option)
 ;; any later version.
 
 ;; GNU Emacs is distributed in the hope that it will be useful,
 ;;
 ;;  (add-hook 'foo-mode-hook
 ;;   (lambda ()
-;;     (make-local-variable 'font-lock-defaults)
-;;     (setq font-lock-defaults '(foo-font-lock-keywords t))))
+;;     (set (make-local-variable 'font-lock-defaults)
+;;          '(foo-font-lock-keywords t))))
 
 ;;; Adding Font Lock support for modes:
 
 ;;
 ;; and within `bar-mode' there could be:
 ;;
-;;  (make-local-variable 'font-lock-defaults)
-;;  (setq font-lock-defaults '(bar-font-lock-keywords nil t))
+;;  (set (make-local-variable 'font-lock-defaults)
+;;       '(bar-font-lock-keywords nil t))
 \f
 ;; What is fontification for?  You might say, "It's to make my code look nice."
 ;; I think it should be for adding information in the form of cues.  These cues
@@ -281,12 +281,6 @@ If a number, only buffers greater than this size have fontification messages."
                 (other :tag "always" t)
                 (integer :tag "size"))
   :group 'font-lock)
-
-(defcustom font-lock-lines-before 0
-  "*Number of lines before the changed text to include in refontification."
-  :type 'integer
-  :group 'font-lock
-  :version "22.1")
 \f
 
 ;; Originally these variable values were face names such as `bold' etc.
@@ -361,7 +355,7 @@ Each element in a user-level keywords list should have one of these forms:
 
 where MATCHER can be either the regexp to search for, or the function name to
 call to make the search (called with one argument, the limit of the search;
-it should return non-nil, move point, and set `match-data' appropriately iff
+it should return non-nil, move point, and set `match-data' appropriately if
 it succeeds; like `re-search-forward' would).
 MATCHER regexps can be generated via the function `regexp-opt'.
 
@@ -474,6 +468,7 @@ they are added at the end.
 
 This is normally set via `font-lock-add-keywords' and
 `font-lock-remove-keywords'.")
+(put 'font-lock-keywords-alist 'risky-local-variable t)
 
 (defvar font-lock-removed-keywords-alist nil
   "Alist of `font-lock-keywords' elements to be removed for major modes.
@@ -703,6 +698,14 @@ see the variables `c-font-lock-extra-types', `c++-font-lock-extra-types',
         ;; contain the new keywords.
         (font-lock-update-removed-keyword-alist mode keywords how))
        (t
+         (when (and font-lock-mode
+                    (not (or font-lock-keywords font-lock-defaults)))
+           ;; The major mode has not set any keywords, so when we enabled
+           ;; font-lock-mode it only enabled the font-core.el part, not the
+           ;; font-lock-mode-internal.  Try again.
+           (font-lock-mode -1)
+           (set (make-local-variable 'font-lock-defaults) '(nil t))
+           (font-lock-mode 1))
         ;; Otherwise set or add the keywords now.
         ;; This is a no-op if it has been done already in this buffer
         ;; for the correct major mode.
@@ -723,8 +726,8 @@ see the variables `c-font-lock-extra-types', `c++-font-lock-extra-types',
                                          (append keywords old)))))
           ;; If the keywords were compiled before, compile them again.
           (if was-compiled
-              (set (make-local-variable 'font-lock-keywords)
-                   (font-lock-compile-keywords font-lock-keywords t)))))))
+              (setq font-lock-keywords
+                     (font-lock-compile-keywords font-lock-keywords)))))))
 
 (defun font-lock-update-removed-keyword-alist (mode keywords how)
   "Update `font-lock-removed-keywords-alist' when adding new KEYWORDS to MODE."
@@ -830,8 +833,8 @@ happens, so the major mode can be corrected."
 
           ;; If the keywords were compiled before, compile them again.
           (if was-compiled
-              (set (make-local-variable 'font-lock-keywords)
-                   (font-lock-compile-keywords font-lock-keywords t)))))))
+              (setq font-lock-keywords
+                     (font-lock-compile-keywords font-lock-keywords)))))))
 \f
 ;;; Font Lock Support mode.
 
@@ -899,7 +902,11 @@ The value of this variable is used when Font Lock mode is turned on."
           (set (make-local-variable 'font-lock-fontified) t)
           ;; Use jit-lock.
           (jit-lock-register 'font-lock-fontify-region
-                             (not font-lock-keywords-only))))))
+                             (not font-lock-keywords-only))
+           ;; Tell jit-lock how we extend the region to refontify.
+           (add-hook 'jit-lock-after-change-extend-region-functions
+                     'font-lock-extend-jit-lock-region-after-change
+                     nil t)))))
 
 (defun font-lock-turn-off-thing-lock ()
   (cond ((and (boundp 'fast-lock-mode) fast-lock-mode)
@@ -977,9 +984,25 @@ The value of this variable is used when Font Lock mode is turned on."
 ;; directives correctly and cleanly.  (It is the same problem as fontifying
 ;; multi-line strings and comments; regexps are not appropriate for the job.)
 
+(defvar font-lock-extend-after-change-region-function nil
+  "A function that determines the region to refontify after a change.
+
+This variable is either nil, or is a function that determines the
+region to refontify after a change.
+It is usually set by the major mode via `font-lock-defaults'.
+Font-lock calls this function after each buffer change.
+
+The function is given three parameters, the standard BEG, END, and OLD-LEN
+from `after-change-functions'.  It should return either a cons of the beginning
+and end buffer positions \(in that order) of the region to refontify, or nil
+\(which directs the caller to fontify a default region).
+This function should preserve the match-data.
+The region it returns may start or end in the middle of a line.")
+
 (defun font-lock-fontify-buffer ()
   "Fontify the current buffer the way the function `font-lock-mode' would."
   (interactive)
+  (font-lock-set-defaults)
   (let ((font-lock-verbose (or font-lock-verbose (interactive-p))))
     (funcall font-lock-fontify-buffer-function)))
 
@@ -987,6 +1010,7 @@ The value of this variable is used when Font Lock mode is turned on."
   (funcall font-lock-unfontify-buffer-function))
 
 (defun font-lock-fontify-region (beg end &optional loudly)
+  (font-lock-set-defaults)
   (funcall font-lock-fontify-region-function beg end loudly))
 
 (defun font-lock-unfontify-region (beg end)
@@ -1000,9 +1024,6 @@ The value of this variable is used when Font Lock mode is turned on."
     (with-temp-message
        (when verbose
          (format "Fontifying %s..." (buffer-name)))
-      ;; Make sure we have the right `font-lock-keywords' etc.
-      (unless font-lock-mode
-       (font-lock-set-defaults))
       ;; Make sure we fontify etc. in the whole buffer.
       (save-restriction
        (widen)
@@ -1028,6 +1049,62 @@ The value of this variable is used when Font Lock mode is turned on."
 Useful for things like RMAIL and Info where the whole buffer is not
 a very meaningful entity to highlight.")
 
+
+(defvar font-lock-beg) (defvar font-lock-end)
+(defvar font-lock-extend-region-functions
+  '(font-lock-extend-region-wholelines
+    ;; This use of font-lock-multiline property is unreliable but is just
+    ;; a handy heuristic: in case you don't have a function that does
+    ;; /identification/ of multiline elements, you may still occasionally
+    ;; discover them by accident (or you may /identify/ them but not in all
+    ;; cases), in which case the font-lock-multiline property can help make
+    ;; sure you will properly *re*identify them during refontification.
+    font-lock-extend-region-multiline)
+  "Special hook run just before proceeding to fontify a region.
+This is used to allow major modes to help font-lock find safe buffer positions
+as beginning and end of the fontified region.  Its most common use is to solve
+the problem of /identification/ of multiline elements by providing a function
+that tries to find such elements and move the boundaries such that they do
+not fall in the middle of one.
+Each function is called with no argument; it is expected to adjust the
+dynamically bound variables `font-lock-beg' and `font-lock-end'; and return
+non-nil if it did make such an adjustment.
+These functions are run in turn repeatedly until they all return nil.
+Put first the functions more likely to cause a change and cheaper to compute.")
+;; Mark it as a special hook which doesn't use any global setting
+;; (i.e. doesn't obey the element t in the buffer-local value).
+(make-variable-buffer-local 'font-lock-extend-region-functions)
+
+(defun font-lock-extend-region-multiline ()
+  "Move fontification boundaries away from any `font-lock-multiline' property."
+  (let ((changed nil))
+    (when (and (> font-lock-beg (point-min))
+               (get-text-property (1- font-lock-beg) 'font-lock-multiline))
+      (setq changed t)
+      (setq font-lock-beg (or (previous-single-property-change
+                               font-lock-beg 'font-lock-multiline)
+                              (point-min))))
+    ;;
+    (when (get-text-property font-lock-end 'font-lock-multiline)
+      (setq changed t)
+      (setq font-lock-end (or (text-property-any font-lock-end (point-max)
+                                                 'font-lock-multiline nil)
+                              (point-max))))
+    changed))
+
+(defun font-lock-extend-region-wholelines ()
+  "Move fontification boundaries to beginning of lines."
+  (let ((changed nil))
+    (goto-char font-lock-beg)
+    (unless (bolp)
+      (setq changed t font-lock-beg (line-beginning-position)))
+    (goto-char font-lock-end)
+    (unless (bolp)
+      (unless (eq font-lock-end
+                  (setq font-lock-end (line-beginning-position 2)))
+        (setq changed t)))
+    changed))
+
 (defun font-lock-default-fontify-region (beg end loudly)
   (save-buffer-state
       ((parse-sexp-lookup-properties
@@ -1039,24 +1116,21 @@ a very meaningful entity to highlight.")
          ;; Use the fontification syntax table, if any.
          (when font-lock-syntax-table
            (set-syntax-table font-lock-syntax-table))
-          (goto-char beg)
-          (setq beg (line-beginning-position (- 1 font-lock-lines-before)))
-         ;; check to see if we should expand the beg/end area for
-         ;; proper multiline matches
-         (when (and (> beg (point-min))
-                    (get-text-property (1- beg) 'font-lock-multiline))
-           ;; We are just after or in a multiline match.
-           (setq beg (or (previous-single-property-change
-                          beg 'font-lock-multiline)
-                         (point-min)))
-           (goto-char beg)
-           (setq beg (line-beginning-position)))
-          (setq end (or (text-property-any end (point-max)
-                                           'font-lock-multiline nil)
-                        (point-max)))
-         (goto-char end)
-         ;; Round up to a whole line.
-          (unless (bolp) (setq end (line-beginning-position 2)))
+          ;; Extend the region to fontify so that it starts and ends at
+          ;; safe places.
+          (let ((funs font-lock-extend-region-functions)
+                (font-lock-beg beg)
+                (font-lock-end end))
+            (while funs
+              (setq funs (if (or (not (funcall (car funs)))
+                                 (eq funs font-lock-extend-region-functions))
+                             (cdr funs)
+                           ;; If there's been a change, we should go through
+                           ;; the list again since this new position may
+                           ;; warrant a different answer from one of the fun
+                           ;; we've already seen.
+                           font-lock-extend-region-functions)))
+            (setq beg font-lock-beg end font-lock-end))
          ;; Now do the fontification.
          (font-lock-unfontify-region beg end)
          (when font-lock-syntactic-keywords
@@ -1090,14 +1164,89 @@ what properties to clear before refontifying a region.")
 
 ;; Called when any modification is made to buffer text.
 (defun font-lock-after-change-function (beg end old-len)
-  (let ((inhibit-point-motion-hooks t)
-       (inhibit-quit t))
-    (save-excursion
+  (save-excursion
+    (let ((inhibit-point-motion-hooks t)
+          (inhibit-quit t)
+          (region (if font-lock-extend-after-change-region-function
+                      (funcall font-lock-extend-after-change-region-function
+                               beg end old-len))))
       (save-match-data
-       ;; Rescan between start of lines enclosing the region.
-       (font-lock-fontify-region
-        (progn (goto-char beg) (forward-line 0) (point))
-        (progn (goto-char end) (forward-line 1) (point)))))))
+       (if region
+           ;; Fontify the region the major mode has specified.
+           (setq beg (car region) end (cdr region))
+         ;; Fontify the whole lines which enclose the region.
+          ;; Actually, this is not needed because
+          ;; font-lock-default-fontify-region already rounds up to a whole
+          ;; number of lines.
+         ;; (setq beg (progn (goto-char beg) (line-beginning-position))
+         ;;       end (progn (goto-char end) (line-beginning-position 2)))
+         (unless (eq end (point-max))
+           ;; Rounding up to a whole number of lines should include the
+           ;; line right after `end'.  Typical case: the first char of
+           ;; the line was deleted.  Or a \n was inserted in the middle
+           ;; of a line.
+           (setq end (1+ end))))
+       (font-lock-fontify-region beg end)))))
+
+(defvar jit-lock-start) (defvar jit-lock-end)
+(defun font-lock-extend-jit-lock-region-after-change (beg end old-len)
+  "Function meant for `jit-lock-after-change-extend-region-functions'.
+This function does 2 things:
+- extend the region so that it not only includes the part that was modified
+  but also the surrounding text whose highlighting may change as a consequence.
+- anticipate (part of) the region extension that will happen later in
+  `font-lock-default-fontify-region', in order to avoid the need for
+  double-redisplay in `jit-lock-fontify-now'."
+  (save-excursion
+    ;; First extend the region as font-lock-after-change-function would.
+    (let ((region (if font-lock-extend-after-change-region-function
+                      (funcall font-lock-extend-after-change-region-function
+                               beg end old-len))))
+      (if region
+          (setq beg (min jit-lock-start (car region))
+                end (max jit-lock-end (cdr region))))
+      ;; Then extend the region obeying font-lock-multiline properties,
+      ;; indicating which part of the buffer needs to be refontified.
+      ;; !!! This is the *main* user of font-lock-multiline property !!!
+      ;; font-lock-after-change-function could/should also do that, but it
+      ;; doesn't need to because font-lock-default-fontify-region does
+      ;; it anyway.  Here OTOH we have no guarantee that
+      ;; font-lock-default-fontify-region will be executed on this region
+      ;; any time soon.
+      ;; Note: contrary to font-lock-default-fontify-region, we do not do
+      ;; any loop here because we are not looking for a safe spot: we just
+      ;; mark the text whose appearance may need to change as a result of
+      ;; the buffer modification.
+      (when (and (> beg (point-min))
+                 (get-text-property (1- beg) 'font-lock-multiline))
+        (setq beg (or (previous-single-property-change
+                       beg 'font-lock-multiline)
+                      (point-min))))
+      (when (< end (point-max))
+        (setq end
+              (if (get-text-property end 'font-lock-multiline)
+                  (or (text-property-any end (point-max)
+                                         'font-lock-multiline nil)
+                      (point-max))
+                ;; Rounding up to a whole number of lines should include the
+                ;; line right after `end'.  Typical case: the first char of
+                ;; the line was deleted.  Or a \n was inserted in the middle
+                ;; of a line.
+                (1+ end))))
+      ;; Finally, pre-enlarge the region to a whole number of lines, to try
+      ;; and anticipate what font-lock-default-fontify-region will do, so as to
+      ;; avoid double-redisplay.
+      ;; We could just run `font-lock-extend-region-functions', but since
+      ;; the only purpose is to avoid the double-redisplay, we prefer to
+      ;; do here only the part that is cheap and most likely to be useful.
+      (when (memq 'font-lock-extend-region-wholelines
+                  font-lock-extend-region-functions)
+        (goto-char beg)
+        (setq jit-lock-start (min jit-lock-start (line-beginning-position)))
+        (goto-char end)
+        (setq jit-lock-end
+              (max jit-lock-end
+                   (if (bolp) (point) (line-beginning-position 2))))))))
 
 (defun font-lock-fontify-block (&optional arg)
   "Fontify some lines the way `font-lock-fontify-buffer' would.
@@ -1290,7 +1439,8 @@ START should be at the beginning of a line."
   ;; If `font-lock-syntactic-keywords' is not compiled, compile it.
   (unless (eq (car font-lock-syntactic-keywords) t)
     (setq font-lock-syntactic-keywords (font-lock-compile-keywords
-                                       font-lock-syntactic-keywords)))
+                                       font-lock-syntactic-keywords
+                                       t)))
   ;; Get down to business.
   (let ((case-fold-search font-lock-keywords-case-fold-search)
        (keywords (cddr font-lock-syntactic-keywords))
@@ -1446,7 +1596,7 @@ START should be at the beginning of a line.
 LOUDLY, if non-nil, allows progress-meter bar."
   (unless (eq (car font-lock-keywords) t)
     (setq font-lock-keywords
-         (font-lock-compile-keywords font-lock-keywords t)))
+         (font-lock-compile-keywords font-lock-keywords)))
   (let ((case-fold-search font-lock-keywords-case-fold-search)
        (keywords (cddr font-lock-keywords))
        (bufname (buffer-name)) (count 0)
@@ -1502,21 +1652,30 @@ LOUDLY, if non-nil, allows progress-meter bar."
 \f
 ;; Various functions.
 
-(defun font-lock-compile-keywords (keywords &optional regexp)
+(defun font-lock-compile-keywords (keywords &optional syntactic-keywords)
   "Compile KEYWORDS into the form (t KEYWORDS COMPILED...)
 Here each COMPILED is of the form (MATCHER HIGHLIGHT ...) as shown in the
 `font-lock-keywords' doc string.
-If REGEXP is non-nil, it means these keywords are used for
-`font-lock-keywords' rather than for `font-lock-syntactic-keywords'."
+If SYNTACTIC-KEYWORDS is non-nil, it means these keywords are used for
+`font-lock-syntactic-keywords' rather than for `font-lock-keywords'."
+  (if (not font-lock-set-defaults)
+      ;; This should never happen.  But some external packages sometimes
+      ;; call font-lock in unexpected and incorrect ways.  It's important to
+      ;; stop processing at this point, otherwise we may end up changing the
+      ;; global value of font-lock-keywords and break highlighting in many
+      ;; other buffers.
+      (error "Font-lock trying to use keywords before setting them up"))
   (if (eq (car-safe keywords) t)
       keywords
     (setq keywords
          (cons t (cons keywords
                        (mapcar 'font-lock-compile-keyword keywords))))
-    (if (and regexp
-            (eq (or syntax-begin-function
-                    font-lock-beginning-of-syntax-function)
-                'beginning-of-defun)
+    (if (and (not syntactic-keywords)
+            (let ((beg-function
+                   (or font-lock-beginning-of-syntax-function
+                       syntax-begin-function)))
+              (or (eq beg-function 'beginning-of-defun)
+                  (get beg-function 'font-lock-syntax-paren-check)))
             (not beginning-of-defun-function))
        ;; Try to detect when a string or comment contains something that
        ;; looks like a defun and would thus confuse font-lock.
@@ -1574,9 +1733,9 @@ A LEVEL of nil is equal to a LEVEL of 0, a LEVEL of t is equal to
   (cond ((not (and (listp keywords) (symbolp (car keywords))))
         keywords)
        ((numberp level)
-        (or (nth level keywords) (car (reverse keywords))))
+        (or (nth level keywords) (car (last keywords))))
        ((eq level t)
-        (car (reverse keywords)))
+        (car (last keywords)))
        (t
         (car keywords))))
 
@@ -1587,7 +1746,7 @@ A LEVEL of nil is equal to a LEVEL of 0, a LEVEL of t is equal to
   "Set fontification defaults appropriately for this mode.
 Sets various variables using `font-lock-defaults' (or, if nil, using
 `font-lock-defaults-alist') and `font-lock-maximum-decoration'."
-  ;; Set fontification defaults iff not previously set for correct major mode.
+  ;; Set fontification defaults if not previously set for correct major mode.
   (unless (and font-lock-set-defaults
               (eq font-lock-mode-major-mode major-mode))
     (setq font-lock-mode-major-mode major-mode)
@@ -1642,8 +1801,8 @@ Sets various variables using `font-lock-defaults' (or, if nil, using
        (font-lock-remove-keywords nil removed-keywords))
       ;; Now compile the keywords.
       (unless (eq (car font-lock-keywords) t)
-       (set (make-local-variable 'font-lock-keywords)
-            (font-lock-compile-keywords font-lock-keywords t))))))
+       (setq font-lock-keywords
+              (font-lock-compile-keywords font-lock-keywords))))))
 \f
 ;;; Colour etc. support.
 
@@ -1957,6 +2116,78 @@ This function could be MATCHER in a MATCH-ANCHORED `font-lock-keywords' item."
              (goto-char (or (scan-sexps (point) 1) (point-max))))
            (goto-char (match-end 2)))
        (error t)))))
+
+;; C preprocessor(cpp) is used outside of C, C++ and Objective-C source file.
+;; e.g. assembler code and GNU linker script in Linux kernel.
+;; `cpp-font-lock-keywords' is handy for modes for the files.
+;;
+;; Here we cannot use `regexp-opt' because because regex-opt is not preloaded
+;; while font-lock.el is preloaded to emacs. So values pre-calculated with 
+;; regexp-opt are used here.
+
+;; `cpp-font-lock-keywords-source-directives' is calculated from:
+;;
+;;         (regexp-opt
+;;          '("define"  "elif" "else" "endif" "error" "file" "if" "ifdef"
+;;            "ifndef" "import" "include" "line" "pragma" "undef" "warning"))
+;;
+(defconst cpp-font-lock-keywords-source-directives
+  "define\\|e\\(?:l\\(?:if\\|se\\)\\|ndif\\|rror\\)\\|file\\|i\\(?:f\\(?:n?def\\)?\\|mport\\|nclude\\)\\|line\\|pragma\\|undef\\|warning"
+  "Regular expressoin used in `cpp-font-lock-keywords'.")
+
+;; `cpp-font-lock-keywords-source-depth' is calculated from:
+;;
+;;          (regexp-opt-depth (regexp-opt
+;;                    '("define"  "elif" "else" "endif" "error" "file" "if" "ifdef"
+;;                      "ifndef" "import" "include" "line" "pragma" "undef" "warning")))
+;;
+(defconst cpp-font-lock-keywords-source-depth 0
+  "An integer representing regular expression depth of `cpp-font-lock-keywords-source-directives'.
+Used in `cpp-font-lock-keywords'.")
+
+(defconst cpp-font-lock-keywords
+  (let* ((directives cpp-font-lock-keywords-source-directives)
+        (directives-depth cpp-font-lock-keywords-source-depth))
+    (list
+     ;;
+     ;; Fontify error directives.
+     '("^#[ \t]*\\(?:error\\|warning\\)[ \t]+\\(.+\\)" 1 font-lock-warning-face prepend)
+     ;;
+     ;; Fontify filenames in #include <...> preprocessor directives as strings.
+     '("^#[ \t]*\\(?:import\\|include\\)[ \t]*\\(<[^>\"\n]*>?\\)"
+       1 font-lock-string-face prepend)
+     ;;
+     ;; Fontify function macro names.
+     '("^#[ \t]*define[ \t]+\\([[:alpha:]_][[:alnum:]_$]*\\)(" 
+       (1 font-lock-function-name-face prepend)
+       ;;
+       ;; Macro arguments.
+       ((lambda (limit)
+         (re-search-forward
+          "\\(?:\\([[:alpha:]_][[:alnum:]_]*\\)[,]?\\)" 
+          (or (save-excursion (re-search-forward ")" limit t)) 
+              limit)
+          t)) 
+       nil nil (1 font-lock-variable-name-face prepend)))
+     ;;
+     ;; Fontify symbol names in #elif or #if ... defined preprocessor directives.
+     '("^#[ \t]*\\(?:elif\\|if\\)\\>"
+       ("\\<\\(defined\\)\\>[ \t]*(?\\([[:alpha:]_][[:alnum:]_]*\\)?" nil nil
+       (1 font-lock-builtin-face prepend) (2 font-lock-variable-name-face prepend t)))
+     ;;
+     ;; Fontify otherwise as symbol names, and the preprocessor directive names.
+     (list
+      (concat "^\\(#[ \t]*\\(?:" directives
+             "\\)\\)\\>[ \t!]*\\([[:alpha:]_][[:alnum:]_]*\\)?")
+      '(1 font-lock-preprocessor-face prepend)
+      (list (+ 2 directives-depth)
+           'font-lock-variable-name-face nil t))))
+    "Font lock keyords for C preprocessor directives.
+`c-mode', `c++-mode' and `objc-mode' have their own 
+font lock keyords for C preprocessor directives. This definition is for the
+other modes in which C preprocessor directives are used. e.g. `asm-mode' and
+`ld-script-mode'.")
+
 \f
 ;; Lisp.
 
@@ -1965,14 +2196,14 @@ This function could be MATCHER in a MATCH-ANCHORED `font-lock-keywords' item."
     `(;; Definitions.
       (,(concat "(\\(def\\("
                ;; Function declarations.
-               "\\(advice\\|varalias\\|alias\\|generic\\|macro\\*?\\|method\\|"
+               "\\(advice\\|alias\\|generic\\|macro\\*?\\|method\\|"
                "setf\\|subst\\*?\\|un\\*?\\|"
                "ine-\\(condition\\|"
-               "\\(?:derived\\|\\(?:global-\\)?minor\\|generic\\)-mode\\|"
+               "\\(?:derived\\|\\(?:global\\(?:ized\\)?-\\)?minor\\|generic\\)-mode\\|"
                "method-combination\\|setf-expander\\|skeleton\\|widget\\|"
                "function\\|\\(compiler\\|modify\\|symbol\\)-macro\\)\\)\\|"
                ;; Variable declarations.
-               "\\(const\\(ant\\)?\\|custom\\|face\\|parameter\\|var\\)\\|"
+               "\\(const\\(ant\\)?\\|custom\\|varalias\\|face\\|parameter\\|var\\)\\|"
                ;; Structure declarations.
                "\\(class\\|group\\|theme\\|package\\|struct\\|type\\)"
                "\\)\\)\\>"
@@ -2004,7 +2235,7 @@ This function could be MATCHER in a MATCH-ANCHORED `font-lock-keywords' item."
                 "condition-case" "track-mouse"
                 "eval-after-load" "eval-and-compile" "eval-when-compile"
                 "eval-when" "eval-at-startup" "eval-next-after-load"
-                "with-category-table"
+                "with-case-table" "with-category-table"
                 "with-current-buffer" "with-electric-help"
                 "with-local-quit" "with-no-warnings"
                 "with-output-to-string" "with-output-to-temp-buffer"
@@ -2042,13 +2273,13 @@ This function could be MATCHER in a MATCH-ANCHORED `font-lock-keywords' item."
        ;; Erroneous structures.
        ("(\\(abort\\|assert\\|warn\\|check-type\\|cerror\\|error\\|signal\\)\\>" 1 font-lock-warning-face)
        ;; Words inside \\[] tend to be for `substitute-command-keys'.
-       ("\\\\\\\\\\[\\(\\sw+\\)]" 1 font-lock-constant-face prepend)
+       ("\\\\\\\\\\[\\(\\sw+\\)\\]" 1 font-lock-constant-face prepend)
        ;; Words inside `' tend to be symbol names.
        ("`\\(\\sw\\sw+\\)'" 1 font-lock-constant-face prepend)
        ;; Constant values.
        ("\\<:\\sw+\\>" 0 font-lock-builtin-face)
        ;; ELisp and CLisp `&' keywords as types.
-       ("\\&\\sw+\\>" . font-lock-type-face)
+       ("\\<\\&\\sw+\\>" . font-lock-type-face)
        ;; ELisp regexp grouping constructs
        ((lambda (bound)
           (catch 'found