]> code.delx.au - gnu-emacs/commitdiff
Update CC Mode to release 5.31.
authorAlan Mackenzie <acm@muc.de>
Fri, 2 Dec 2005 12:30:36 +0000 (12:30 +0000)
committerAlan Mackenzie <acm@muc.de>
Fri, 2 Dec 2005 12:30:36 +0000 (12:30 +0000)
14 files changed:
lisp/progmodes/cc-align.el
lisp/progmodes/cc-awk.el
lisp/progmodes/cc-bytecomp.el
lisp/progmodes/cc-cmds.el
lisp/progmodes/cc-compat.el
lisp/progmodes/cc-defs.el
lisp/progmodes/cc-engine.el
lisp/progmodes/cc-fonts.el
lisp/progmodes/cc-langs.el
lisp/progmodes/cc-menus.el
lisp/progmodes/cc-mode.el
lisp/progmodes/cc-styles.el
lisp/progmodes/cc-subword.el [new file with mode: 0644]
lisp/progmodes/cc-vars.el

index 36b4fd2545cd0da43c4f7704bdf5f55ba37711c7..83b4d8387d4e25444e8993a85aab7ae461a0cf8c 100644 (file)
 (cc-require 'cc-engine)
 
 \f
-;; Standard indentation line-ups
-
-;; Calling convention:
-;;
-;; The single argument is a cons cell containing the syntactic symbol
-;; in the car, and the relpos (a.k.a. anchor position) in the cdr.
-;; The cdr may be nil for syntactic symbols which doesn't have an
-;; associated relpos.
+;; Standard line-up functions
 ;;
-;; Some syntactic symbols provide more information, usually more
-;; interesting positions.  The complete list for the syntactic element
-;; (beginning with the symbol itself) is available in
-;; `c-syntactic-element'.
+;; See the section "Custom Indentation Functions" in the manual for
+;; details on the calling convention.
 
 (defun c-lineup-topmost-intro-cont (langelem)
   "Line up declaration continuation lines zero or one indentation step.
@@ -91,17 +82,67 @@ statement-cont.)
 Works with: topmost-intro-cont."
   (save-excursion
     (beginning-of-line)
-    (c-backward-syntactic-ws (cdr langelem))
-    (if (memq (char-before) '(?} ?,))
+    (c-backward-syntactic-ws (c-langelem-pos langelem))
+    (if (and (memq (char-before) '(?} ?,))
+            (not (and c-overloadable-operators-regexp
+                      (c-after-special-operator-id))))
        c-basic-offset)))
 
+(defun c-block-in-arglist-dwim (arglist-start)
+  ;; This function implements the DWIM to avoid far indentation of
+  ;; brace block constructs in arguments in `c-lineup-arglist' etc.
+  ;; Return non-nil if a brace block construct is detected within the
+  ;; arglist starting at ARGLIST-START.
+
+  (or
+   ;; Check if the syntactic context contains any of the symbols for
+   ;; in-expression constructs.  This can both save the work that we
+   ;; have to do below, and it also detect the brace list constructs
+   ;; that `c-looking-at-inexpr-block' currently misses (they are
+   ;; recognized by `c-inside-bracelist-p' instead).
+   (assq 'inexpr-class c-syntactic-context)
+   (assq 'inexpr-statement c-syntactic-context)
+   (assq 'inlambda c-syntactic-context)
+
+   (save-restriction
+     ;; Search for open braces from the arglist start to the end of the
+     ;; line.
+     (narrow-to-region arglist-start (c-point 'eol arglist-start))
+
+     (goto-char arglist-start)
+     (while (and (c-syntactic-re-search-forward "{" nil t)
+                (progn
+                  (backward-char)
+                  (or
+                   ;; Ignore starts of special brace lists.
+                   (and c-special-brace-lists
+                        (save-restriction
+                          (widen)
+                          (c-looking-at-special-brace-list)))
+                   ;; Ignore complete blocks.
+                   (c-safe (c-forward-sexp) t))))
+       (forward-char))
+
+     (looking-at "{"))
+
+   (let (containing-sexp)
+     (goto-char arglist-start)
+     ;; `c-syntactic-eol' always matches somewhere on the line.
+     (re-search-forward c-syntactic-eol)
+     (goto-char (match-beginning 0))
+     (c-forward-syntactic-ws)
+     (setq containing-sexp (c-most-enclosing-brace (c-parse-state)))
+     (c-looking-at-inexpr-block
+      (c-safe-position (or containing-sexp (point)) c-state-cache)
+      containing-sexp))))
+
 (defun c-lineup-arglist (langelem)
   "Line up the current argument line under the first argument.
 
-As a special case, if an argument on the same line as the open
-parenthesis starts with a brace block opener, the indentation is
-`c-basic-offset' only.  This is intended as a \"DWIM\" measure in
-cases like macros that contains statement blocks, e.g:
+As a special case, if the indented line is inside a brace block
+construct, the indentation is `c-basic-offset' only.  This is intended
+as a \"DWIM\" measure in cases like macros that contains statement
+blocks, e.g:
 
 A_VERY_LONG_MACRO_NAME ({
         some (code, with + long, lines * in[it]);
@@ -115,38 +156,25 @@ indent such cases this way.
 
 Works with: arglist-cont-nonempty, arglist-close."
   (save-excursion
-    (goto-char (1+ (elt c-syntactic-element 2)))
-
-    ;; Don't stop in the middle of a special brace list opener
-    ;; like "({".
-    (when c-special-brace-lists
-      (let ((special-list (c-looking-at-special-brace-list)))
-       (when (and special-list (< (car (car special-list)) (point)))
-         (goto-char (+ (car (car special-list)) 2)))))
-
-    (let ((savepos (point))
-         (eol (c-point 'eol)))
-
-      ;; Find out if an argument on the same line starts with an
-      ;; unclosed open brace paren.  Note similar code in
-      ;; `c-lineup-close-paren' and
-      ;; `c-lineup-arglist-close-under-paren'.
-      (if (and (c-syntactic-re-search-forward "{" eol t t)
-              (looking-at c-syntactic-eol)
-              (progn (backward-char)
-                     (not (c-looking-at-special-brace-list)))
-              (progn (c-backward-syntactic-ws)
-                     (or (= (point) savepos)
-                         (eq (char-before) ?,))))
-         c-basic-offset
+    (let ((indent-pos (point)))
+
+      (if (c-block-in-arglist-dwim (c-langelem-2nd-pos c-syntactic-element))
+         c-basic-offset                ; DWIM case.
 
        ;; Normal case.  Indent to the token after the arglist open paren.
-       (goto-char savepos)
-       (c-forward-syntactic-ws)
-       (when (< (point) eol)
-         (goto-char savepos)
-         (skip-chars-forward " \t"))
-       (vector (current-column))))))
+       (goto-char (c-langelem-2nd-pos c-syntactic-element))
+       (if (and c-special-brace-lists
+                (c-looking-at-special-brace-list))
+           ;; Skip a special brace list opener like "({".
+           (progn (c-forward-token-2)
+                  (forward-char))
+         (forward-char))
+       (let ((arglist-content-start (point)))
+         (c-forward-syntactic-ws)
+         (when (< (point) indent-pos)
+           (goto-char arglist-content-start)
+           (skip-chars-forward " \t"))
+         (vector (current-column)))))))
 
 ;; Contributed by Kevin Ryde <user42@zip.com.au>.
 (defun c-lineup-argcont (elem)
@@ -172,7 +200,7 @@ Works with: arglist-cont, arglist-cont-nonempty."
       ;; isn't, go back to the last position in it.  We do this by
       ;; stepping back over open parens until we get to the open paren
       ;; of our argument list.
-      (let ((open-paren (elt c-syntactic-element 2))
+      (let ((open-paren (c-langelem-2nd-pos c-syntactic-element))
            (paren-state (c-parse-state)))
        (while (not (eq (car paren-state) open-paren))
          (unless (consp (car paren-state)) ;; ignore matched braces
@@ -233,51 +261,36 @@ corresponding open paren, but can also be used with arglist-cont and
 arglist-cont-nonempty to line up all lines inside a parenthesis under
 the open paren.
 
-As a special case, if a brace block is opened at the same line as the
-open parenthesis of the argument list, the indentation is
+As a special case, if a brace block construct starts at the same line
+as the open parenthesis of the argument list, the indentation is
 `c-basic-offset' only.  See `c-lineup-arglist' for further discussion
 of this \"DWIM\" measure.
 
 Works with: Almost all symbols, but are typically most useful on
 arglist-close, brace-list-close, arglist-cont and arglist-cont-nonempty."
   (save-excursion
-    (let (special-list paren-start savepos)
-      (if (memq (car langelem) '(arglist-cont-nonempty arglist-close))
-         (goto-char (elt c-syntactic-element 2))
-       (beginning-of-line)
-       (c-go-up-list-backward))
-
-      (if (and c-special-brace-lists
-              (setq special-list (c-looking-at-special-brace-list)))
-         ;; Don't stop in the middle of a special brace list opener
-         ;; like "({".
-         (progn
-           (setq paren-start (car (car special-list)))
-           (goto-char (+ paren-start 2)))
-       (setq paren-start (point))
-       (forward-char 1))
-
-      (setq savepos (point))
-      ;; Find out if an argument on the same line starts with an
-      ;; unclosed open brace paren.  Note similar code in
-      ;; `c-lineup-arglist' and `c-lineup-close-paren'.
-      (if (and (c-syntactic-re-search-forward "{" (c-point 'eol) t t)
-              (looking-at c-syntactic-eol)
-              (progn (backward-char)
-                     (not (c-looking-at-special-brace-list)))
-              (progn (c-backward-syntactic-ws)
-                     (or (= (point) savepos)
-                         (eq (char-before) ?,))))
-         c-basic-offset
-
-       ;; Normal case.  Indent to the arglist open paren.
-       (goto-char paren-start)
+    (if (memq (c-langelem-sym langelem)
+             '(arglist-cont-nonempty arglist-close))
+       (goto-char (c-langelem-2nd-pos c-syntactic-element))
+      (beginning-of-line)
+      (c-go-up-list-backward))
+
+    (if (save-excursion (c-block-in-arglist-dwim (point)))
+       c-basic-offset                  ; DWIM case.
+
+      ;; Normal case.  Indent to the arglist open paren.
+      (let (special-list)
+       (if (and c-special-brace-lists
+                (setq special-list (c-looking-at-special-brace-list)))
+           ;; Cope if we're in the middle of a special brace list
+           ;; opener like "({".
+           (goto-char (car (car special-list))))
        (vector (current-column))))))
 
 (defun c-lineup-arglist-operators (langelem)
   "Line up lines starting with an infix operator under the open paren.
 Return nil on lines that don't start with an operator, to leave those
-cases to other lineup functions.  Example:
+cases to other line-up functions.  Example:
 
 if (  x < 10
    || at_limit (x,       <- c-lineup-arglist-operators
@@ -285,7 +298,7 @@ if (  x < 10
    )
 
 Since this function doesn't do anything for lines without an infix
-operator you typically want to use it together with some other lineup
+operator you typically want to use it together with some other line-up
 settings, e.g. as follows \(the arglist-close setting is just a
 suggestion to get a consistent style):
 
@@ -310,52 +323,48 @@ main (int,              main (
       char **               int, char **
      )           <->    )                 <- c-lineup-close-paren
 
-As a special case, if a brace block is opened at the same line as the
-open parenthesis of the argument list, the indentation is
+As a special case, if a brace block construct starts at the same line
+as the open parenthesis of the argument list, the indentation is
 `c-basic-offset' instead of the open paren column.  See
 `c-lineup-arglist' for further discussion of this \"DWIM\" measure.
 
 Works with: All *-close symbols."
   (save-excursion
-    (beginning-of-line)
-    (c-go-up-list-backward)
+    (if (memq (c-langelem-sym langelem)
+             '(arglist-cont-nonempty arglist-close))
+       (goto-char (c-langelem-2nd-pos c-syntactic-element))
+      (beginning-of-line)
+      (c-go-up-list-backward))
 
-    (let ((spec (c-looking-at-special-brace-list)) savepos argstart)
-      (if spec (goto-char (car (car spec))))
-      (setq savepos (point))
-      (forward-char 1)
-      (when spec
-       (c-forward-syntactic-ws)
-       (forward-char 1))
+    (let (special-list arglist-start)
+      (if (and c-special-brace-lists
+              (setq special-list (c-looking-at-special-brace-list)))
+         ;; Cope if we're in the middle of a special brace list
+         ;; opener like "({".
+         (progn
+           (goto-char (setq arglist-start (car (car special-list))))
+           (c-forward-token-2)
+           (forward-char))
+       (setq arglist-start (point))
+       (forward-char))
 
-      (if (looking-at c-syntactic-eol)
-         ;; The arglist is "empty".
-         0
-
-       ;; Find out if an argument on the same line starts with an
-       ;; unclosed open brace paren.  Note similar code in
-       ;; `c-lineup-arglist' and
-       ;; `c-lineup-arglist-close-under-paren'.
-       (setq argstart (point))
-       (if (and (c-syntactic-re-search-forward "{" (c-point 'eol) t t)
-                (looking-at c-syntactic-eol)
-                (progn (backward-char)
-                       (not (c-looking-at-special-brace-list)))
-                (progn (c-backward-syntactic-ws)
-                       (or (= (point) argstart)
-                           (eq (char-before) ?,))))
-           c-basic-offset
-
-         ;; Normal case.  Indent to the arglist open paren.
-         (goto-char savepos)
-         (vector (current-column)))))))
+      (cond ((looking-at c-syntactic-eol)
+            0)                         ; The arglist is "empty".
+
+           ((c-block-in-arglist-dwim (point))
+            c-basic-offset)            ; DWIM case.
+
+           (t
+            ;; Normal case.  Indent to the arglist open paren.
+            (goto-char arglist-start)
+            (vector (current-column)))))))
 
 (defun c-lineup-streamop (langelem)
   "Line up C++ stream operators under each other.
 
 Works with: stream-op."
   (save-excursion
-    (goto-char (cdr langelem))
+    (goto-char (c-langelem-pos langelem))
     (re-search-forward "<<\\|>>" (c-point 'eol) 'move)
     (goto-char (match-beginning 0))
     (vector (current-column))))
@@ -382,7 +391,8 @@ Works with: inher-cont, member-init-cont."
     (let* ((eol (c-point 'eol))
           (here (point))
           (char-after-ip (char-after)))
-      (if (cdr langelem) (goto-char (cdr langelem)))
+      (if (c-langelem-pos langelem)
+         (goto-char (c-langelem-pos langelem)))
 
       ;; This kludge is necessary to support both inher-cont and
       ;; member-init-cont, since they have different anchor positions.
@@ -415,7 +425,7 @@ class Foo             class Foo
 
 Works with: inher-cont."
   (save-excursion
-    (goto-char (cdr langelem))
+    (goto-char (c-langelem-pos langelem))
     (forward-word 1)
     (if (looking-at "[ \t]*$")
        c-basic-offset
@@ -439,7 +449,7 @@ Works with: func-decl-cont."
   (save-excursion
     (let* ((lim (1- (c-point 'bol)))
           (throws (catch 'done
-                    (goto-char (cdr langelem))
+                    (goto-char (c-langelem-pos langelem))
                     (while (zerop (c-forward-token-2 1 t lim))
                       (if (looking-at "throws\\>[^_]")
                           (throw 'done t))))))
@@ -537,13 +547,13 @@ Works with: The `c' syntactic symbol."
            ;; matches comment-start-skip, and choose whichever is
            ;; longest.
            (max (save-excursion
-                  (goto-char (1+ (cdr langelem)))
+                  (goto-char (1+ (c-langelem-pos langelem)))
                   (if (and (match-string 0)
                            (looking-at (regexp-quote (match-string 0))))
                       (- (match-end 0) (match-beginning 0))
                     0))
                 (save-excursion
-                  (goto-char (cdr langelem))
+                  (goto-char (c-langelem-pos langelem))
                   (looking-at comment-start-skip)
                   (- (or (match-end 1)
                          (save-excursion
@@ -557,14 +567,20 @@ Works with: The `c' syntactic symbol."
          ;; a nonempty comment prefix.  Treat it as free form text
          ;; and don't change the indentation.
          (vector (current-column))
-       (forward-line -1)
-       (back-to-indentation)
-       (if (>= (cdr langelem) (point))
-           ;; On the second line in the comment.
+       ;; Go back to the previous non-blank line, if any.
+       (while
+           (progn
+             (forward-line -1)
+             (back-to-indentation)
+             (and (> (point) (c-langelem-pos langelem))
+                  (looking-at "[ \t]*$"))))
+       ;; Is the starting line the first continuation line with content?
+       (if (>= (c-langelem-pos langelem) (point))
            (if (zerop prefixlen)
                ;; No nonempty comment prefix. Align after comment
                ;; starter.
                (progn
+                 (looking-at comment-start-skip)
                  (goto-char (match-end 0))
                  ;; The following should not be necessary, since
                  ;; comment-start-skip should match everything (i.e.
@@ -580,27 +596,27 @@ Works with: The `c' syntactic symbol."
              ;; Javadoc style comments.
              (if (> starterlen prefixlen)
                  (progn
-                   (goto-char (cdr langelem))
+                   (goto-char (c-langelem-pos langelem))
                    (vector (1+ (current-column))))
-               (goto-char (+ (cdr langelem) starterlen 1))
+               (goto-char (+ (c-langelem-pos langelem) starterlen 1))
                (vector (- (current-column) prefixlen))))
-         ;; Not on the second line in the comment.  If the previous
-         ;; line has a nonempty comment prefix, align with it.
-         ;; Otherwise, align with the previous nonempty line, but
-         ;; align the comment ender with the starter.
+         ;; We didn't start on the first non-blank continuation line.  If the
+         ;; previous line has a nonempty comment prefix, align with it.
+         ;; Otherwise, align with the previous nonempty line, but align the
+         ;; comment ender with the starter.
          (when (or (not (looking-at c-current-comment-prefix))
                    (eq (match-beginning 0) (match-end 0)))
            (goto-char here)
            (back-to-indentation)
            (if (looking-at (concat "\\(" c-current-comment-prefix "\\)\\*/"))
-               (goto-char (cdr langelem))
+               (goto-char (c-langelem-pos langelem))
              (while (and (zerop (forward-line -1))
                          (looking-at "^[ \t]*$")))
              (back-to-indentation)
-             (if (< (point) (cdr langelem))
+             (if (< (point) (c-langelem-pos langelem))
                  ;; Align with the comment starter rather than
                  ;; with the code before it.
-                 (goto-char (cdr langelem)))))
+                 (goto-char (c-langelem-pos langelem)))))
          (vector (current-column)))))))
 
 (defun c-lineup-comment (langelem)
@@ -665,38 +681,39 @@ If there is no statement after the opening brace to align with, nil is
 returned.  This makes the function usable in list expressions.
 
 Works with: The `statement' syntactic symbol."
-  (if (eq (char-after (cdr langelem)) ?{)
+  (if (eq (char-after (c-langelem-pos langelem)) ?{)
       (save-excursion
-       (if (cdr langelem) (goto-char (cdr langelem)))
+       (if (c-langelem-pos langelem)
+           (goto-char (c-langelem-pos langelem)))
        (forward-char 1)
        (skip-chars-forward " \t")
        (unless (eolp)
          (vector (current-column))))))
 
-(defun c-lineup-math (langelem)
-  "Line up the current line after the equal sign on the first line in
-the statement.  If there isn't any, indent with `c-basic-offset'.  If
-the current line contains an equal sign too, try to align it with the
-first one.
+(defun c-lineup-assignments (langelem)
+  "Line up the current line after the assignment operator on the first
+line in the statement.  If there isn't any, return nil to allow
+stacking with other line-up functions.  If the current line contains
+an assignment operator too, try to align it with the first one.
 
 Works with: topmost-intro-cont, statement-cont, arglist-cont,
 arglist-cont-nonempty."
   (let (startpos endpos equalp)
 
-    (if (eq (car langelem) 'arglist-cont-nonempty)
+    (if (eq (c-langelem-sym langelem) 'arglist-cont-nonempty)
        ;; If it's an arglist-cont-nonempty then we're only interested
        ;; in equal signs outside it.  We don't search for a "=" on
        ;; the current line since that'd have a different nesting
        ;; compared to the one we should align with.
        (save-excursion
          (save-restriction
-           (setq endpos (nth 2 c-syntactic-element))
-           (narrow-to-region (cdr langelem) endpos)
+           (setq endpos (c-langelem-2nd-pos c-syntactic-element))
+           (narrow-to-region (c-langelem-pos langelem) endpos)
            (if (setq startpos (c-up-list-backward endpos))
                (setq startpos (1+ startpos))
-             (setq startpos (cdr langelem)))))
+             (setq startpos (c-langelem-pos langelem)))))
 
-      (setq startpos (cdr langelem)
+      (setq startpos (c-langelem-pos langelem)
            endpos (point))
 
       ;; Find a syntactically relevant and unnested "=" token on the
@@ -727,7 +744,7 @@ arglist-cont-nonempty."
                (eolp)))
          ;; There's no equal sign on the line, or there is one but
          ;; nothing follows it.
-         c-basic-offset
+         nil
 
        ;; calculate indentation column after equals and ws, unless
        ;; our line contains an equals sign
@@ -739,6 +756,17 @@ arglist-cont-nonempty."
        (vector (- (current-column) equalp)))
       )))
 
+(defun c-lineup-math (langelem)
+  "Like `c-lineup-assignments' but indent with `c-basic-offset' if no
+assignment operator was found on the first line.  I.e. this function
+is the same as specifying a list (c-lineup-assignments +).  It's
+provided for compatibility with old configurations.
+
+Works with: topmost-intro-cont, statement-cont, arglist-cont,
+arglist-cont-nonempty."
+  (or (c-lineup-assignments langelem)
+      c-basic-offset))
+
 (defun c-lineup-cascaded-calls (langelem)
   "Line up \"cascaded calls\" under each other.
 If the line begins with \"->\" or \".\" and the preceding line ends
@@ -755,8 +783,8 @@ expressions.
 Works with: topmost-intro-cont, statement-cont, arglist-cont,
 arglist-cont-nonempty."
 
-  (if (and (eq (car langelem) 'arglist-cont-nonempty)
-          (not (eq (nth 2 c-syntactic-element)
+  (if (and (eq (c-langelem-sym langelem) 'arglist-cont-nonempty)
+          (not (eq (c-langelem-2nd-pos c-syntactic-element)
                    (c-most-enclosing-brace (c-parse-state)))))
       ;; The innermost open paren is not our one, so don't do
       ;; anything.  This can occur for arglist-cont-nonempty with
@@ -767,7 +795,7 @@ arglist-cont-nonempty."
       (back-to-indentation)
       (let ((operator (and (looking-at "->\\|\\.")
                           (regexp-quote (match-string 0))))
-           (stmt-start (cdr langelem)) col)
+           (stmt-start (c-langelem-pos langelem)) col)
 
        (when (and operator
                   (looking-at operator)
@@ -794,7 +822,7 @@ result = prefix + \"A message \"
                   \"string.\";      <- c-lineup-string-cont
 
 Nil is returned in other situations, to allow stacking with other
-lineup functions.
+line-up functions.
 
 Works with: topmost-intro-cont, statement-cont, arglist-cont,
 arglist-cont-nonempty."
@@ -829,18 +857,18 @@ Works with: template-args-cont."
 Go to the position right after the message receiver, and if you are at
 the end of the line, indent the current line c-basic-offset columns
 from the opening bracket; otherwise you are looking at the first
-character of the first method call argument, so lineup the current
+character of the first method call argument, so line up the current
 line with it.
 
 Works with: objc-method-call-cont."
   (save-excursion
     (let* ((extra (save-excursion
                    (back-to-indentation)
-                   (c-backward-syntactic-ws (cdr langelem))
+                   (c-backward-syntactic-ws (c-langelem-pos langelem))
                    (if (eq (char-before) ?:)
                        (- c-basic-offset)
                      0)))
-          (open-bracket-pos (cdr langelem))
+          (open-bracket-pos (c-langelem-pos langelem))
            (open-bracket-col (progn
                               (goto-char open-bracket-pos)
                               (current-column)))
@@ -864,7 +892,7 @@ Works with: objc-method-args-cont."
     (let* ((here (c-point 'boi))
           (curcol (progn (goto-char here) (current-column)))
           (eol (c-point 'eol))
-          (relpos (cdr langelem))
+          (relpos (c-langelem-pos langelem))
           (first-col-column (progn
                               (goto-char relpos)
                               (skip-chars-forward "^:" eol)
@@ -888,7 +916,7 @@ Works with: objc-method-args-cont."
     (let* ((here (c-point 'boi))
           (curcol (progn (goto-char here) (current-column)))
           (eol (c-point 'eol))
-          (relpos (cdr langelem))
+          (relpos (c-langelem-pos langelem))
           (prev-col-column (progn
                              (skip-chars-backward "^:" relpos)
                              (and (eq (char-before) ?:)
@@ -927,13 +955,10 @@ Works with: inlambda, inexpr-statement, inexpr-class."
                                 containing-sexp))))))
       (when res
        (goto-char (cdr res))
-       (- (current-column)
-          (progn
-            (back-to-indentation)
-            (current-column)))))))
+       (vector (current-column))))))
 
 (defun c-lineup-whitesmith-in-block (langelem)
-  "Line up lines inside a block in whitesmith style.
+  "Line up lines inside a block in Whitesmith style.
 It's done in a way that works both when the opening brace hangs and
 when it doesn't.  E.g:
 
@@ -946,21 +971,54 @@ something
 In the first case the indentation is kept unchanged, in the
 second `c-basic-offset' is added.
 
-Works with: defun-close, defun-block-intro, block-close,
-brace-list-close, brace-list-intro, statement-block-intro and all in*
+Works with: defun-close, defun-block-intro, inline-close, block-close,
+brace-list-close, brace-list-intro, statement-block-intro,
+arglist-intro, arglist-cont-nonempty, arglist-close, and all in*
 symbols, e.g. inclass and inextern-lang."
   (save-excursion
-    (+ (progn
-        (back-to-indentation)
-        (if (eq (char-syntax (char-after)) ?\()
-            c-basic-offset
-          0))
-       (progn
-        (goto-char (cdr langelem))
-        (back-to-indentation)
-        (if (eq (char-syntax (char-after)) ?\()
-            0
-          c-basic-offset)))))
+    (if (and (c-go-up-list-backward)
+            (= (point) (c-point 'boi)))
+       nil
+      c-basic-offset)))
+
+(defun c-lineup-after-whitesmith-blocks (langelem)
+  "Compensate for Whitesmith style indentation of blocks.
+Due to the way CC Mode calculates anchor positions for normal lines
+inside blocks, this function is necessary for those lines to get
+correct Whitesmith style indentation.  Consider the following
+examples:
+
+                    int foo()
+                        {
+int foo()                   {
+    {                       a;
+    a;                      }
+    x;       <->        x;        <- c-lineup-after-whitesmith-blocks
+
+The fact that the line with \"x\" is preceded by a Whitesmith style
+indented block in one case and not the other should not affect its
+indentation.  But since CC Mode in cases like this uses the
+indentation of the preceding statement as anchor position, the \"x\"
+would in the rightmost case be indented too much if the offset for
+`statement' was set simply to zero.
+
+This lineup function corrects for this situation by detecting if the
+anchor position is at an open paren character.  In that case, it
+instead indents relative to the surrounding block just like
+`c-lineup-whitesmith-in-block'.
+
+Works with: brace-list-entry, brace-entry-open, statement,
+arglist-cont."
+  (save-excursion
+    (goto-char (c-langelem-pos langelem))
+    (when (looking-at "\\s\(")
+      (if (c-go-up-list-backward)
+         (let ((pos (point)))
+           (back-to-indentation)
+           (if (= pos (point))
+               (vector (current-column))
+             (vector (+ (current-column) c-basic-offset))))
+       (vector 0)))))
 
 (defun c-lineup-cpp-define (langelem)
   "Line up macro continuation lines according to the indentation of
@@ -1058,9 +1116,10 @@ Works with: cpp-define-intro."
 The \"x\" line is aligned to the text after the \":\" on the \"w\" line, and
 similarly \"z\" under \"y\".
 
-This is done only in an \"asm\" or \"__asm__\" block, and only to those
-lines mentioned.  Anywhere else nil is returned.  The usual arrangement is
-to have this routine as an extra feature at the start of arglist lineups, e.g.
+This is done only in an \"asm\" or \"__asm__\" block, and only to
+those lines mentioned.  Anywhere else nil is returned.  The usual
+arrangement is to have this routine as an extra feature at the start
+of arglist line-ups, e.g.
 
     (c-lineup-gcc-asm-reg c-lineup-arglist)
 
@@ -1076,7 +1135,7 @@ Works with: arglist-cont, arglist-cont-nonempty."
        ;; This can occur for arglist-cont-nonempty with nested arglist
        ;; starts on the same line.
        (or (not (eq (car elem) 'arglist-cont-nonempty))
-          (eq (elt c-syntactic-element 2)
+          (eq (c-langelem-2nd-pos c-syntactic-element)
               (c-most-enclosing-brace (c-parse-state))))
 
        ;; Find the ":" to align to.  Look for this first so as to quickly
@@ -1117,13 +1176,24 @@ ACTION associated with `block-close' syntax."
     (let (langelem)
       (if (and (eq syntax 'block-close)
               (setq langelem (assq 'block-close c-syntactic-context))
-              (progn (goto-char (elt langelem 1))
+              (progn (goto-char (c-langelem-pos langelem))
                      (if (eq (char-after) ?{)
                          (c-safe (c-forward-sexp -1)))
                      (looking-at "\\<do\\>[^_]")))
          '(before)
        '(before after)))))
 
+(defun c-snug-1line-defun-close (syntax pos)
+  "Determine the brace hanginess for an AWK defun-close.
+If the action/function being closed is a one-liner, keep it so.  Otherwise put
+the closing brace on its own line."
+  (save-excursion
+    (goto-char pos)
+    (if (> (c-point 'bol)
+          (progn (up-list -1) (point)))
+       '(before after)
+      '(after))))
+
 (defun c-gnu-impose-minimum ()
   "Imposes a minimum indentation for lines inside code blocks.
 The variable `c-label-minimum-indentation' specifies the minimum
index 995dc48c1aec37db7e617d923afdd209c91d3e46..b16d571d277bb750193bdbee06df5b2e75d31662 100644 (file)
@@ -1,7 +1,7 @@
 ;;; cc-awk.el --- AWK specific code within cc-mode.
 
-;; Copyright (C) 1988, 94, 96, 2000, 2001, 2002, 2003, 2004, 2005
-;; Free Software Foundation, Inc.
+;; Copyright (C) 1988,94,96,2000, 2001, 2002, 2003, 2004, 2005  Free
+;; Software Foundation, Inc.
 
 ;; Author: Alan Mackenzie <acm@muc.de> (originally based on awk-mode.el)
 ;; Maintainer: FSF
@@ -20,7 +20,7 @@
 ;; GNU General Public License for more details.
 
 ;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; along with this program; see the file COPYING.  If not, write to the
 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 ;; Boston, MA 02110-1301, USA.
 
 
 ;; This file contains (most of) the adaptations to cc-mode required for the
 ;; integration of AWK Mode.
-;; It is organised thusly:
+;; It is organised thusly, the sections being separated by page breaks:
 ;;   1. The AWK Mode syntax table.
-;;   2. Indentation calculation stuff ("c-awk-NL-prop text-property").
-;;   3. Syntax-table property/font-locking stuff, but not including the
+;;   2. Regular expressions for analysing AWK code.
+;;   3. Indentation calculation stuff ("c-awk-NL-prop text-property").
+;;   4. Syntax-table property/font-locking stuff, but not including the
 ;;      font-lock-keywords setting.
-;;   4. The AWK Mode before/after-change-functions.
-;;   5. AWK Mode specific versions of commands like beginning-of-defun.
+;;   5. The AWK Mode before/after-change-functions.
+;;   6. AWK Mode specific versions of commands like beginning-of-defun.
 ;; The AWK Mode keymap, abbreviation table, and the mode function itself are
 ;; in cc-mode.el.
 
@@ -70,7 +71,7 @@
     ;; / can delimit regexes or be a division operator.  By default we assume
     ;; that it is a division sign, and fix the regexp operator cases with
     ;; `font-lock-syntactic-keywords'.
-    (modify-syntax-entry ?/ "." st)     ; ACM 2002/4/27.
+    (modify-syntax-entry ?/ "." st)     ; ACM 2002/4/27.  
     (modify-syntax-entry ?* "." st)
     (modify-syntax-entry ?+ "." st)
     (modify-syntax-entry ?- "." st)
     st)
   "Syntax table in use in AWK Mode buffers.")
 
+\f
+;; This section defines regular expressions used in the analysis of AWK code.
+
+;; N.B. In the following regexps, an EOL is either \n OR \r.  This is because
+;; Emacs has in the past used \r to mark hidden lines in some fashion (and
+;; maybe still does).
+
+(defconst c-awk-esc-pair-re "\\\\\\(.\\|\n\\|\r\\|\\'\\)")
+;;   Matches any escaped (with \) character-pair, including an escaped newline.
+(defconst c-awk-non-eol-esc-pair-re "\\\\\\(.\\|\\'\\)")
+;;   Matches any escaped (with \) character-pair, apart from an escaped newline.
+(defconst c-awk-comment-without-nl "#.*")
+;; Matches an AWK comment, not including the terminating NL (if any).  Note
+;; that the "enclosing" (elisp) regexp must ensure the # is real.
+(defconst c-awk-nl-or-eob "\\(\n\\|\r\\|\\'\\)")
+;; Matches a newline, or the end of buffer.
+
+;; "Space" regular expressions.
+(eval-and-compile
+  (defconst c-awk-escaped-nl "\\\\[\n\r]"))
+;; Matches an escaped newline.
+(defconst c-awk-escaped-nls* (concat "\\(" c-awk-escaped-nl "\\)*"))
+;; Matches a possibly empty sequence of escaped newlines.  Used in
+;; awk-font-lock-keywords.
+;; (defconst c-awk-escaped-nls*-with-space*
+;;   (concat "\\(" c-awk-escaped-nls* "\\|" "[ \t]+" "\\)*"))
+;; The above RE was very slow.  It's runtime was doubling with each additional
+;; space :-(  Reformulate it as below:
+(eval-and-compile
+  (defconst c-awk-escaped-nls*-with-space*
+    (concat "\\(" c-awk-escaped-nl "\\|" "[ \t]" "\\)*")))
+;; Matches a possibly empty sequence of escaped newlines with optional
+;; interspersed spaces and tabs.  Used in awk-font-lock-keywords.
+(defconst c-awk-blank-or-comment-line-re
+  (concat "[ \t]*\\(#\\|\\\\?$\\)"))
+;; Matche (the tail of) a line containing at most either a comment or an
+;; escaped EOL.
+
+;; REGEXPS FOR "HARMLESS" STRINGS/LINES.
+(defconst c-awk-harmless-char-re "[^_#/\"\\\\\n\r]")
+;;   Matches any character but a _, #, /, ", \, or newline.  N.B. _" starts a
+;; localisation string in gawk 3.1
+(defconst c-awk-harmless-_ "_\\([^\"]\\|\\'\\)")
+;;   Matches an underline NOT followed by ".
+(defconst c-awk-harmless-string*-re
+  (concat "\\(" c-awk-harmless-char-re "\\|" c-awk-esc-pair-re "\\|" c-awk-harmless-_ "\\)*"))
+;;   Matches a (possibly empty) sequence of chars without unescaped /, ", \,
+;; #, or newlines.
+(defconst c-awk-harmless-string*-here-re
+  (concat "\\=" c-awk-harmless-string*-re))
+;; Matches the (possibly empty) sequence of chars without unescaped /, ", \,
+;; at point.
+(defconst c-awk-harmless-line-re
+  (concat c-awk-harmless-string*-re
+          "\\(" c-awk-comment-without-nl "\\)?" c-awk-nl-or-eob))
+;;   Matches (the tail of) an AWK \"logical\" line not containing an unescaped
+;; " or /.  "logical" means "possibly containing escaped newlines".  A comment
+;; is matched as part of the line even if it contains a " or a /.  The End of
+;; buffer is also an end of line.
+(defconst c-awk-harmless-lines+-here-re
+  (concat "\\=\\(" c-awk-harmless-line-re "\\)+"))
+;; Matches a sequence of (at least one) \"harmless-line\" at point.
+
+
+;; REGEXPS FOR AWK STRINGS.
+(defconst c-awk-string-ch-re "[^\"\\\n\r]")
+;; Matches any character which can appear unescaped in a string.
+(defconst c-awk-string-innards-re
+  (concat "\\(" c-awk-string-ch-re "\\|" c-awk-esc-pair-re "\\)*"))
+;;   Matches the inside of an AWK string (i.e. without the enclosing quotes).
+(defconst c-awk-string-without-end-here-re
+  (concat "\\=_?\"" c-awk-string-innards-re))
+;;   Matches an AWK string at point up to, but not including, any terminator.
+;; A gawk 3.1+ string may look like _"localisable string".
+(defconst c-awk-one-line-possibly-open-string-re
+  (concat "\"\\(" c-awk-string-ch-re "\\|" c-awk-non-eol-esc-pair-re "\\)*"
+         "\\(\"\\|\\\\?$\\|\\'\\)"))
+
+;; REGEXPS FOR AWK REGEXPS.
+(defconst c-awk-regexp-normal-re "[^[/\\\n\r]")
+;;   Matches any AWK regexp character which doesn't require special analysis.
+(defconst c-awk-escaped-newlines*-re "\\(\\\\[\n\r]\\)*")
+;;   Matches a (possibly empty) sequence of escaped newlines.
+
+;; NOTE: In what follows, "[asdf]" in a regexp will be called a "character
+;; list", and "[:alpha:]" inside a character list will be known as a
+;; "character class".  These terms for these things vary between regexp
+;; descriptions .
+(defconst c-awk-regexp-char-class-re
+  "\\[:[a-z]+:\\]")
+  ;; Matches a character class spec (e.g. [:alpha:]).
+(defconst c-awk-regexp-char-list-re
+  (concat "\\[" c-awk-escaped-newlines*-re "^?" c-awk-escaped-newlines*-re "]?"
+          "\\(" c-awk-esc-pair-re "\\|" c-awk-regexp-char-class-re
+         "\\|" "[^]\n\r]" "\\)*" "\\(]\\|$\\)"))
+;;   Matches a regexp char list, up to (but not including) EOL if the ] is
+;;   missing.
+(defconst c-awk-regexp-one-line-possibly-open-char-list-re
+  (concat "\\[\\]?\\(" c-awk-non-eol-esc-pair-re "\\|" "[^]\n\r]" "\\)*"
+         "\\(]\\|\\\\?$\\|\\'\\)"))
+;;   Matches the head (or all) of a regexp char class, up to (but not
+;;   including) the first EOL.
+(defconst c-awk-regexp-innards-re
+  (concat "\\(" c-awk-esc-pair-re "\\|" c-awk-regexp-char-list-re
+          "\\|" c-awk-regexp-normal-re "\\)*"))
+;;   Matches the inside of an AWK regexp (i.e. without the enclosing /s)
+(defconst c-awk-regexp-without-end-re
+  (concat "/" c-awk-regexp-innards-re))
+;; Matches an AWK regexp up to, but not including, any terminating /. 
+(defconst c-awk-one-line-possibly-open-regexp-re
+  (concat "/\\(" c-awk-non-eol-esc-pair-re
+         "\\|" c-awk-regexp-one-line-possibly-open-char-list-re
+         "\\|" c-awk-regexp-normal-re "\\)*"
+         "\\(/\\|\\\\?$\\|\\'\\)"))
+;; Matches as much of the head of an AWK regexp which fits on one line,
+;; possibly all of it.
+
+;; REGEXPS used for scanning an AWK buffer in order to decide IF A '/' IS A
+;; REGEXP OPENER OR A DIVISION SIGN.  By "state" in the following is meant
+;; whether a '/' at the current position would by a regexp opener or a
+;; division sign.
+(defconst c-awk-neutral-re
+;  "\\([{}@` \t]\\|\\+\\+\\|--\\|\\\\.\\)+") ; changed, 2003/6/7
+  "\\([{}@` \t]\\|\\+\\+\\|--\\|\\\\.\\)")
+;;   A "neutral" char(pair).  Doesn't change the "state" of a subsequent /.
+;; This is space/tab, braces, an auto-increment/decrement operator or an
+;; escaped character.  Or one of the (illegal) characters @ or `.  But NOT an
+;; end of line (even if escaped).
+(defconst c-awk-neutrals*-re
+  (concat "\\(" c-awk-neutral-re "\\)*"))
+;;   A (possibly empty) string of neutral characters (or character pairs).
+(defconst c-awk-var-num-ket-re "[]\)0-9a-zA-Z_$.\x80-\xff]+")
+;;   Matches a char which is a constituent of a variable or number, or a ket
+;; (i.e. closing bracKET), round or square.  Assume that all characters \x80 to
+;; \xff are "letters".
+(defconst c-awk-div-sign-re
+  (concat c-awk-var-num-ket-re c-awk-neutrals*-re "/"))
+;;   Will match a piece of AWK buffer ending in / which is a division sign, in
+;; a context where an immediate / would be a regexp bracket.  It follows a
+;; variable or number (with optional intervening "neutral" characters).  This
+;; will only work when there won't be a preceding " or / before the sought /
+;; to foul things up.
+(defconst c-awk-non-arith-op-bra-re
+  "[[\(&=:!><,?;'~|]")
+;;   Matches an openeing BRAcket ,round or square, or any operator character
+;; apart from +,-,/,*,%.  For the purpose at hand (detecting a / which is a
+;; regexp bracket) these arith ops are unnecessary and a pain, because of "++"
+;; and "--".
+(defconst c-awk-regexp-sign-re
+  (concat c-awk-non-arith-op-bra-re c-awk-neutrals*-re "/"))
+;;   Will match a piece of AWK buffer ending in / which is an opening regexp
+;; bracket, in a context where an immediate / would be a division sign.  This
+;; will only work when there won't be a preceding " or / before the sought /
+;; to foul things up.
+
+;; REGEXPS USED FOR FINDING THE POSITION OF A "virtual semicolon"
+(defconst c-awk-_-harmless-nonws-char-re "[^#/\"\\\\\n\r \t]")
+;;;; NEW VERSION!  (which will be restricted to the current line)
+(defconst c-awk-one-line-non-syn-ws*-re
+  (concat "\\([ \t]*"
+              "\\(" c-awk-_-harmless-nonws-char-re "\\|"
+                   c-awk-non-eol-esc-pair-re "\\|"
+                   c-awk-one-line-possibly-open-string-re "\\|"
+                   c-awk-one-line-possibly-open-regexp-re
+             "\\)"
+          "\\)*"))
+
+\f
 ;; ACM, 2002/5/29:
-;;
+;; 
 ;; The next section of code is about determining whether or not an AWK
 ;; statement is complete or not.  We use this to indent the following line.
 ;; The determination is pretty straightforward in C, where a statement ends
 ;; after-change function) must be constantly updated for the mode to work
 ;; properly).
 ;;
+;; This text property is also used for "syntactic whitespace" movement, this
+;; being where the distinction between the values '$' and '}' is significant.
+;;
 ;; The valid values for c-awk-NL-prop are:
 ;;
 ;; nil The property is not currently set for this line.
 ;;     essential to the syntax of the program.  (i.e. if it had been a
 ;;     frivolous \, it would have been ignored and the line been given one of
 ;;     the other property values.)
-;; ';' A statement is completed as the last thing (aside from ws) on the line -
-;;     i.e. there is (at least part of) a statement on this line, and the last
-;;     statement on the line is complete, OR (2002/10/25) the line is
-;;     content-free but terminates a statement from the preceding (continued)
-;;     line (which has property \).
+;; '$' A non-empty statement is terminated on the line by an EOL (a "virtual
+;;     semicolon").  This might be a content-free line terminating a statement
+;;     from the preceding (continued) line (which has property \).
+;; '}' A statement, being the last thing (aside from ws/comments) is
+;;     explicitly terminated on this line by a closing brace (or sometimes a
+;;     semicolon).
 ;;
 ;; This set of values has been chosen so that the property's value on a line
 ;; is completely determined by the contents of the line and the property on
   ;;
   ;; DO-LIM sets a limit on how far back we search for the "do" of a possible
   ;; do-while.
+  ;;
+  ;; This function might do hidden buffer changes.
   (and
    (eq (char-before) ?\))
    (save-excursion
 
 (defun c-awk-after-function-decl-param-list ()
   ;; Are we just after the ) in "function foo (bar)" ?
+  ;;
+  ;; This function might do hidden buffer changes.
   (and (eq (char-before) ?\))
        (save-excursion
          (let ((par-pos (c-safe (scan-lists (point) -1 0))))
 (defun c-awk-after-continue-token ()
 ;; Are we just after a token which can be continued onto the next line without
 ;; a backslash?
+;;
+;; This function might do hidden buffer changes.
   (save-excursion
     (c-backward-token-1)              ; FIXME 2002/10/27.  What if this fails?
     (if (and (looking-at "[&|]") (not (bobp)))
 (defun c-awk-after-rbrace-or-statement-semicolon ()
   ;; Are we just after a } or a ; which closes a statement?
   ;; Be careful about ;s in for loop control bits.  They don't count!
+  ;;
+  ;; This function might do hidden buffer changes.
   (or (eq (char-before) ?\})
       (and
        (eq (char-before) ?\;)
   ;;  Move back to just after the first found of either (i) an EOL which has
   ;;  the c-awk-NL-prop text-property set; or (ii) non-ws text; or (iii) BOB.
   ;;  We return either the value of c-awk-NL-prop (in case (i)) or nil.
-  ;;  Calling function can best distinguish cases (ii) and (iii) with (bolp).
+  ;;  Calling functions can best distinguish cases (ii) and (iii) with (bolp).
   ;;
   ;;  Note that an escaped eol counts as whitespace here.
   ;;
   ;;  Kludge: If c-backward-syntactic-ws gets stuck at a BOL, it is likely
   ;;  that the previous line contains an unterminated string (without \).  In
-  ;;  this case, assume that the previous line's c-awk-NL-prop is a ;.
-  ;;
+  ;;  this case, assume that the previous line's c-awk-NL-prop is a $.
+  ;; 
   ;;  POINT MUST BE AT THE START OF A LINE when calling this function.  This
   ;;  is to ensure that the various backward-comment functions will work
   ;;  properly.
+  ;;
+  ;; This function might do hidden buffer changes.
   (let ((nl-prop nil)
         bol-pos bsws-pos) ; starting pos for a backward-syntactic-ws call.
     (while ;; We are at a BOL here.  Go back one line each iteration.
                 (setq bsws-pos (point))
                 ;; N.B. the following function will not go back past an EOL if
                 ;; there is an open string (without \) on the previous line.
+                ;; If we find such, set the c-awk-NL-prop on it, too
+                ;; (2004/3/29).
                 (c-backward-syntactic-ws bol-pos)
                 (or (/= (point) bsws-pos)
-                    (progn (setq nl-prop ?\;)
+                    (progn (setq nl-prop ?\$)
+                          (c-put-char-property (1- (point)) 'c-awk-NL-prop nl-prop)
                            nil)))
          ;; If we had a backslash at EOL, c-backward-syntactic-ws will
          ;; have gone backwards over it.  Check the backslash was "real".
   ;; Calculate and set the value of the c-awk-NL-prop on the immediately
   ;; preceding EOL.  This may also involve doing the same for several
   ;; preceding EOLs.
-  ;;
+  ;; 
   ;; NOTE that if the property was already set, we return it without
   ;; recalculation.  (This is by accident rather than design.)
-  ;;
+  ;; 
   ;; Return the property which got set (or was already set) on the previous
   ;; line.  Return nil if we hit BOB.
-  ;;
+  ;; 
   ;; See c-awk-after-if-for-while-condition-p for a description of DO-LIM.
+  ;;
+  ;; This function might do hidden buffer changes.
   (save-excursion
     (save-match-data
       (beginning-of-line)
                  ((and (looking-at "[ \t]*\\\\$")
                        (not (c-awk-after-rbrace-or-statement-semicolon)))
                   ?\\)
-                 (t ?\;)))            ; A statement was completed on this line
+                ;; A statement was completed on this line.  How?
+                ((memq (char-before) '(?\; ?\}))  ?\}) ; Real ; or }
+                 (t ?\$)))            ; A virtual semicolon.
           (end-of-line)
           (c-put-char-property (point) 'c-awk-NL-prop nl-prop)
           (forward-line))
         ;; Set c-awk-NL-prop on each of these lines's EOL.
         (while (< (point) pos)         ; one content-free line each iteration.
           (cond              ; recalculate nl-prop from previous line's value.
-           ((memq nl-prop '(?\; nil)) (setq nl-prop ?\#))
+           ((memq nl-prop '(?\} ?\$ nil)) (setq nl-prop ?\#))
            ((eq nl-prop ?\\)
-            (if (not (looking-at "[ \t]*\\\\$")) (setq nl-prop ?\;))) ; was ?\#  2002/10/25
+            (if (not (looking-at "[ \t]*\\\\$")) (setq nl-prop ?\$)))
            ;; ?\# (empty line) and ?\{ (open stmt) don't change.
            )
           (forward-line)
   ;; Get the c-awk-NL-prop text-property from the previous line, calculating
   ;; it if necessary.  Return nil iff we're already at BOB.
   ;; See c-awk-after-if-for-while-condition-p for a description of DO-LIM.
+  ;;
+  ;; This function might do hidden buffer changes.
   (if (bobp)
       nil
     (or (c-get-char-property (c-point 'eopl) 'c-awk-NL-prop)
   ;; if necessary. (As a special case, the property doesn't get set on an
   ;; empty line at EOB (there's no position to set the property on), but the
   ;; function returns the property value an EOL would have got.)
-  ;;
+  ;; 
   ;; See c-awk-after-if-for-while-condition-p for a description of DO-LIM.
+  ;;
+  ;; This function might do hidden buffer changes.
   (save-excursion
     (let ((extra-nl nil))
       (end-of-line)                ; Necessary for the following test to work.
       (prog1 (c-awk-get-NL-prop-prev-line do-lim)
         (if extra-nl (delete-backward-char 1))))))
 
-(defun c-awk-prev-line-incomplete-p (&optional do-lim)
+(defsubst c-awk-prev-line-incomplete-p (&optional do-lim)
   ;; Is there an incomplete statement at the end of the previous line?
   ;; See c-awk-after-if-for-while-condition-p for a description of DO-LIM.
+  ;;
+  ;; This function might do hidden buffer changes.
   (memq (c-awk-get-NL-prop-prev-line do-lim) '(?\\ ?\{)))
 
-(defun c-awk-cur-line-incomplete-p (&optional do-lim)
+(defsubst c-awk-cur-line-incomplete-p (&optional do-lim)
   ;; Is there an incomplete statement at the end of the current line?
   ;; See c-awk-after-if-for-while-condition-p for a description of DO-LIM.
+  ;;
+  ;; This function might do hidden buffer changes.
   (memq (c-awk-get-NL-prop-cur-line do-lim) '(?\\ ?\{)))
 
-(defun c-awk-completed-stmt-ws-ends-prev-line-p (&optional do-lim)
-  ;; Is there a termination of a statement as the last thing (apart from an
-  ;; optional comment) on the previous line?
-  ;; See c-awk-after-if-for-while-condition-p for a description of DO-LIM.
-  (eq (c-awk-get-NL-prop-prev-line do-lim) ?\;))
-
-(defun c-awk-completed-stmt-ws-ends-line-p (&optional pos do-lim)
-  ;; Same as previous function, but for the line containing position POS (or
-  ;; the current line if POS is omitted).
-  ;; See c-awk-after-if-for-while-condition-p for a description of DO-LIM.
+;;;; NOTES ON "VIRTUAL SEMICOLONS"
+;;;;
+;;;; A "virtual semicolon" is what terminates a statement when there is no ;
+;;;; or } to do the job.  Like point, it is considered to lie _between_ two
+;;;; characters.  As from mid-March 2004, it is considered to lie just after
+;;;; the last non-syntactic-whitespace character on the line; (previously, it
+;;;; was considered an attribute of the EOL on the line).  A real semicolon
+;;;; never counts as a virtual one.
+
+(defun c-awk-at-vsemi-p (&optional pos)
+  ;; Is there a virtual semicolon at POS (or POINT)?
   (save-excursion
-    (if pos (goto-char pos))
-    (eq (c-awk-get-NL-prop-cur-line do-lim) ?\;)))
-
-(defun c-awk-after-logical-semicolon (&optional do-lim)
-;; Are we at BOL, the preceding EOL being a "logical semicolon"?
-;; See c-awk-after-if-for-while-condition-p for a description of DO-LIM.
-  (and (bolp)
-       (eq (c-awk-get-NL-prop-prev-line do-lim) ?\;)))
-
-(defun c-awk-backward-syntactic-ws (&optional lim)
-;; Skip backwards over awk-syntactic whitespace.  This is whitespace
-;; characters, comments, and NEWLINES WHICH AREN'T "VIRTUAL SEMICOLONS".  For
-;; this function, a newline isn't a "virtual semicolon" if that line ends with
-;; a real semicolon (or closing brace).
-;; However if point starts inside a comment or preprocessor directive, the
-;; content of it is not treated as whitespace.  LIM (optional) sets a limit on
-;; the backward movement.
-  (let ((lim (or lim (point-min)))
-        after-real-br)
-    (c-backward-syntactic-ws (max lim (c-point 'bol)))
-    (while                    ; go back one WS line each time round this loop.
-        (and (bolp)
-             (> (point) lim)
-             (/= (c-awk-get-NL-prop-prev-line) ?\;)
-             (/= (point)
-                 ;; The following function requires point at BONL [not EOL] to
-                 ;; recognise a preceding comment,.
-                 (progn (c-backward-syntactic-ws (max lim (c-point 'bopl)))
-                        (point)))))
-    ;; Does the previous line end with a real ; or }?  If so, go back to it.
-    (if (and (bolp)
-             (eq (c-awk-get-NL-prop-prev-line) ?\;)
-             (save-excursion
-               (c-backward-syntactic-ws (max lim (c-point 'bopl)))
-               (setq after-real-br (point))
-               (c-awk-after-rbrace-or-statement-semicolon)))
-        (goto-char after-real-br))))
-
-(defun c-awk-NL-prop-not-set ()
-  ;; Is the NL-prop on the current line either nil or unset?
+    (let (nl-prop
+         (pos-or-point (progn (if pos (goto-char pos)) (point))))
+      (forward-line 0)
+      (search-forward-regexp c-awk-one-line-non-syn-ws*-re)
+      (and (eq (point) pos-or-point)
+          (progn
+            (while (and (eq (setq nl-prop (c-awk-get-NL-prop-cur-line)) ?\\)
+                        (eq (forward-line) 0)
+                        (looking-at c-awk-blank-or-comment-line-re)))
+            (eq nl-prop ?\$))))))
+
+(defun c-awk-vsemi-status-unknown-p ()
+  ;; Are we unsure whether there is a virtual semicolon on the current line?
+  ;; DO NOT under any circumstances attempt to calculate this; that would
+  ;; defeat the (admittedly kludgey) purpose of this function, which is to
+  ;; prevent an infinite recursion in c-beginning-of-statement-1 when point
+  ;; starts at a `while' token.
   (not (c-get-char-property (c-point 'eol) 'c-awk-NL-prop)))
 
 (defun c-awk-clear-NL-props (beg end)
   ;; c-awk-NL-prop text property from beg to the end of the buffer (The END
   ;; parameter is ignored).  This ensures that the indentation engine will
   ;; never use stale values for this property.
+  ;;
+  ;; This function might do hidden buffer changes.
   (save-restriction
     (widen)
     (c-clear-char-properties beg (point-max) 'c-awk-NL-prop)))
 ;awk-mode-map isn't yet defined.  :-(
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
+\f
 ;; The following section of the code is to do with font-locking.  The biggest
 ;; problem for font-locking is deciding whether a / is a regular expression
 ;; delimiter or a division sign - determining precisely where strings and
 ;; Go back to the start of the (apparent) current line (or the start of the
 ;; line containing POS), returning the buffer position of that point.  I.e.,
 ;; go back to the last line which doesn't have an escaped EOL before it.
-;;
+;; 
 ;; This is guaranteed to be "safe" for syntactic analysis, i.e. outwith any
 ;; comment, string or regexp.  IT MAY WELL BE that this function should not be
 ;; executed on a narrowed buffer.
+;;
+;; This function might do hidden buffer changes.
   (if pos (goto-char pos))
   (forward-line 0)
   (while (and (> (point) (point-min))
 ;; This is guaranteed to be "safe" for syntactic analysis, i.e. outwith any
 ;; comment, string or regexp.  IT MAY WELL BE that this function should not be
 ;; executed on a narrowed buffer.
+;;
+;; This function might do hidden buffer changes.
   (if pos (goto-char pos))
   (end-of-line)
   (while (and (< (point) (point-max))
     (end-of-line 2))
   (point))
 
-;; N.B. In the following regexps, an EOL is either \n OR \r.  This is because
-;; Emacs has in the past used \r to mark hidden lines in some fashion (and
-;; maybe still does).
-
-(defconst c-awk-esc-pair-re "\\\\\\(.\\|\n\\|\r\\|\\'\\)")
-;;   Matches any escaped (with \) character-pair, including an escaped newline.
-(defconst c-awk-comment-without-nl "#.*")
-;; Matches an AWK comment, not including the terminating NL (if any).  Note
-;; that the "enclosing" (elisp) regexp must ensure the # is real.
-(defconst c-awk-nl-or-eob "\\(\n\\|\r\\|\\'\\)")
-;; Matches a newline, or the end of buffer.
-
-;; "Space" regular expressions.
-(defconst c-awk-escaped-nl "\\\\[\n\r]")
-;; Matches an escaped newline.
-(defconst c-awk-escaped-nls* (concat "\\(" c-awk-escaped-nl "\\)*"))
-;; Matches a possibly empty sequence of escaped newlines.  Used in
-;; awk-font-lock-keywords.
-;; (defconst c-awk-escaped-nls*-with-space*
-;;   (concat "\\(" c-awk-escaped-nls* "\\|" "[ \t]+" "\\)*"))
-;; The above RE was very slow.  It's runtime was doubling with each additional
-;; space :-(  Reformulate it as below:
-(defconst c-awk-escaped-nls*-with-space*
-  (concat "\\(" c-awk-escaped-nl "\\|" "[ \t]" "\\)*"))
-;; Matches a possibly empty sequence of escaped newlines with optional
-;; interspersed spaces and tabs.  Used in awk-font-lock-keywords.
-
-;; REGEXPS FOR "HARMLESS" STRINGS/LINES.
-(defconst c-awk-harmless-char-re "[^_#/\"\\\\\n\r]")
-;;   Matches any character but a _, #, /, ", \, or newline.  N.B. _" starts a
-;; localisation string in gawk 3.1
-(defconst c-awk-harmless-_ "_\\([^\"]\\|\\'\\)")
-;;   Matches an underline NOT followed by ".
-(defconst c-awk-harmless-string*-re
-  (concat "\\(" c-awk-harmless-char-re "\\|" c-awk-esc-pair-re "\\|" c-awk-harmless-_ "\\)*"))
-;;   Matches a (possibly empty) sequence of chars without unescaped /, ", \,
-;; #, or newlines.
-(defconst c-awk-harmless-string*-here-re
-  (concat "\\=" c-awk-harmless-string*-re))
-;; Matches the (possibly empty) sequence of chars without unescaped /, ", \,
-;; at point.
-(defconst c-awk-harmless-line-re
-  (concat c-awk-harmless-string*-re
-          "\\(" c-awk-comment-without-nl "\\)?" c-awk-nl-or-eob))
-;;   Matches (the tail of) an AWK \"logical\" line not containing an unescaped
-;; " or /.  "logical" means "possibly containing escaped newlines".  A comment
-;; is matched as part of the line even if it contains a " or a /.  The End of
-;; buffer is also an end of line.
-(defconst c-awk-harmless-lines+-here-re
-  (concat "\\=\\(" c-awk-harmless-line-re "\\)+"))
-;; Matches a sequence of (at least one) \"harmless-line\" at point.
-
-
-;; REGEXPS FOR AWK STRINGS.
-(defconst c-awk-string-ch-re "[^\"\\\n\r]")
-;; Matches any character which can appear unescaped in a string.
-(defconst c-awk-string-innards-re
-  (concat "\\(" c-awk-string-ch-re "\\|" c-awk-esc-pair-re "\\)*"))
-;;   Matches the inside of an AWK string (i.e. without the enclosing quotes).
-(defconst c-awk-string-without-end-here-re
-  (concat "\\=_?\"" c-awk-string-innards-re))
-;;   Matches an AWK string at point up to, but not including, any terminator.
-;; A gawk 3.1+ string may look like _"localisable string".
-
-;; REGEXPS FOR AWK REGEXPS.
-(defconst c-awk-regexp-normal-re "[^[/\\\n\r]")
-;;   Matches any AWK regexp character which doesn't require special analysis.
-(defconst c-awk-escaped-newlines*-re "\\(\\\\[\n\r]\\)*")
-;;   Matches a (possibly empty) sequence of escaped newlines.
-
-;; NOTE: In what follows, "[asdf]" in a regexp will be called a "character
-;; list", and "[:alpha:]" inside a character list will be known as a
-;; "character class".  These terms for these things vary between regexp
-;; descriptions .
-(defconst c-awk-regexp-char-class-re
-  "\\[:[a-z]+:\\]")
-  ;; Matches a character class spec (e.g. [:alpha:]).
-(defconst c-awk-regexp-char-list-re
-  (concat "\\[" c-awk-escaped-newlines*-re "^?" c-awk-escaped-newlines*-re "]?"
-          "\\(" c-awk-esc-pair-re "\\|" c-awk-regexp-char-class-re
-         "\\|" "[^]\n\r]" "\\)*" "\\(]\\|$\\)"))
-;;   Matches a regexp char list, up to (but not including) EOL if the ] is
-;;   missing.
-(defconst c-awk-regexp-innards-re
-  (concat "\\(" c-awk-esc-pair-re "\\|" c-awk-regexp-char-list-re
-          "\\|" c-awk-regexp-normal-re "\\)*"))
-;;   Matches the inside of an AWK regexp (i.e. without the enclosing /s)
-(defconst c-awk-regexp-without-end-re
-  (concat "/" c-awk-regexp-innards-re))
-;; Matches an AWK regexp up to, but not including, any terminating /.
-
-;; REGEXPS used for scanning an AWK buffer in order to decide IF A '/' IS A
-;; REGEXP OPENER OR A DIVISION SIGN.  By "state" in the following is meant
-;; whether a '/' at the current position would by a regexp opener or a
-;; division sign.
-(defconst c-awk-neutral-re
-;  "\\([{}@` \t]\\|\\+\\+\\|--\\|\\\\.\\)+") ; changed, 2003/6/7
-  "\\([{}@` \t]\\|\\+\\+\\|--\\|\\\\.\\)")
-;;   A "neutral" char(pair).  Doesn't change the "state" of a subsequent /.
-;; This is space/tab, braces, an auto-increment/decrement operator or an
-;; escaped character.  Or one of the (illegal) characters @ or `.  But NOT an
-;; end of line (even if escaped).
-(defconst c-awk-neutrals*-re
-  (concat "\\(" c-awk-neutral-re "\\)*"))
-;;   A (possibly empty) string of neutral characters (or character pairs).
-(defconst c-awk-var-num-ket-re "[]\)0-9a-zA-Z_$.\x80-\xff]+")
-;;   Matches a char which is a constituent of a variable or number, or a ket
-;; (i.e. closing bracKET), round or square.  Assume that all characters \x80 to
-;; \xff are "letters".
-(defconst c-awk-div-sign-re
-  (concat c-awk-var-num-ket-re c-awk-neutrals*-re "/"))
-;;   Will match a piece of AWK buffer ending in / which is a division sign, in
-;; a context where an immediate / would be a regexp bracket.  It follows a
-;; variable or number (with optional intervening "neutral" characters).  This
-;; will only work when there won't be a preceding " or / before the sought /
-;; to foul things up.
-(defconst c-awk-non-arith-op-bra-re
-  "[[\(&=:!><,?;'~|]")
-;;   Matches an openeing BRAcket ,round or square, or any operator character
-;; apart from +,-,/,*,%.  For the purpose at hand (detecting a / which is a
-;; regexp bracket) these arith ops are unnecessary and a pain, because of "++"
-;; and "--".
-(defconst c-awk-regexp-sign-re
-  (concat c-awk-non-arith-op-bra-re c-awk-neutrals*-re "/"))
-;;   Will match a piece of AWK buffer ending in / which is an opening regexp
-;; bracket, in a context where an immediate / would be a division sign.  This
-;; will only work when there won't be a preceding " or / before the sought /
-;; to foul things up.
-
 ;; ACM, 2002/02/15: The idea of the next function is to put the "Error font"
 ;; on strings/regexps which are missing their closing delimiter.
 ;; 2002/4/28.  The default syntax for / has been changed from "string" to
 ;;
 ;; If the closing delimiter is missing (i.e., there is an EOL there) set the
 ;; STRING-FENCE property on the opening " or / and closing EOL.
+;;
+;; This function does hidden buffer changes.
   (if (eq (char-after beg) ?_) (setq beg (1+ beg)))
 
   ;; First put the properties on the delimiters.
   (cond ((eq end (point-max))           ; string/regexp terminated by EOB
-         (put-text-property beg (1+ beg) 'syntax-table '(15))) ; (15) = "string fence"
+         (c-put-char-property beg 'syntax-table '(15))) ; (15) = "string fence"
         ((/= (char-after beg) (char-after end)) ; missing end delimiter
-         (put-text-property beg (1+ beg) 'syntax-table '(15))
-         (put-text-property end (1+ end) 'syntax-table '(15)))
+         (c-put-char-property beg 'syntax-table '(15))
+         (c-put-char-property end 'syntax-table '(15)))
         ((eq (char-after beg) ?/)       ; Properly bracketed regexp
-         (put-text-property beg (1+ beg) 'syntax-table '(7)) ; (7) = "string"
-         (put-text-property end (1+ end) 'syntax-table '(7)))
+         (c-put-char-property beg 'syntax-table '(7)) ; (7) = "string"
+         (c-put-char-property end 'syntax-table '(7)))
         (t))                       ; Properly bracketed string: Nothing to do.
   ;; Now change the properties of any escaped "s in the string to punctuation.
   (save-excursion
     (goto-char (1+ beg))
     (or (eobp)
         (while (search-forward "\"" end t)
-          (put-text-property (1- (point)) (point) 'syntax-table '(1))))))
+          (c-put-char-property (1- (point)) 'syntax-table '(1))))))
 
 (defun c-awk-syntax-tablify-string ()
   ;; Point is at the opening " or _" of a string.  Set the syntax-table
   ;;
   ;; The result is nil if a / immediately after the string would be a regexp
   ;; opener, t if it would be a division sign.
+  ;;
+  ;; This function does hidden buffer changes.
   (search-forward-regexp c-awk-string-without-end-here-re nil t) ; a (possibly unterminated) string
   (c-awk-set-string-regexp-syntax-table-properties
    (match-beginning 0) (match-end 0))
   ;; point is.
   ;;
   ;; The result is what ANCHOR-STATE-/DIV (see above) is where point is left.
+  ;;
+  ;; This function might do hidden buffer changes.
   (let ((/point (point)))
     (goto-char anchor)
     ;; Analyse the line to find out what the / is.
 ;;   given the property "punctuation".  This will later allow other routines
 ;;   to use the regexp "\\S\"*" to skip over the string innards.
 ;; (iv) Inside a comment, all syntax-table properties are cleared.
+;;
+;; This function does hidden buffer changes.
   (let (anchor
        (anchor-state-/div nil)) ; t means a following / would be a div sign.
     (c-awk-beginning-of-logical-line) ; ACM 2002/7/21.  This is probably redundant.
-    (put-text-property (point) lim 'syntax-table nil)
-    (search-forward-regexp c-awk-harmless-lines+-here-re nil t) ; skip harmless lines.
-
+    (c-clear-char-properties (point) lim 'syntax-table)
     ;; Once round the next loop for each string, regexp, or div sign
-    (while (< (point) lim)
+    (while (progn
+             ;; Skip any "harmless" lines before the next tricky one.
+             (if (search-forward-regexp c-awk-harmless-lines+-here-re nil t)
+                 (setq anchor-state-/div nil))
+             (< (point) lim))
       (setq anchor (point))
       (search-forward-regexp c-awk-harmless-string*-here-re nil t)
       ;; We are now looking at either a " or a /.
       (setq anchor-state-/div
             (if (looking-at "_?\"")
                 (c-awk-syntax-tablify-string)
-              (c-awk-syntax-tablify-/ anchor anchor-state-/div)))
-
-      ;; Skip any further "harmless" lines before the next tricky one.
-      (if (search-forward-regexp c-awk-harmless-lines+-here-re nil t)
-          (setq anchor-state-/div nil)))
+              (c-awk-syntax-tablify-/ anchor anchor-state-/div))))
     nil))
 
 
 ;; This function is called exclusively from the before-change-functions hook.
 ;; It does two things: Finds the end of the (logical) line on which END lies,
 ;; and clears c-awk-NL-prop text properties from this point onwards.
+;;
+;; This function might do hidden buffer changes.
   (save-restriction
     (save-excursion
       (setq c-awk-old-EOLL (c-awk-end-of-logical-line end))
   ;; This is the end of the logical line on which the change happened, either
   ;; as it was before the change, or as it is now, which ever is later.
   ;; N.B. point is left undefined.
+  ;;
+  ;; This function might do hidden buffer changes.
   (max (+ (- c-awk-old-EOLL old-len) (- end beg))
        (c-awk-end-of-logical-line end)))
 
 ;; changed region.  However, if font-lock is enabled, this function does
 ;; nothing, since an enabled font-lock after-change function will always do
 ;; this.
+;;
+;; This function might do hidden buffer changes.
   (unless (and (boundp 'font-lock-mode) font-lock-mode)
     (save-restriction
       (save-excursion
 (c-awk-advise-fl-for-awk-region lazy-lock-defer-rest-after-change)
 (c-awk-advise-fl-for-awk-region lazy-lock-defer-line-after-change)
 
-;; ACM 2002/9/29.  Functions for C-M-a and C-M-e
+\f
+;; ACM 2002/9/29.  Movement functions, e.g. for C-M-a and C-M-e
 
+;; The following three regexps differ from those earlier on in cc-awk.el in
+;; that they assume the syntax-table properties have been set.  They are thus
+;; not useful for code which sets these properties.
 (defconst c-awk-terminated-regexp-or-string-here-re "\\=\\s\"\\S\"*\\s\"")
-;; Matches a terminated string/regexp (utilising syntax-table properties).
+;; Matches a terminated string/regexp.
 
 (defconst c-awk-unterminated-regexp-or-string-here-re "\\=\\s|\\S|*$")
 ;; Matches an unterminated string/regexp, NOT including the eol at the end.
   (concat "\\([^{;#/\"\\\\\n\r]\\|" c-awk-esc-pair-re "\\)*"))
 ;; Matches any "harmless" character in a pattern or an escaped character pair.
 
+(defun c-awk-at-statement-end-p ()
+  ;; Point is not inside a comment or string.  Is it AT the end of a
+  ;; statement?  This means immediately after the last non-ws character of the
+  ;; statement.  The caller is responsible for widening the buffer, if
+  ;; appropriate.
+  (and (not (bobp))
+       (save-excursion
+        (backward-char)
+        (or (looking-at "[};]")
+            (and (memq (c-awk-get-NL-prop-cur-line) '(?\$ ?\\))
+                 (looking-at
+                  (eval-when-compile
+                    (concat "[^ \t\n\r\\]" c-awk-escaped-nls*-with-space*
+                            "[#\n\r]"))))))))
+
 (defun c-awk-beginning-of-defun (&optional arg)
   "Move backward to the beginning of an AWK \"defun\".  With ARG, do it that
 many times.  Negative arg -N means move forward to Nth following beginning of
@@ -807,7 +891,10 @@ By a \"defun\" is meant either a pattern-action pair or a function.  The start
 of a defun is recognized as code starting at column zero which is neither a
 closing brace nor a comment nor a continuation of the previous line.  Unlike
 in some other modes, having an opening brace at column 0 is neither necessary
-nor helpful."
+nor helpful.
+
+Note that this function might do hidden buffer changes.  See the
+comment at the start of cc-engine.el for more info."
   (interactive "p")
   (save-match-data
     (c-save-buffer-state                ; ensures the buffer is writable.
@@ -820,14 +907,14 @@ nor helpful."
              ;; is genuinely a beginning-of-defun.
              (while (and (setq found (search-backward-regexp
                                       "^[^#} \t\n\r]" (point-min) 'stop-at-limit))
-                         (not (memq (c-awk-get-NL-prop-prev-line) '(?\; ?\#)))))
+                         (not (memq (c-awk-get-NL-prop-prev-line) '(?\$ ?\} ?\#)))))
              (setq arg (1- arg)))
          ;; The same for a -ve arg.
          (if (not (eq (point) (point-max))) (forward-char 1))
          (while (and found (< arg 0) (not (eq (point) (point-max)))) ; The same for -ve arg.
            (while (and (setq found (search-forward-regexp
                                     "^[^#} \t\n\r]" (point-max) 'stop-at-limit))
-                       (not (memq (c-awk-get-NL-prop-prev-line) '(?\; ?\#)))))
+                       (not (memq (c-awk-get-NL-prop-prev-line) '(?\$ ?\} ?\#)))))
            (setq arg (1+ arg)))
          (if found (goto-char (match-beginning 0))))
        (eq arg 0)))))
@@ -838,6 +925,8 @@ nor helpful."
   ;; comment.  Typically, we stop at the { which denotes the corresponding AWK
   ;; action/function body.  Otherwise we stop at the EOL (or ;) marking the
   ;; absence of an explicit action.
+  ;;
+  ;; This function might do hidden buffer changes.
   (while
       (progn
         (search-forward-regexp c-awk-harmless-pattern-characters*)
@@ -855,6 +944,8 @@ nor helpful."
 
 (defun c-awk-end-of-defun1 ()
   ;; point is at the start of a "defun".  Move to its end.  Return end position.
+  ;;
+  ;; This function might do hidden buffer changes.
   (c-awk-forward-awk-pattern)
   (cond
    ((looking-at "{") (goto-char (scan-sexps (point) 1)))
@@ -866,6 +957,8 @@ nor helpful."
 (defun c-awk-beginning-of-defun-p ()
   ;; Are we already at the beginning of a defun?  (i.e. at code in column 0
   ;; which isn't a }, and isn't a continuation line of any sort.
+  ;;
+  ;; This function might do hidden buffer changes.
   (and (looking-at "^[^#} \t\n\r]")
        (not (c-awk-prev-line-incomplete-p))))
 
@@ -875,7 +968,10 @@ Negative argument -N means move back to Nth preceding end of defun.
 
 An end of a defun occurs right after the closing brace that matches the
 opening brace at its start, or immediately after the AWK pattern when there is
-no explicit action; see function `c-awk-beginning-of-defun'."
+no explicit action; see function `c-awk-beginning-of-defun'.
+
+Note that this function might do hidden buffer changes.  See the
+comment at the start of cc-engine.el for more info."
   (interactive "p")
   (or arg (setq arg 1))
   (save-match-data
@@ -911,6 +1007,7 @@ no explicit action; see function `c-awk-beginning-of-defun'."
                      (< arg 0)))
          (goto-char (min start-point end-point)))))))
 
+\f
 (cc-provide 'cc-awk)                   ; Changed from 'awk-mode, ACM 2002/5/21
 
 ;;; arch-tag: c4836289-3aa4-4a59-9934-9ccc2bacccf3
index ae7adb92edbd25031103bf6335ec1189c18eb7d7..6358f230e7ccf5c935f17f7d71339279f44e3597 100644 (file)
@@ -1,7 +1,7 @@
 ;;; cc-bytecomp.el --- compile time setup for proper compilation
 
-;; Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005
-;; Free Software Foundation, Inc.
+;; Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation,
+;; Inc.
 
 ;; Author:     Martin Stjernholm
 ;; Maintainer: bug-cc-mode@gnu.org
@@ -22,7 +22,7 @@
 ;; GNU General Public License for more details.
 
 ;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING.  If not, write to
+;; along with this program; see the file COPYING.  If not, write to
 ;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 ;; Boston, MA 02110-1301, USA.
 
index 42808c3e3077f633baa1b325f899d1579c38cc90..e17656e54dd2def183c542bd99f1839dd56e3415 100644 (file)
@@ -1,6 +1,7 @@
 ;;; cc-cmds.el --- user level commands for CC Mode
 
-;; Copyright (C) 1985,1987,1992-2003, 2004, 2005 Free Software Foundation, Inc.
+;; Copyright (C) 1985,1987,1992-2003, 2004, 2005 Free Software Foundation,
+;; Inc.
 
 ;; Authors:    1998- Martin Stjernholm
 ;;             1992-1999 Barry A. Warsaw
@@ -24,7 +25,7 @@
 ;; GNU General Public License for more details.
 
 ;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING.  If not, write to
+;; along with this program; see the file COPYING.  If not, write to
 ;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 ;; Boston, MA 02110-1301, USA.
 
 (cc-require 'cc-engine)
 
 ;; Silence the compiler.
-(cc-bytecomp-defvar delete-key-deletes-forward) ; XEmacs 20+
-(cc-bytecomp-defun delete-forward-p)   ; XEmacs 21+
-(cc-bytecomp-obsolete-fun insert-and-inherit) ; Marked obsolete in XEmacs 19
+(cc-bytecomp-defun delete-forward-p)   ; XEmacs
 (cc-bytecomp-defvar filladapt-mode)    ; c-fill-paragraph contains a kludge
                                        ; which looks at this.
-
+(cc-bytecomp-defun c-forward-subword)
+(cc-bytecomp-defun c-backward-subword)
 \f
 (defvar c-fix-backslashes t)
 
@@ -64,8 +64,6 @@ point is used to decide where the old indentation is on a lines that
 is otherwise empty \(ignoring any line continuation backslash), but
 that's not done if IGNORE-POINT-POS is non-nil.  Returns the amount of
 indentation change \(in columns)."
-  ;;
-  ;; This function does not do any hidden buffer changes.
 
   (let ((line-cont-backslash (save-excursion
                               (end-of-line)
@@ -134,13 +132,11 @@ indentation change \(in columns)."
     shift-amt))
 
 (defun c-newline-and-indent (&optional newline-arg)
-  "Inserts a newline and indents the new line.
+  "Insert a newline and indent the new line.
 This function fixes line continuation backslashes if inside a macro,
 and takes care to set the indentation before calling
 `indent-according-to-mode', so that lineup functions like
 `c-lineup-dont-change' works better."
-  ;;
-  ;; This function does not do any hidden buffer changes.
 
   ;; TODO: Backslashes before eol in comments and literals aren't
   ;; kept intact.
@@ -221,14 +217,30 @@ With universal argument, inserts the analysis as a comment on that line."
                   (c-save-buffer-state nil
                     (c-guess-basic-syntax)))))
     (if (not (consp arg))
-       (message "syntactic analysis: %s" syntax)
+       (let (elem pos ols)
+         (message "Syntactic analysis: %s" syntax)
+         (unwind-protect
+             (progn
+               (while syntax
+                 (setq elem (pop syntax))
+                 (when (setq pos (c-langelem-pos elem))
+                   (push (c-put-overlay pos (1+ pos)
+                                        'face 'highlight)
+                         ols))
+                 (when (setq pos (c-langelem-2nd-pos elem))
+                   (push (c-put-overlay pos (1+ pos)
+                                        'face 'secondary-selection)
+                         ols)))
+               (sit-for 10))
+           (while ols
+             (c-delete-overlay (pop ols)))))
       (indent-for-comment)
       (insert-and-inherit (format "%s" syntax))
       ))
   (c-keep-region-active))
 
 (defun c-syntactic-information-on-region (from to)
-  "Inserts a comment with the syntactic analysis on every line in the region."
+  "Insert a comment with the syntactic analysis on every line in the region."
   (interactive "*r")
   (save-excursion
     (save-restriction
@@ -239,6 +251,23 @@ With universal argument, inserts the analysis as a comment on that line."
        (forward-line)))))
 
 \f
+(defun c-update-modeline ()
+  (let ((fmt (format "/%s%s%s%s"
+                    (if c-electric-flag "l" "")
+                    (if (and c-electric-flag c-auto-newline)
+                        "a" "")
+                    (if c-hungry-delete-key "h" "")
+                    (if (and
+                         ;; cc-subword might not be loaded.
+                         (boundp 'c-subword-mode)
+                         (symbol-value 'c-subword-mode))
+                        "w"
+                      ""))))
+    (setq c-submode-indicators
+         (if (> (length fmt) 1)
+             fmt))
+    (force-mode-line-update)))
+
 (defun c-toggle-syntactic-indentation (&optional arg)
   "Toggle syntactic indentation.
 Optional numeric ARG, if supplied, turns on syntactic indentation when
@@ -249,12 +278,12 @@ When syntactic indentation is turned on (the default), the indentation
 functions and the electric keys indent according to the syntactic
 context keys, when applicable.
 
-When it's turned off, the electric keys does no reindentation, the
-indentation functions indents every new line to the same level as the
-previous nonempty line, and \\[c-indent-command] adjusts the
-indentation in seps specified `c-basic-offset'.  The indentation style
-has no effect in this mode, nor any of the indentation associated
-variables, e.g. `c-special-indent-hook'.
+When it's turned off, the electric keys don't reindent, the indentation
+functions indents every new line to the same level as the previous
+nonempty line, and \\[c-indent-command] adjusts the indentation in steps
+specified by `c-basic-offset'.  The indentation style has no effect in
+this mode, nor any of the indentation associated variables,
+e.g. `c-special-indent-hook'.
 
 This command sets the variable `c-syntactic-indentation'."
   (interactive "P")
@@ -262,30 +291,36 @@ This command sets the variable `c-syntactic-indentation'."
        (c-calculate-state arg c-syntactic-indentation))
   (c-keep-region-active))
 
-(defun c-toggle-auto-state (&optional arg)
+(defun c-toggle-auto-newline (&optional arg)
   "Toggle auto-newline feature.
 Optional numeric ARG, if supplied, turns on auto-newline when
 positive, turns it off when negative, and just toggles it when zero or
 left out.
 
-When the auto-newline feature is enabled (as evidenced by the `/a' or
-`/ah' on the modeline after the mode name) newlines are automatically
-inserted after special characters such as brace, comma, semi-colon,
-and colon."
+Turning on auto-newline automatically enables electric indentation.
+
+When the auto-newline feature is enabled (indicated by \"/la\" on the
+modeline after the mode name) newlines are automatically inserted
+after special characters such as brace, comma, semi-colon, and colon."
   (interactive "P")
-  (setq c-auto-newline (c-calculate-state arg c-auto-newline))
+  (setq c-auto-newline
+       (c-calculate-state arg (and c-auto-newline c-electric-flag)))
+  (if c-auto-newline (setq c-electric-flag t))
   (c-update-modeline)
   (c-keep-region-active))
 
+(defalias 'c-toggle-auto-state 'c-toggle-auto-newline)
+(make-obsolete 'c-toggle-auto-state 'c-toggle-auto-newline)
+
 (defun c-toggle-hungry-state (&optional arg)
   "Toggle hungry-delete-key feature.
 Optional numeric ARG, if supplied, turns on hungry-delete when
 positive, turns it off when negative, and just toggles it when zero or
 left out.
 
-When the hungry-delete-key feature is enabled (as evidenced by the
-`/h' or `/ah' on the modeline after the mode name) the delete key
-gobbles all preceding whitespace in one fell swoop."
+When the hungry-delete-key feature is enabled (indicated by \"/h\" on
+the modeline after the mode name) the delete key gobbles all preceding
+whitespace in one fell swoop."
   (interactive "P")
   (setq c-hungry-delete-key (c-calculate-state arg c-hungry-delete-key))
   (c-update-modeline)
@@ -297,27 +332,38 @@ Optional numeric ARG, if supplied, turns on auto-newline and
 hungry-delete when positive, turns them off when negative, and just
 toggles them when zero or left out.
 
-See `c-toggle-auto-state' and `c-toggle-hungry-state' for details."
+See `c-toggle-auto-newline' and `c-toggle-hungry-state' for details."
   (interactive "P")
   (setq c-auto-newline (c-calculate-state arg c-auto-newline))
   (setq c-hungry-delete-key (c-calculate-state arg c-hungry-delete-key))
   (c-update-modeline)
   (c-keep-region-active))
 
+(defun c-toggle-electric-state (&optional arg)
+  "Toggle the electric indentation feature.
+Optional numeric ARG, if supplied, turns on electric indentation when
+positive, turns it off when negative, and just toggles it when zero or
+left out."
+  (interactive "P")
+  (setq c-electric-flag (c-calculate-state arg c-electric-flag))
+  (c-update-modeline)
+  (c-keep-region-active))
+
 \f
 ;; Electric keys
 
 (defun c-electric-backspace (arg)
   "Delete the preceding character or whitespace.
-If `c-hungry-delete-key' is non-nil, as evidenced by the \"/h\" or
-\"/ah\" string on the mode line, then all preceding whitespace is
-consumed.  If however a prefix argument is supplied, or
-`c-hungry-delete-key' is nil, or point is inside a literal then the
-function in the variable `c-backspace-function' is called."
+If `c-hungry-delete-key' is non-nil (indicated by \"/h\" on the mode
+line) then all preceding whitespace is consumed.  If however a prefix
+argument is supplied, or `c-hungry-delete-key' is nil, or point is
+inside a literal then the function in the variable
+`c-backspace-function' is called."
   (interactive "*P")
-  (if (or (not c-hungry-delete-key)
-         arg
-         (c-in-literal))
+  (if (c-save-buffer-state ()
+       (or (not c-hungry-delete-key)
+           arg
+           (c-in-literal)))
       (funcall c-backspace-function (prefix-numeric-value arg))
     (c-hungry-backspace)))
 
@@ -334,15 +380,16 @@ See also \\[c-hungry-delete-forward]."
 
 (defun c-electric-delete-forward (arg)
   "Delete the following character or whitespace.
-If `c-hungry-delete-key' is non-nil, as evidenced by the \"/h\" or
-\"/ah\" string on the mode line, then all following whitespace is
-consumed.  If however a prefix argument is supplied, or
-`c-hungry-delete-key' is nil, or point is inside a literal then the
-function in the variable `c-delete-function' is called."
+If `c-hungry-delete-key' is non-nil (indicated by \"/h\" on the mode
+line) then all following whitespace is consumed.  If however a prefix
+argument is supplied, or `c-hungry-delete-key' is nil, or point is
+inside a literal then the function in the variable `c-delete-function'
+is called."
   (interactive "*P")
-  (if (or (not c-hungry-delete-key)
-         arg
-         (c-in-literal))
+  (if (c-save-buffer-state ()
+       (or (not c-hungry-delete-key)
+           arg
+           (c-in-literal)))
       (funcall c-delete-function (prefix-numeric-value arg))
     (c-hungry-delete-forward)))
 
@@ -361,43 +408,54 @@ See also \\[c-hungry-backspace]."
 (defun c-electric-delete (arg)
   "Deletes preceding or following character or whitespace.
 This function either deletes forward as `c-electric-delete-forward' or
-backward as `c-electric-backspace', depending on the configuration:
-
-If the function `delete-forward-p' is defined (XEmacs 21) and returns
-non-nil, it deletes forward.  Else, if the variable
-`delete-key-deletes-forward' is defined (XEmacs 20) and is set to
-non-nil, it deletes forward.  Otherwise it deletes backward.
-
-Note: This is the way in XEmacs 20 and later to choose the correct
-action for the [delete] key, whichever key that means.  In other
-flavors this function isn't used, instead it's left to the user to
-bind [delete] to either \\[c-electric-delete-forward] or \\[c-electric-backspace] as appropriate
-\(the keymap `function-key-map' is useful for that).  Emacs 21 handles
-that automatically, though."
+backward as `c-electric-backspace', depending on the configuration: If
+the function `delete-forward-p' is defined and returns non-nil, it
+deletes forward.  Otherwise it deletes backward.
+
+Note: This is the way in XEmacs to choose the correct action for the
+\[delete] key, whichever key that means.  Other flavors don't use this
+function to control that."
   (interactive "*P")
-  (if (or (and (fboundp 'delete-forward-p) ;XEmacs 21
-              (delete-forward-p))
-         (and (boundp 'delete-key-deletes-forward) ;XEmacs 20
-              delete-key-deletes-forward))
+  (if (and (fboundp 'delete-forward-p)
+          (delete-forward-p))
       (c-electric-delete-forward arg)
     (c-electric-backspace arg)))
 
+;; This function is only used in XEmacs.
+(defun c-hungry-delete ()
+  "Delete a non-whitespace char, or all whitespace up to the next non-whitespace char.
+The direction of deletion depends on the configuration: If the
+function `delete-forward-p' is defined and returns non-nil, it deletes
+forward using `c-hungry-delete-forward'.  Otherwise it deletes
+backward using `c-hungry-backspace'.
+
+Note: This is the way in XEmacs to choose the correct action for the
+\[delete] key, whichever key that means.  Other flavors don't use this
+function to control that."
+  (interactive)
+  (if (and (fboundp 'delete-forward-p)
+          (delete-forward-p))
+      (c-hungry-delete-forward)
+    (c-hungry-backspace)))
+
 (defun c-electric-pound (arg)
-  "Electric pound (`#') insertion.
-Inserts a `#' character specially depending on the variable
-`c-electric-pound-behavior'.  If a numeric ARG is supplied, or if
-point is inside a literal or a macro, nothing special happens."
+  "Insert a \"#\".
+If `c-electric-flag' is set, handle it specially according to the variable
+`c-electric-pound-behavior'.  If a numeric ARG is supplied, or if point is
+inside a literal or a macro, nothing special happens."
   (interactive "*P")
-  (if (or arg
-         (not (memq 'alignleft c-electric-pound-behavior))
-         (save-excursion
-           (skip-chars-backward " \t")
-           (not (bolp)))
-         (save-excursion
-           (and (= (forward-line -1) 0)
-                (progn (end-of-line)
-                       (eq (char-before) ?\\))))
-         (c-in-literal))
+  (if (c-save-buffer-state ()
+       (or arg
+           (not c-electric-flag)
+           (not (memq 'alignleft c-electric-pound-behavior))
+           (save-excursion
+             (skip-chars-backward " \t")
+             (not (bolp)))
+           (save-excursion
+             (and (= (forward-line -1) 0)
+                  (progn (end-of-line)
+                         (eq (char-before) ?\\))))
+           (c-in-literal)))
       ;; do nothing special
       (self-insert-command (prefix-numeric-value arg))
     ;; place the pound character at the left edge
@@ -410,243 +468,332 @@ point is inside a literal or a macro, nothing special happens."
           (goto-char (- (point-max) pos)))
       )))
 
+(defun c-point-syntax ()
+  ;; Return the syntactic context of the construct at point.  (This is NOT
+  ;; nec. the same as the s.c. of the line point is on).  N.B. This won't work
+  ;; between the `#' of a cpp thing and what follows (see c-opt-cpp-prefix).
+  (c-save-buffer-state (;; shut this up too
+       (c-echo-syntactic-information-p nil)
+       syntax)
+    (c-tentative-buffer-changes
+      ;; insert a newline to isolate the construct at point for syntactic
+      ;; analysis.
+      (insert-char ?\n 1)
+      ;; In AWK (etc.) or in a macro, make sure this CR hasn't changed
+      ;; the syntax.  (There might already be an escaped NL there.)
+      (when (or (c-at-vsemi-p (1- (point)))
+               (let ((pt (point)))
+                 (save-excursion
+                   (backward-char)
+                   (and (c-beginning-of-macro)
+                        (progn (c-end-of-macro)
+                               (< (point) pt))))))
+       (backward-char)
+       (insert-char ?\\ 1)
+       (forward-char))
+      (let ((c-syntactic-indentation-in-macros t)
+           (c-auto-newline-analysis t))
+       ;; Turn on syntactic macro analysis to help with auto
+       ;; newlines only.
+       (setq syntax (c-guess-basic-syntax))
+       nil))
+    syntax))
+
+(defun c-brace-newlines (syntax)
+  ;; A brace stands at point.  SYNTAX is the syntactic context of this brace
+  ;; (not necessarily the same as the S.C. of the line it is on).  Return
+  ;; NEWLINES, the list containing some combination of the symbols `before'
+  ;; and `after' saying where newlines should be inserted.
+  (c-save-buffer-state
+      ((syms
+       ;; This is the list of brace syntactic symbols that can hang.
+       ;; If any new ones are added to c-offsets-alist, they should be
+       ;; added here as well.
+       '(class-open class-close defun-open defun-close
+                    inline-open inline-close
+                    brace-list-open brace-list-close
+                    brace-list-intro brace-entry-open
+                    block-open block-close
+                    substatement-open statement-case-open
+                    extern-lang-open extern-lang-close
+                    namespace-open namespace-close
+                    module-open module-close
+                    composition-open composition-close
+                    inexpr-class-open inexpr-class-close
+                    ;; `statement-cont' is here for the case with a brace
+                    ;; list opener inside a statement.  C.f. CASE B.2 in
+                    ;; `c-guess-continued-construct'.
+                    statement-cont))
+       ;; shut this up too
+       (c-echo-syntactic-information-p nil)
+       symb-newlines)               ; e.g. (substatement-open . (after))
+    
+    (setq symb-newlines
+         ;; Do not try to insert newlines around a special
+         ;; (Pike-style) brace list.
+         (if (and c-special-brace-lists
+                  (save-excursion
+                    (c-safe (if (= (char-before) ?{)
+                                (forward-char -1)
+                              (c-forward-sexp -1))
+                            (c-looking-at-special-brace-list))))
+             nil
+           ;; Seek the matching entry in c-hanging-braces-alist.
+           (or (c-lookup-lists
+                syms
+                ;; Substitute inexpr-class and class-open or
+                ;; class-close with inexpr-class-open or
+                ;; inexpr-class-close.
+                (if (assq 'inexpr-class syntax)
+                    (cond ((assq 'class-open syntax)
+                           '((inexpr-class-open)))
+                          ((assq 'class-close syntax)
+                           '((inexpr-class-close)))
+                          (t syntax))
+                  syntax)
+                c-hanging-braces-alist)
+               '(ignore before after)))) ; Default, when not in c-h-b-l.
+
+    ;; If syntax is a function symbol, then call it using the
+    ;; defined semantics.
+    (if (and (not (consp (cdr symb-newlines)))
+            (functionp (cdr symb-newlines)))
+       (let ((c-syntactic-context syntax))
+         (funcall (cdr symb-newlines)
+                  (car symb-newlines)
+                  (point)))
+      (cdr symb-newlines))))
+
+(defun c-try-one-liner ()
+  ;; Point is just after a newly inserted }.  If the non-whitespace
+  ;; content of the braces is a single line of code, compact the whole
+  ;; construct to a single line, if this line isn't too long.  The Right
+  ;; Thing is done with comments.
+  ;;
+  ;; Point will be left after the }, regardless of whether the clean-up is
+  ;; done.  Return NON-NIL if the clean-up happened, NIL if it didn't.
+
+  (let ((here (point))
+       (pos (- (point-max) (point)))
+       mbeg1 mend1 mbeg4 mend4
+       eol-col cmnt-pos cmnt-col cmnt-gap)
+
+    (when
+       (save-excursion
+         (save-restriction
+           ;; Avoid backtracking over a very large block.  The one we
+           ;; deal with here can never be more than three lines.
+           (narrow-to-region (save-excursion
+                               (forward-line -2)
+                               (point))
+                             (point))
+           (and (c-safe (c-backward-sexp))
+                (progn
+                  (forward-char)
+                  (narrow-to-region (point) (1- here)) ; innards of {.}
+                  (looking-at
+                   (cc-eval-when-compile
+                     (concat
+                      "\\("            ; (match-beginning 1)
+                      "[ \t]*\\([\r\n][ \t]*\\)?" ; WS with opt. NL
+                      "\\)"            ; (match-end 1)
+                      "[^ \t\r\n]+\\([ \t]+[^ \t\r\n]+\\)*" ; non-WS
+                      "\\("            ; (match-beginning 4)
+                      "[ \t]*\\([\r\n][ \t]*\\)?" ; WS with opt. NL
+                      "\\)\\'")))))))  ; (match-end 4) at EOB.
+
+      (if (c-tentative-buffer-changes
+           (setq mbeg1 (match-beginning 1) mend1 (match-end 1)
+                 mbeg4 (match-beginning 4) mend4 (match-end 4))
+           (backward-char)             ; back over the `}'
+           (save-excursion
+             (setq cmnt-pos (and (c-backward-single-comment)
+                                 (- (point) (- mend1 mbeg1)))))
+           (delete-region mbeg4 mend4)
+           (delete-region mbeg1 mend1)
+           (setq eol-col (save-excursion (end-of-line) (current-column)))
+
+           ;; Necessary to put the closing brace before any line
+           ;; oriented comment to keep it syntactically significant.
+           ;; This isn't necessary for block comments, but the result
+           ;; looks nicer anyway.
+           (when cmnt-pos
+             (delete-char 1)           ; the `}' has blundered into a comment
+             (goto-char cmnt-pos)
+             (setq cmnt-col (1+ (current-column)))
+             (setq cmnt-pos (1+ cmnt-pos)) ; we're inserting a `}'
+             (c-skip-ws-backward)
+             (insert-char ?\} 1)       ; reinsert the `}' before the comment.
+             (setq cmnt-gap (- cmnt-col (current-column)))
+             (when (zerop cmnt-gap)
+               (insert-char ?\  1)     ; Put a space before a bare comment.
+               (setq cmnt-gap 1)))
+
+           (or (null c-max-one-liner-length)
+               (zerop c-max-one-liner-length)
+               (<= eol-col c-max-one-liner-length)
+               ;; Can we trim space before comment to make the line fit?
+               (and cmnt-gap
+                    (< (- eol-col cmnt-gap) c-max-one-liner-length)
+                    (progn (goto-char cmnt-pos)
+                           (backward-delete-char-untabify
+                            (- eol-col c-max-one-liner-length))
+                           t))))
+         (goto-char (- (point-max) pos))))))
+
 (defun c-electric-brace (arg)
   "Insert a brace.
 
-If the auto-newline feature is turned on, as evidenced by the \"/a\"
-or \"/ah\" string on the mode line, newlines are inserted before and
-after braces based on the value of `c-hanging-braces-alist'.
+If `c-electric-flag' is non-nil, the brace is not inside a literal and a
+numeric ARG hasn't been supplied, the command performs several electric
+actions:
 
-Also, the line is re-indented unless a numeric ARG is supplied, the
-brace is inserted inside a literal, or `c-syntactic-indentation' is
-nil.
+\(a) If the auto-newline feature is turned on (indicated by \"/ln\" on
+the mode line) newlines are inserted before and after the brace as
+directed by the settings in `c-hanging-braces-alist'.
+
+\(b) Any auto-newlines are indented.  The original line is also
+reindented unless `c-syntactic-indentation' is nil.
+
+\(c) If auto-newline is turned on, various newline cleanups based on the
+settings of `c-cleanup-list' are done."
 
-This function does various newline cleanups based on the value of
-`c-cleanup-list'."
   (interactive "*P")
-  (let* ((safepos (c-safe-position (point) (c-parse-state)))
-        (literal (c-in-literal safepos))
-        ;; We want to inhibit blinking the paren since this will be
-        ;; most disruptive.  We'll blink it ourselves later on.
-        (old-blink-paren blink-paren-function)
-        blink-paren-function)
-    (cond
-     ((or literal arg)
-      (self-insert-command (prefix-numeric-value arg)))
-     ((not (looking-at "[ \t]*\\\\?$"))
-      (self-insert-command (prefix-numeric-value arg))
-      (if c-syntactic-indentation
-         (indent-according-to-mode)))
-     (t
-      (let* ((syms
-             ;; This is the list of brace syntactic symbols that can
-             ;; hang.  If any new ones are added to c-offsets-alist,
-             ;; they should be added here as well.
-             '(class-open class-close defun-open defun-close
-               inline-open inline-close
-               brace-list-open brace-list-close
-               brace-list-intro brace-entry-open
-               block-open block-close
-               substatement-open statement-case-open
-               extern-lang-open extern-lang-close
-               namespace-open namespace-close
-               module-open module-close
-                composition-open composition-close
-               inexpr-class-open inexpr-class-close
-               ;; `statement-cont' is here for the case with a brace
-               ;; list opener inside a statement.  C.f. CASE B.2 in
-               ;; `c-guess-continued-construct'.
-               statement-cont))
-            (insertion-point (point))
-            (preserve-p (and (not (bobp))
-                             (eq ?\  (char-syntax (char-before)))))
-            ;; shut this up too
-            (c-echo-syntactic-information-p nil)
-            delete-temp-newline syntax newlines)
-       ;; only insert a newline if there is non-whitespace behind us
-       (when (save-excursion
-               (skip-chars-backward " \t")
-               (not (bolp)))
-         (c-newline-and-indent)
-         ;; Set markers around the newline and indention inserted
-         ;; above.  We insert the start marker here and not before
-         ;; the call to kludge around a misfeature in expand-abbrev:
-         ;; If the line contains e.g. "else" then expand-abbrev will
-         ;; be called when c-newline-and-indent inserts the newline.
-         ;; That function first removes the abbrev "else" and then
-         ;; inserts the expansion, which is an identical "else" in
-         ;; this case.  So the marker that we put after "else" would
-         ;; end up before it.
-         (setq delete-temp-newline
-               (cons (save-excursion
-                       (end-of-line 0)
-                       (if (eq (char-before) ?\\)
-                           ;; Ignore a line continuation.
-                           (backward-char))
-                       (skip-chars-backward " \t")
-                       (copy-marker (point) t))
-                     (point-marker))))
-       (unwind-protect
-           (progn
-             (if (eq last-command-char ?{)
-                 (setq c-state-cache (cons (point) c-state-cache)))
-             (self-insert-command (prefix-numeric-value arg))
-             (c-save-buffer-state ((c-syntactic-indentation-in-macros t)
-                                   (c-auto-newline-analysis t))
-               ;; Turn on syntactic macro analysis to help with auto
-               ;; newlines only.
-               (setq syntax (c-guess-basic-syntax)))
-             (setq newlines
-                   (and
-                    c-auto-newline
-                    (or (c-lookup-lists
-                         syms
-                         ;; Substitute inexpr-class and class-open or
-                         ;; class-close with inexpr-class-open or
-                         ;; inexpr-class-close.
-                         (if (assq 'inexpr-class syntax)
-                             (cond ((assq 'class-open syntax)
-                                    '((inexpr-class-open)))
-                                   ((assq 'class-close syntax)
-                                    '((inexpr-class-close)))
-                                   (t syntax))
-                           syntax)
-                         c-hanging-braces-alist)
-                        '(ignore before after))))
-             ;; Do not try to insert newlines around a special
-             ;; (Pike-style) brace list.
-             (if (and c-special-brace-lists
-                      (save-excursion
-                        (c-save-buffer-state nil
-                          (c-safe (if (= (char-before) ?{)
-                                      (forward-char -1)
-                                    (c-forward-sexp -1))
-                                  (c-looking-at-special-brace-list)))))
-                 (setq newlines nil))
-             ;; If syntax is a function symbol, then call it using the
-             ;; defined semantics.
-             (if (and (not (consp (cdr newlines)))
-                      (functionp (cdr newlines)))
-                 (let ((c-syntactic-context syntax))
-                   (setq newlines
-                         (funcall (cdr newlines)
-                                  (car newlines)
-                                  insertion-point))))
-             ;; does a newline go before the open brace?
-             (when (memq 'before newlines)
-               ;; we leave the newline we've put in there before,
-               ;; but we need to re-indent the line above
-               (when delete-temp-newline
-                 (set-marker (car delete-temp-newline) nil)
-                 (set-marker (cdr delete-temp-newline) nil)
-                 (setq delete-temp-newline nil))
-               (when c-syntactic-indentation
-                 (let ((pos (- (point-max) (point)))
-                       (here (point)))
-                   (forward-line -1)
-                   (indent-according-to-mode)
-                   (goto-char (- (point-max) pos))
-                   ;; if the buffer has changed due to the
-                   ;; indentation, we need to recalculate syntax for
-                   ;; the current line.
-                   (if (/= (point) here)
-                       (c-save-buffer-state
-                           ((c-syntactic-indentation-in-macros t)
-                            (c-auto-newline-analysis t))
-                         ;; Turn on syntactic macro analysis to help
-                         ;; with auto newlines only.
-                         (setq syntax (c-guess-basic-syntax))))))))
-         ;; must remove the newline we just stuck in (if we really did it)
-         (when delete-temp-newline
-           (save-excursion
-             (delete-region (car delete-temp-newline)
-                            (cdr delete-temp-newline))
-             (goto-char (car delete-temp-newline))
-             (set-marker (car delete-temp-newline) nil)
-             (set-marker (cdr delete-temp-newline) nil)
-             ;; if there is whitespace before point, then preserve
-             ;; at least one space.
-             (just-one-space)
-             (if (not preserve-p)
-                 (delete-char -1)))))
-       (if (not (memq 'before newlines))
-           ;; since we're hanging the brace, we need to recalculate
-           ;; syntax.
-           (c-save-buffer-state ((c-syntactic-indentation-in-macros t)
-                                 (c-auto-newline-analysis t))
-             ;; Turn on syntactic macro analysis to help with auto
-             ;; newlines only.
-             (setq syntax (c-guess-basic-syntax))))
-       (when c-syntactic-indentation
-         ;; Now adjust the line's indentation.  Don't update the state
-         ;; cache since c-guess-basic-syntax isn't called when
-         ;; c-syntactic-context is set.
-         (let* ((c-syntactic-context syntax))
-           (indent-according-to-mode)))
-       ;; Do all appropriate clean ups
-       (let ((here (point))
-             (pos (- (point-max) (point)))
-             mbeg mend tmp)
-         ;; clean up empty defun braces
-         (if (and c-auto-newline
-                  (memq 'empty-defun-braces c-cleanup-list)
-                  (eq last-command-char ?\})
-                  (c-intersect-lists '(defun-close class-close inline-close)
-                                     syntax)
-                  (progn
-                    (forward-char -1)
-                    (c-skip-ws-backward)
-                    (eq (char-before) ?\{))
-                  ;; make sure matching open brace isn't in a comment
-                  (not (c-in-literal)))
-             (delete-region (point) (1- here)))
-         ;; clean up brace-else-brace and brace-elseif-brace
-         (when (and c-auto-newline
-                    (eq last-command-char ?\{))
-           (cond
-            ((and (memq 'brace-else-brace c-cleanup-list)
-                  (re-search-backward
-                   (concat "}"
-                           "\\([ \t\n]\\|\\\\\n\\)*"
-                           "else"
-                           "\\([ \t\n]\\|\\\\\n\\)*"
-                           "{")
-                   nil t)
-                  (progn
-                    (setq mbeg (match-beginning 0)
-                          mend (match-end 0))
-                    (eq (match-end 0) here)))
-             (delete-region mbeg mend)
-             (insert-and-inherit "} else {"))
-            ((and (memq 'brace-elseif-brace c-cleanup-list)
-                  (progn
-                    (goto-char (1- here))
-                    (setq mend (point))
-                    (c-skip-ws-backward)
-                    (setq mbeg (point))
-                    (eq (char-before) ?\)))
-                  (zerop (c-save-buffer-state nil (c-backward-token-2 1 t)))
-                  (eq (char-after) ?\()
-                  (progn
-                    (setq tmp (point))
-                    (re-search-backward
-                     (concat "}"
-                             "\\([ \t\n]\\|\\\\\n\\)*"
-                             "else"
-                             "\\([ \t\n]\\|\\\\\n\\)+"
-                             "if"
-                             "\\([ \t\n]\\|\\\\\n\\)*")
-                     nil t))
-                  (eq (match-end 0) tmp))
-             (delete-region mbeg mend)
-             (goto-char mbeg)
-             (insert ?\ ))))
-         (goto-char (- (point-max) pos))
-         )
-       ;; does a newline go after the brace?
-       (if (memq 'after newlines)
-           (c-newline-and-indent))
-       )))
+  (let (safepos literal
+       ;; We want to inhibit blinking the paren since this would be
+       ;; most disruptive.  We'll blink it ourselves later on.
+       (old-blink-paren blink-paren-function)
+       blink-paren-function)
+
+    (c-save-buffer-state ()
+      (setq safepos (c-safe-position (point) (c-parse-state))
+           literal (c-in-literal safepos)))
+
+    ;; Insert the brace.  Note that expand-abbrev might reindent
+    ;; the line here if there's a preceding "else" or something.
+    (self-insert-command (prefix-numeric-value arg))
+
+    (when (and c-electric-flag (not literal) (not arg))
+      (if (not (looking-at "[ \t]*\\\\?$"))
+         (if c-syntactic-indentation
+             (indent-according-to-mode))
+
+       (let ( ;; shut this up too
+             (c-echo-syntactic-information-p nil)
+             newlines
+             ln-syntax br-syntax syntax) ; Syntactic context of the original line,
+                       ; of the brace itself, of the line the brace ends up on.
+         (c-save-buffer-state ((c-syntactic-indentation-in-macros t)
+                               (c-auto-newline-analysis t))
+           (setq ln-syntax (c-guess-basic-syntax)))
+         (if c-syntactic-indentation
+             (c-indent-line ln-syntax))
+
+         (when c-auto-newline
+           (backward-char)
+           (setq br-syntax (c-point-syntax)
+                 newlines (c-brace-newlines br-syntax))
+
+           ;; Insert the BEFORE newline, if wanted, and reindent the newline.
+           (if (and (memq 'before newlines)
+                    (> (current-column) (current-indentation)))
+               (if c-syntactic-indentation
+                   ;; Only a plain newline for now - it's indented
+                   ;; after the cleanups when the line has its final
+                   ;; appearance.
+                   (newline)
+                 (c-newline-and-indent)))
+           (forward-char)
+
+           ;; `syntax' is the syntactic context of the line which ends up
+           ;; with the brace on it.
+           (setq syntax (if (memq 'before newlines) br-syntax ln-syntax))
+
+           ;; Do all appropriate clean ups
+           (let ((here (point))
+                 (pos (- (point-max) (point)))
+                 mbeg mend
+                 )
+
+             ;; `}': clean up empty defun braces
+             (when (c-save-buffer-state ()
+                     (and (memq 'empty-defun-braces c-cleanup-list)
+                          (eq last-command-char ?\})
+                          (c-intersect-lists '(defun-close class-close inline-close)
+                                             syntax)
+                          (progn
+                            (forward-char -1)
+                            (c-skip-ws-backward)
+                            (eq (char-before) ?\{))
+                          ;; make sure matching open brace isn't in a comment
+                          (not (c-in-literal))))
+               (delete-region (point) (1- here))
+               (setq here (- (point-max) pos)))
+             (goto-char here)
+
+             ;; `}': compact to a one-liner defun?
+             (save-match-data
+               (when
+                   (and (eq last-command-char ?\})
+                        (memq 'one-liner-defun c-cleanup-list)
+                        (c-intersect-lists '(defun-close) syntax)
+                        (c-try-one-liner))
+                 (setq here (- (point-max) pos))))
+
+             ;; `{': clean up brace-else-brace and brace-elseif-brace
+             (when (eq last-command-char ?\{)
+               (cond
+                ((and (memq 'brace-else-brace c-cleanup-list)
+                      (re-search-backward
+                       (concat "}"
+                               "\\([ \t\n]\\|\\\\\n\\)*"
+                               "else"
+                               "\\([ \t\n]\\|\\\\\n\\)*"
+                               "{"
+                               "\\=")
+                       nil t))
+                 (delete-region mbeg mend)
+                 (insert-and-inherit "} else {"))
+                ((and (memq 'brace-elseif-brace c-cleanup-list)
+                      (progn
+                        (goto-char (1- here))
+                        (setq mend (point))
+                        (c-skip-ws-backward)
+                        (setq mbeg (point))
+                        (eq (char-before) ?\)))
+                      (zerop (c-save-buffer-state nil (c-backward-token-2 1 t)))
+                      (eq (char-after) ?\()
+                     ; (progn
+                       ; (setq tmp (point))
+                        (re-search-backward
+                         (concat "}"
+                                 "\\([ \t\n]\\|\\\\\n\\)*"
+                                 "else"
+                                 "\\([ \t\n]\\|\\\\\n\\)+"
+                                 "if"
+                                 "\\([ \t\n]\\|\\\\\n\\)*"
+                                 "\\=")
+                         nil t);)
+                      ;(eq (match-end 0) tmp);
+                        )
+                 (delete-region mbeg mend)
+                 (goto-char mbeg)
+                 (insert ?\ ))))
+
+             (goto-char (- (point-max) pos))
+
+             ;; Indent the line after the cleanups since it might
+             ;; very well indent differently due to them, e.g. if
+             ;; c-indent-one-line-block is used together with the
+             ;; one-liner-defun cleanup.
+             (when c-syntactic-indentation
+               (c-indent-line)))
+
+           ;; does a newline go after the brace?
+           (if (memq 'after newlines)
+               (c-newline-and-indent))
+           ))))
+
     ;; blink the paren
     (and (eq last-command-char ?\})
         (not executing-kbd-macro)
@@ -659,332 +806,465 @@ This function does various newline cleanups based on the value of
 (defun c-electric-slash (arg)
   "Insert a slash character.
 
+If the slash is inserted immediately after the comment prefix in a c-style
+comment, the comment might get closed by removing whitespace and possibly
+inserting a \"*\".  See the variable `c-cleanup-list'.
+
 Indent the line as a comment, if:
 
-  1. The slash is second of a `//' line oriented comment introducing
+  1. The slash is second of a \"//\" line oriented comment introducing
      token and we are on a comment-only-line, or
 
-  2. The slash is part of a `*/' token that closes a block oriented
+  2. The slash is part of a \"*/\" token that closes a block oriented
      comment.
 
 If a numeric ARG is supplied, point is inside a literal, or
-`c-syntactic-indentation' is nil, indentation is inhibited."
+`c-syntactic-indentation' is nil or `c-electric-flag' is nil, indentation
+is inhibited."
   (interactive "*P")
-  (let* ((ch (char-before))
-        (literal (c-in-literal))
-        (indentp (and c-syntactic-indentation
-                      (not arg)
+  (let ((literal (c-save-buffer-state () (c-in-literal)))
+       indentp
+       ;; shut this up
+       (c-echo-syntactic-information-p nil))
+
+    ;; comment-close-slash cleanup?  This DOESN'T need `c-electric-flag' or
+    ;; `c-syntactic-indentation' set.
+    (when (and (not arg)
+              (eq literal 'c)
+              (memq 'comment-close-slash c-cleanup-list)
+              (eq last-command-char ?/)
+       ; (eq c-block-comment-ender "*/") ; C-style comments ALWAYS end in */
+              (save-excursion
+                (back-to-indentation)
+                (looking-at (concat c-current-comment-prefix "[ \t]*$"))))
+      (end-of-line)
+      (delete-horizontal-space)
+      (or (eq (char-before) ?*) (insert-char ?* 1))) ; Do I need a t (retain sticky properties) here?
+
+    (setq indentp (and (not arg)
+                      c-syntactic-indentation
+                      c-electric-flag
                       (eq last-command-char ?/)
-                      (or (and (eq ch ?/)
-                               (not literal))
-                          (and (eq ch ?*)
-                               literal))
-                      ))
-        ;; shut this up
-        (c-echo-syntactic-information-p nil))
+                      (eq (char-before) (if literal ?* ?/))))
     (self-insert-command (prefix-numeric-value arg))
     (if indentp
        (indent-according-to-mode))))
 
 (defun c-electric-star (arg)
   "Insert a star character.
-If the star is the second character of a C style comment introducing
-construct, and we are on a comment-only-line, indent line as comment.
-If a numeric ARG is supplied, point is inside a literal, or
-`c-syntactic-indentation' is nil, indentation is inhibited."
+If `c-electric-flag' and `c-syntactic-indentation' are both non-nil, and
+the star is the second character of a C style comment starter on a
+comment-only-line, indent the line as a comment.  If a numeric ARG is
+supplied, point is inside a literal, or `c-syntactic-indentation' is nil,
+this indentation is inhibited."
+
   (interactive "*P")
   (self-insert-command (prefix-numeric-value arg))
-  ;; if we are in a literal, or if arg is given do not re-indent the
+  ;; if we are in a literal, or if arg is given do not reindent the
   ;; current line, unless this star introduces a comment-only line.
-  (if (and c-syntactic-indentation
-          (not arg)
-          (eq (c-in-literal) 'c)
-          (eq (char-before) ?*)
-          (save-excursion
-            (forward-char -1)
-            (skip-chars-backward "*")
-            (if (eq (char-before) ?/)
-                (forward-char -1))
-            (skip-chars-backward " \t")
-            (bolp)))
+  (if (c-save-buffer-state ()
+       (and c-syntactic-indentation
+            c-electric-flag
+            (not arg)
+            (eq (c-in-literal) 'c)
+            (eq (char-before) ?*)
+            (save-excursion
+              (forward-char -1)
+              (skip-chars-backward "*")
+              (if (eq (char-before) ?/)
+                  (forward-char -1))
+              (skip-chars-backward " \t")
+              (bolp))))
       (let (c-echo-syntactic-information-p) ; shut this up
        (indent-according-to-mode))
     ))
 
 (defun c-electric-semi&comma (arg)
   "Insert a comma or semicolon.
-When the auto-newline feature is turned on, as evidenced by the \"/a\"
-or \"/ah\" string on the mode line, a newline might be inserted.  See
-the variable `c-hanging-semi&comma-criteria' for how newline insertion
-is determined.
 
-When a semicolon is inserted, the line is re-indented unless a numeric
-arg is supplied, point is inside a literal, or
-`c-syntactic-indentation' is nil.
+If `c-electric-flag' is non-nil, point isn't inside a literal and a
+numeric ARG hasn't been supplied, the command performs several electric
+actions:
+
+\(a) When the auto-newline feature is turned on (indicated by \"/ln\" on
+the mode line) a newline might be inserted.  See the variable
+`c-hanging-semi&comma-criteria' for how newline insertion is determined.
 
-Based on the value of `c-cleanup-list', this function cleans up commas
-following brace lists and semicolons following defuns."
+\(b) Any auto-newlines are indented.  The original line is also
+reindented unless `c-syntactic-indentation' is nil.
+
+\(c) If auto-newline is turned on, a comma following a brace list or a
+semicolon following a defun might be cleaned up, depending on the
+settings of `c-cleanup-list'."
   (interactive "*P")
-  (let* ((lim (c-most-enclosing-brace (c-parse-state)))
-        (literal (c-in-literal lim))
+  (let* (lim literal c-syntactic-context
         (here (point))
         ;; shut this up
         (c-echo-syntactic-information-p nil))
-    (if (or literal arg)
-       (self-insert-command (prefix-numeric-value arg))
-      ;; do some special stuff with the character
-      (self-insert-command (prefix-numeric-value arg))
-      ;; do all cleanups and newline insertions if c-auto-newline is
-      ;; turned on
-      (if (or (not c-auto-newline)
-             (not (looking-at "[ \t]*\\\\?$")))
-         (if c-syntactic-indentation
-             (indent-according-to-mode))
-       ;; clean ups
-       (let ((pos (- (point-max) (point))))
-         (if (and (or (and
-                       (eq last-command-char ?,)
-                       (memq 'list-close-comma c-cleanup-list))
-                      (and
-                       (eq last-command-char ?\;)
-                       (memq 'defun-close-semi c-cleanup-list)))
-                  (progn
-                    (forward-char -1)
-                    (c-skip-ws-backward)
-                    (eq (char-before) ?}))
-                  ;; make sure matching open brace isn't in a comment
-                  (not (c-in-literal lim)))
-             (delete-region (point) here))
-         (goto-char (- (point-max) pos)))
-       ;; re-indent line
-       (if c-syntactic-indentation
-           (indent-according-to-mode))
-       ;; check to see if a newline should be added
-       (let ((criteria c-hanging-semi&comma-criteria)
-             answer add-newline-p)
-         (while criteria
-           (setq answer (funcall (car criteria)))
-           ;; only nil value means continue checking
-           (if (not answer)
-               (setq criteria (cdr criteria))
-             (setq criteria nil)
-             ;; only 'stop specifically says do not add a newline
-             (setq add-newline-p (not (eq answer 'stop)))
-             ))
-         (if add-newline-p
-             (c-newline-and-indent))
-         )))))
+
+    (c-save-buffer-state ()
+      (setq lim (c-most-enclosing-brace (c-parse-state))
+           literal (c-in-literal lim)))
+
+    (self-insert-command (prefix-numeric-value arg))
+
+    (if (and c-electric-flag (not literal) (not arg))
+       ;; do all cleanups and newline insertions if c-auto-newline is on.
+       (if (or (not c-auto-newline)
+               (not (looking-at "[ \t]*\\\\?$")))
+           (if c-syntactic-indentation
+               (c-indent-line))
+         ;; clean ups: list-close-comma or defun-close-semi
+         (let ((pos (- (point-max) (point))))
+           (if (c-save-buffer-state ()
+                 (and (or (and
+                           (eq last-command-char ?,)
+                           (memq 'list-close-comma c-cleanup-list))
+                          (and
+                           (eq last-command-char ?\;)
+                           (memq 'defun-close-semi c-cleanup-list)))
+                      (progn
+                        (forward-char -1)
+                        (c-skip-ws-backward)
+                        (eq (char-before) ?}))
+                      ;; make sure matching open brace isn't in a comment
+                      (not (c-in-literal lim))))
+               (delete-region (point) here))
+           (goto-char (- (point-max) pos)))
+         ;; reindent line
+         (when c-syntactic-indentation
+           (setq c-syntactic-context (c-guess-basic-syntax))
+           (c-indent-line c-syntactic-context))
+         ;; check to see if a newline should be added
+         (let ((criteria c-hanging-semi&comma-criteria)
+               answer add-newline-p)
+           (while criteria
+             (setq answer (funcall (car criteria)))
+             ;; only nil value means continue checking
+             (if (not answer)
+                 (setq criteria (cdr criteria))
+               (setq criteria nil)
+               ;; only 'stop specifically says do not add a newline
+               (setq add-newline-p (not (eq answer 'stop)))
+               ))
+           (if add-newline-p
+               (c-newline-and-indent))
+           )))))
 
 (defun c-electric-colon (arg)
   "Insert a colon.
 
-If the auto-newline feature is turned on, as evidenced by the \"/a\"
-or \"/ah\" string on the mode line, newlines are inserted before and
-after colons based on the value of `c-hanging-colons-alist'.
+If `c-electric-flag' is non-nil, the colon is not inside a literal and a
+numeric ARG hasn't been supplied, the command performs several electric
+actions:
+
+\(a) If the auto-newline feature is turned on (indicated by \"/ln\" on
+the mode line) newlines are inserted before and after the colon based on
+the settings in `c-hanging-colons-alist'.
 
-Also, the line is re-indented unless a numeric ARG is supplied, the
-colon is inserted inside a literal, or `c-syntactic-indentation' is
-nil.
+\(b) Any auto-newlines are indented.  The original line is also
+reindented unless `c-syntactic-indentation' is nil.
+
+\(c) If auto-newline is turned on, whitespace between two colons will be
+\"cleaned up\" leaving a scope operator, if this action is set in
+`c-cleanup-list'."
 
-This function cleans up double colon scope operators based on the
-value of `c-cleanup-list'."
   (interactive "*P")
   (let* ((bod (c-point 'bod))
-        (literal (c-in-literal bod))
+        (literal (c-save-buffer-state () (c-in-literal bod)))
         newlines is-scope-op
         ;; shut this up
         (c-echo-syntactic-information-p nil))
-    (cond
-     ((or literal arg)
-      (self-insert-command (prefix-numeric-value arg)))
-     ((not (looking-at "[ \t]*\\\\?$"))
-      (self-insert-command (prefix-numeric-value arg))
-      (if c-syntactic-indentation
-         (indent-according-to-mode)))
-     (t
-      ;; insert the colon, then do any specified cleanups
-      (self-insert-command (prefix-numeric-value arg))
-      (let ((pos (- (point-max) (point)))
-           (here (point)))
-       (if (and c-auto-newline
-                (memq 'scope-operator c-cleanup-list)
-                (eq (char-before) ?:)
-                (progn
-                  (forward-char -1)
-                  (c-skip-ws-backward)
-                  (eq (char-before) ?:))
-                (not (c-in-literal))
-                (not (eq (char-after (- (point) 2)) ?:)))
-           (progn
-             (delete-region (point) (1- here))
-             (setq is-scope-op t)))
-       (goto-char (- (point-max) pos)))
-      ;; indent the current line if it's done syntactically.
-      (if c-syntactic-indentation
-         ;; Cannot use the same syntax analysis as we find below,
-         ;; since that's made with c-syntactic-indentation-in-macros
-         ;; always set to t.
-         (indent-according-to-mode))
-      (c-save-buffer-state
-           ((c-syntactic-indentation-in-macros t)
-            (c-auto-newline-analysis t)
-            ;; Turn on syntactic macro analysis to help with auto newlines
-            ;; only.
-            (syntax (c-guess-basic-syntax))
-            (elem syntax))
-       ;; Translate substatement-label to label for this operation.
-       (while elem
-         (if (eq (car (car elem)) 'substatement-label)
-             (setcar (car elem) 'label))
-         (setq elem (cdr elem)))
-       ;; some language elements can only be determined by checking
-       ;; the following line.  Lets first look for ones that can be
-       ;; found when looking on the line with the colon
-       (setq newlines
-             (and c-auto-newline
-                  (or (c-lookup-lists '(case-label label access-label)
-                                      syntax c-hanging-colons-alist)
-                      (c-lookup-lists '(member-init-intro inher-intro)
-                                      (progn
-                                        (insert ?\n)
-                                        (unwind-protect
-                                            (c-guess-basic-syntax)
-                                          (delete-char -1)))
-                                      c-hanging-colons-alist)))))
-      ;; does a newline go before the colon?  Watch out for already
-      ;; non-hung colons.  However, we don't unhang them because that
-      ;; would be a cleanup (and anti-social).
-      (if (and (memq 'before newlines)
-              (not is-scope-op)
-              (save-excursion
-                (skip-chars-backward ": \t")
-                (not (bolp))))
-         (let ((pos (- (point-max) (point))))
-           (forward-char -1)
-           (c-newline-and-indent)
-           (goto-char (- (point-max) pos))))
-      ;; does a newline go after the colon?
-      (if (and (memq 'after (cdr-safe newlines))
-              (not is-scope-op))
-         (c-newline-and-indent))
-      ))))
+    (self-insert-command (prefix-numeric-value arg))
+    ;; Any electric action?
+    (if (and c-electric-flag (not literal) (not arg))
+       ;; Unless we're at EOL, only re-indentation happens.
+       (if (not (looking-at "[ \t]*\\\\?$"))
+           (if c-syntactic-indentation
+               (indent-according-to-mode))
+
+         ;; scope-operator clean-up?
+         (let ((pos (- (point-max) (point)))
+               (here (point)))
+           (if (c-save-buffer-state () ; Why do we need this? [ACM, 2003-03-12]
+                 (and c-auto-newline
+                      (memq 'scope-operator c-cleanup-list)
+                      (eq (char-before) ?:)
+                      (progn
+                        (forward-char -1)
+                        (c-skip-ws-backward)
+                        (eq (char-before) ?:))
+                      (not (c-in-literal))
+                      (not (eq (char-after (- (point) 2)) ?:))))
+               (progn
+                 (delete-region (point) (1- here))
+                 (setq is-scope-op t)))
+           (goto-char (- (point-max) pos)))
+
+         ;; indent the current line if it's done syntactically.
+         (if c-syntactic-indentation
+             ;; Cannot use the same syntax analysis as we find below,
+             ;; since that's made with c-syntactic-indentation-in-macros
+             ;; always set to t.
+             (indent-according-to-mode))
+
+         ;; Calculate where, if anywhere, we want newlines.
+         (c-save-buffer-state
+             ((c-syntactic-indentation-in-macros t)
+              (c-auto-newline-analysis t)
+              ;; Turn on syntactic macro analysis to help with auto newlines
+              ;; only.
+              (syntax (c-guess-basic-syntax))
+              (elem syntax))
+           ;; Translate substatement-label to label for this operation.
+           (while elem
+             (if (eq (car (car elem)) 'substatement-label)
+                 (setcar (car elem) 'label))
+             (setq elem (cdr elem)))
+           ;; some language elements can only be determined by checking
+           ;; the following line.  Lets first look for ones that can be
+           ;; found when looking on the line with the colon
+           (setq newlines
+                 (and c-auto-newline
+                      (or (c-lookup-lists '(case-label label access-label)
+                                          syntax c-hanging-colons-alist)
+                          (c-lookup-lists '(member-init-intro inher-intro)
+                                          (progn
+                                            (insert ?\n)
+                                            (unwind-protect
+                                                (c-guess-basic-syntax)
+                                              (delete-char -1)))
+                                          c-hanging-colons-alist)))))
+         ;; does a newline go before the colon?  Watch out for already
+         ;; non-hung colons.  However, we don't unhang them because that
+         ;; would be a cleanup (and anti-social).
+         (if (and (memq 'before newlines)
+                  (not is-scope-op)
+                  (save-excursion
+                    (skip-chars-backward ": \t")
+                    (not (bolp))))
+             (let ((pos (- (point-max) (point))))
+               (forward-char -1)
+               (c-newline-and-indent)
+               (goto-char (- (point-max) pos))))
+         ;; does a newline go after the colon?
+         (if (and (memq 'after (cdr-safe newlines))
+                  (not is-scope-op))
+             (c-newline-and-indent))
+         ))))
 
 (defun c-electric-lt-gt (arg)
-  "Insert a less-than, or greater-than character.
-The line will be re-indented if the character inserted is the second
-of a C++ style stream operator and the buffer is in C++ mode.
-Exceptions are when a numeric argument is supplied, point is inside a
-literal, or `c-syntactic-indentation' is nil, in which case the line
-will not be re-indented."
+  "Insert a \"<\" or \">\" character.
+If the current language uses angle bracket parens (e.g. template
+arguments in C++), try to find out if the inserted character is a
+paren and give it paren syntax if appropriate.
+
+If `c-electric-flag' and `c-syntactic-indentation' are both non-nil, the
+line will be reindented if the inserted character is a paren or if it
+finishes a C++ style stream operator in C++ mode.  Exceptions are when a
+numeric argument is supplied, or the point is inside a literal."
+
   (interactive "*P")
-  (let ((indentp (and c-syntactic-indentation
-                     (not arg)
-                     (eq (char-before) last-command-char)
-                     (not (c-in-literal))))
-       ;; shut this up
-       (c-echo-syntactic-information-p nil))
+  (let ((c-echo-syntactic-information-p nil)
+       final-pos close-paren-inserted)
+
     (self-insert-command (prefix-numeric-value arg))
-    (if indentp
-       (indent-according-to-mode))))
+    (setq final-pos (point))
+
+    (c-save-buffer-state (c-parse-and-markup-<>-arglists
+                         c-restricted-<>-arglists
+                         <-pos)
+
+      (when c-recognize-<>-arglists
+       (if (eq last-command-char ?<)
+           (when (and (progn
+                        (backward-char)
+                        (= (point)
+                           (progn
+                             (c-beginning-of-current-token)
+                             (point))))
+                      (progn
+                        (c-backward-token-2)
+                        (looking-at c-opt-<>-sexp-key)))
+             (c-mark-<-as-paren (1- final-pos)))
+
+         ;; It's a ">".  Check if there's an earlier "<" which either has
+         ;; open paren syntax already or that can be recognized as an arglist
+         ;; together with this ">".  Note that this won't work in cases like
+         ;; "template <x, a < b, y>" but they ought to be rare.
+
+         (save-restriction
+           ;; Narrow to avoid that `c-forward-<>-arglist' below searches past
+           ;; our position.
+           (narrow-to-region (point-min) final-pos)
+
+           (while (and
+                   (progn
+                     (goto-char final-pos)
+                     (c-syntactic-skip-backward "^<;}" nil t)
+                     (eq (char-before) ?<))
+                   (progn
+                     (backward-char)
+                     ;; If the "<" already got open paren syntax we know we
+                     ;; have the matching closer.  Handle it and exit the
+                     ;; loop.
+                     (if (looking-at "\\s\(")
+                         (progn
+                           (c-mark->-as-paren (1- final-pos))
+                           (setq close-paren-inserted t)
+                           nil)
+                       t))
+
+                   (progn
+                     (setq <-pos (point))
+                     (c-backward-syntactic-ws)
+                     (c-simple-skip-symbol-backward))
+                   (or (looking-at c-opt-<>-sexp-key)
+                       (not (looking-at c-keywords-regexp)))
+
+                   (let ((c-parse-and-markup-<>-arglists t)
+                         c-restricted-<>-arglists
+                         (containing-sexp
+                          (c-most-enclosing-brace (c-parse-state))))
+                     (when (and containing-sexp
+                                (progn (goto-char containing-sexp)
+                                       (eq (char-after) ?\())
+                                (not (eq (get-text-property (point) 'c-type)
+                                         'c-decl-arg-start)))
+                       (setq c-restricted-<>-arglists t))
+                     (goto-char <-pos)
+                     (c-forward-<>-arglist nil))
+
+                   ;; Loop here if the "<" we found above belongs to a nested
+                   ;; angle bracket sexp.  When we start over we'll find the
+                   ;; previous or surrounding sexp.
+                   (if (< (point) final-pos)
+                       t
+                     (setq close-paren-inserted t)
+                     nil)))))))
+    (goto-char final-pos)
+
+    ;; Indent the line if appropriate.
+    (when (and c-electric-flag c-syntactic-indentation)
+      (backward-char)
+      (when (prog1 (or (looking-at "\\s\(\\|\\s\)")
+                      (and (c-major-mode-is 'c++-mode)
+                           (progn
+                             (c-beginning-of-current-token)
+                             (looking-at "<<\\|>>"))
+                           (= (match-end 0) final-pos)))
+             (goto-char final-pos))
+       (indent-according-to-mode)))
+
+    (when (and close-paren-inserted
+              (not executing-kbd-macro)
+              blink-paren-function)
+      ;; Note: Most paren blink functions, such as the standard
+      ;; `blink-matching-open', currently doesn't handle paren chars
+      ;; marked with text properties very well.  Maybe we should avoid
+      ;; this call for the time being?
+      (funcall blink-paren-function))))
 
 (defun c-electric-paren (arg)
   "Insert a parenthesis.
 
-Some newline cleanups are done if appropriate; see the variable
-`c-cleanup-list'.
+If `c-syntactic-indentation' and `c-electric-flag' are both non-nil, the
+line is reindented unless a numeric ARG is supplied, or the parenthesis
+is inserted inside a literal.
 
-Also, the line is re-indented unless a numeric ARG is supplied, the
-parenthesis is inserted inside a literal, or `c-syntactic-indentation'
-is nil."
+Whitespace between a function name and the parenthesis may get added or
+removed; see the variable `c-cleanup-list'.
+
+Also, if `c-electric-flag' and `c-auto-newline' are both non-nil, some
+newline cleanups are done if appropriate; see the variable `c-cleanup-list'."
   (interactive "*P")
-  (let ((literal (c-in-literal (c-point 'bod)))
+  (let ((literal (c-save-buffer-state () (c-in-literal)))
        ;; shut this up
        (c-echo-syntactic-information-p nil))
-    (if (or arg literal)
-       (self-insert-command (prefix-numeric-value arg))
-      ;; do some special stuff with the character
-      (let* (;; We want to inhibit blinking the paren since this will
-            ;; be most disruptive.  We'll blink it ourselves
-            ;; afterwards.
-            (old-blink-paren blink-paren-function)
-            blink-paren-function
-            (noblink (eq last-input-event ?\()))
-       (self-insert-command (prefix-numeric-value arg))
-       (if c-syntactic-indentation
-           (indent-according-to-mode))
-       (when (looking-at "[ \t]*\\\\?$")
-         (when c-auto-newline
-           ;; Do all appropriate clean ups
-           (let ((here (point))
-                 (pos (- (point-max) (point)))
-                 mbeg mend)
-             ;; clean up brace-elseif-brace
-             (if (and (memq 'brace-elseif-brace c-cleanup-list)
-                      (eq last-command-char ?\()
-                      (re-search-backward
-                       (concat "}"
-                               "\\([ \t\n]\\|\\\\\n\\)*"
-                               "else"
-                               "\\([ \t\n]\\|\\\\\n\\)+"
-                               "if"
-                               "\\([ \t\n]\\|\\\\\n\\)*"
-                               "(")
-                       nil t)
-                      (save-excursion
-                        (setq mbeg (match-beginning 0)
-                              mend (match-end 0))
-                        (= mend here))
-                      (not (c-in-literal)))
-                 (progn
-                   (delete-region mbeg mend)
-                   (insert-and-inherit "} else if ("))
-               ;; clean up brace-catch-brace
-               (goto-char here)
-               (if (and (memq 'brace-catch-brace c-cleanup-list)
-                        (eq last-command-char ?\()
-                        (re-search-backward
-                         (concat "}"
-                                 "\\([ \t\n]\\|\\\\\n\\)*"
-                                 "catch"
-                                 "\\([ \t\n]\\|\\\\\n\\)*"
-                                 "(")
-                         nil t)
-                        (save-excursion
-                          (setq mbeg (match-beginning 0)
-                                mend (match-end 0))
-                          (= mend here))
-                        (not (c-in-literal)))
-                   (progn
-                     (delete-region mbeg mend)
-                     (insert-and-inherit "} catch ("))))
-             (goto-char (- (point-max) pos))
-             )))
-       (let (beg (end (1- (point))))
-         (cond ((and (memq 'space-before-funcall c-cleanup-list)
-                     (eq last-command-char ?\()
-                     (save-excursion
-                       (backward-char)
-                       (skip-chars-backward " \t")
-                       (setq beg (point))
-                       (c-on-identifier)))
-                (save-excursion
-                  (delete-region beg end)
-                  (goto-char beg)
-                  (insert ?\ )))
-               ((and (memq 'compact-empty-funcall c-cleanup-list)
-                     (eq last-command-char ?\))
-                     (save-excursion
-                       (c-safe (backward-char 2))
-                       (when (looking-at "()")
-                         (setq end (point))
-                         (skip-chars-backward " \t")
-                         (setq beg (point))
-                         (c-on-identifier))))
-                (delete-region beg end))))
-       (and (not executing-kbd-macro)
-            old-blink-paren
-            (not noblink)
-            (funcall old-blink-paren))))))
+    (self-insert-command (prefix-numeric-value arg))
+
+    (if (and (not arg) (not literal))
+       (let* ( ;; We want to inhibit blinking the paren since this will
+              ;; be most disruptive.  We'll blink it ourselves
+              ;; afterwards.
+              (old-blink-paren blink-paren-function)
+              blink-paren-function)
+         (if (and c-syntactic-indentation c-electric-flag)
+             (indent-according-to-mode))
+
+         ;; If we're at EOL, check for new-line clean-ups.
+         (when (and c-electric-flag c-auto-newline
+                    (looking-at "[ \t]*\\\\?$"))
+
+           ;; clean up brace-elseif-brace
+           (when
+               (and (memq 'brace-elseif-brace c-cleanup-list)
+                    (eq last-command-char ?\()
+                    (re-search-backward
+                     (concat "}"
+                             "\\([ \t\n]\\|\\\\\n\\)*"
+                             "else"
+                             "\\([ \t\n]\\|\\\\\n\\)+"
+                             "if"
+                             "\\([ \t\n]\\|\\\\\n\\)*"
+                             "("
+                             "\\=")
+                     nil t)
+                    (not  (c-save-buffer-state () (c-in-literal))))
+             (delete-region (match-beginning 0) (match-end 0))
+             (insert-and-inherit "} else if ("))
+
+           ;; clean up brace-catch-brace
+           (when
+               (and (memq 'brace-catch-brace c-cleanup-list)
+                    (eq last-command-char ?\()
+                    (re-search-backward
+                     (concat "}"
+                             "\\([ \t\n]\\|\\\\\n\\)*"
+                             "catch"
+                             "\\([ \t\n]\\|\\\\\n\\)*"
+                             "("
+                             "\\=")
+                     nil t)
+                    (not  (c-save-buffer-state () (c-in-literal))))
+             (delete-region (match-beginning 0) (match-end 0))
+             (insert-and-inherit "} catch (")))
+
+         ;; Check for clean-ups at function calls.  These two DON'T need
+         ;; `c-electric-flag' or `c-syntactic-indentation' set.
+         ;; Point is currently just after the inserted paren.
+         (let (beg (end (1- (point))))
+           (cond
+
+            ;; space-before-funcall clean-up?
+            ((and (memq 'space-before-funcall c-cleanup-list)
+                  (eq last-command-char ?\()
+                  (save-excursion
+                    (backward-char)
+                    (skip-chars-backward " \t")
+                    (setq beg (point))
+                    (c-save-buffer-state () (c-on-identifier))))
+             (save-excursion
+               (delete-region beg end)
+               (goto-char beg)
+               (insert ?\ )))
+
+            ;; compact-empty-funcall clean-up?
+                 ((c-save-buffer-state ()
+                    (and (memq 'compact-empty-funcall c-cleanup-list)
+                         (eq last-command-char ?\))
+                         (save-excursion
+                           (c-safe (backward-char 2))
+                           (when (looking-at "()")
+                             (setq end (point))
+                             (skip-chars-backward " \t")
+                             (setq beg (point))
+                             (c-on-identifier)))))
+                  (delete-region beg end))))
+         (and (eq last-input-event ?\))
+              (not executing-kbd-macro)
+              old-blink-paren
+              (funcall old-blink-paren))))))
 
 (defun c-electric-continued-statement ()
   "Reindent the current line if appropriate.
@@ -995,16 +1275,18 @@ continues an earlier statement is typed, e.g. an \"else\" or the
 
 The line is reindented if there is nothing but whitespace before the
 keyword on the line, the keyword is not inserted inside a literal, and
-`c-syntactic-indentation' is non-nil."
+`c-electric-flag' and `c-syntactic-indentation' are both non-nil."
   (let (;; shut this up
        (c-echo-syntactic-information-p nil))
-    (when (and c-syntactic-indentation
-              (not (eq last-command-char ?_))
-              (= (save-excursion
-                   (skip-syntax-backward "w")
-                   (point))
-                 (c-point 'boi))
-              (not (c-in-literal (c-point 'bod))))
+    (when (c-save-buffer-state ()
+           (and c-electric-flag
+                c-syntactic-indentation
+                (not (eq last-command-char ?_))
+                (= (save-excursion
+                     (skip-syntax-backward "w")
+                     (point))
+                   (c-point 'boi))
+                (not (c-in-literal (c-point 'bod)))))
       ;; Have to temporarily insert a space so that
       ;; c-guess-basic-syntax recognizes the keyword.  Follow the
       ;; space with a nonspace to avoid messing up any whitespace
@@ -1016,36 +1298,19 @@ keyword on the line, the keyword is not inserted inside a literal, and
        (delete-char -2)))))
 
 \f
-;; better movement routines for ThisStyleOfVariablesCommonInCPlusPlus
-;; originally contributed by Terry_Glanfield.Southern@rxuk.xerox.com
 (defun c-forward-into-nomenclature (&optional arg)
-  "Move forward to end of a nomenclature section or word.
-With arg, do it arg times."
+  "Compatibility alias for `c-forward-subword'."
   (interactive "p")
-  (let ((case-fold-search nil))
-    (if (> arg 0)
-       (re-search-forward
-        (cc-eval-when-compile
-          (concat "\\W*\\([" c-upper "]*[" c-lower c-digit "]*\\)"))
-        (point-max) t arg)
-      (while (and (< arg 0)
-                 (re-search-backward
-                  (cc-eval-when-compile
-                    (concat
-                     "\\(\\(\\W\\|[" c-lower c-digit "]\\)[" c-upper "]+"
-                     "\\|\\W\\w+\\)"))
-                  (point-min) 0))
-       (forward-char 1)
-       (setq arg (1+ arg)))))
-  (c-keep-region-active))
+  (require 'cc-subword)
+  (c-forward-subword arg))
+(make-obsolete 'c-forward-into-nomenclature 'c-forward-subword)
 
 (defun c-backward-into-nomenclature (&optional arg)
-  "Move backward to beginning of a nomenclature section or word.
-With optional ARG, move that many times.  If ARG is negative, move
-forward."
+  "Compatibility alias for `c-backward-subword'."
   (interactive "p")
-  (c-forward-into-nomenclature (- arg))
-  (c-keep-region-active))
+  (require 'cc-subword)
+  (c-backward-subword arg))
+(make-obsolete 'c-backward-into-nomenclature 'c-backward-subword)
 
 (defun c-scope-operator ()
   "Insert a double colon scope operator at point.
@@ -1246,6 +1511,8 @@ the open-parenthesis that starts a defun; see `beginning-of-defun'."
   ;; following one is chosen instead (if there is any).  The end
   ;; position is at the next line, providing there is one before the
   ;; declaration.
+  ;;
+  ;; This function might do hidden buffer changes.
   (save-excursion
 
     ;; Note: Some code duplication in `c-beginning-of-defun' and
@@ -1369,6 +1636,604 @@ function does not require the declaration to contain a brace block."
       (push-mark (cdr decl-limits) nil t))))
 
 \f
+(defun c-in-comment-line-prefix-p ()
+  ;; Point is within a comment.  Is it also within a comment-prefix?
+  ;; Space at BOL which precedes a comment-prefix counts as part of it.
+  ;;
+  ;; This function might do hidden buffer changes.
+  (let ((here (point)))
+    (save-excursion
+      (beginning-of-line)
+      (skip-chars-forward " \t")
+      (and (looking-at c-current-comment-prefix)
+          (/= (match-beginning 0) (match-end 0))
+          (< here (match-end 0))))))
+
+(defun c-narrow-to-comment-innards (range)
+  ;; Narrow to the "inside" of the comment (block) defined by range, as
+  ;; follows:
+  ;; 
+  ;; A c-style block comment has its opening "/*" and its closing "*/" (if
+  ;; present) removed.  A c++-style line comment retains its opening "//" but
+  ;; has any final NL removed.  If POINT is currently outwith these innards,
+  ;; move it to the appropriate boundary.
+  ;; 
+  ;; This narrowing simplifies the sentence movement functions, since it
+  ;; eliminates awkward things at the boundaries of the comment (block).
+  ;;
+  ;; This function might do hidden buffer changes.
+  (let* ((lit-type (c-literal-type range))
+        (beg (if (eq lit-type 'c) (+ (car range) 2) (car range)))
+        (end (if (eq lit-type 'c)
+                 (if (and (eq (char-before (cdr range)) ?/)
+                          (eq (char-before (1- (cdr range))) ?*))
+                     (- (cdr range) 2)
+                   (point-max))
+               (if (eq (cdr range) (point-max))
+                   (point-max)
+                 (- (cdr range) 1)))))
+    (if (> (point) end)
+       (goto-char end))                ; This would be done automatically by ...
+    (if (< (point) beg)
+       (goto-char beg))        ;  ... narrow-to-region but is not documented.
+    (narrow-to-region beg end)))
+
+(defun c-beginning-of-sentence-in-comment (range)
+  ;; Move backwards to the "beginning of a sentence" within the comment
+  ;; defined by RANGE, a cons of its starting and ending positions.  If we
+  ;; find a BOS, return NIL.  Otherwise, move point to just before the start
+  ;; of the comment and return T.
+  ;;
+  ;; The BOS is either text which follows a regexp match of sentence-end,
+  ;; or text which is a beginning of "paragraph".  
+  ;; Comment-prefixes are treated like WS when calculating BOSes or BOPs.
+  ;;
+  ;; This code was adapted from GNU Emacs's forward-sentence in paragraphs.el.
+  ;; It is not a general function, but is intended only for calling from
+  ;; c-move-over-sentence.  Not all preconditions have been explicitly stated.
+  ;;
+  ;; This function might do hidden buffer changes.
+  (save-match-data
+    (let ((start-point (point)))
+      (save-restriction
+       (c-narrow-to-comment-innards range) ; This may move point back.
+       (let* ((here (point))
+              last
+              (here-filler        ; matches WS and comment-prefices at point.
+               (concat "\\=\\(^[ \t]*\\(" c-current-comment-prefix "\\)"
+                       "\\|[ \t\n\r\f]\\)*"))
+              (prefix-at-bol-here ; matches WS and prefix at BOL, just before point
+               (concat "^[ \t]*\\(" c-current-comment-prefix "\\)[ \t\n\r\f]*\\="))
+              ;; First, find the previous paragraph start, if any.
+              (par-beg ; point where non-WS/non-prefix text of paragraph starts.
+               (save-excursion
+                 (forward-paragraph -1) ; uses cc-mode values of
+                                       ; paragraph-\(start\|separate\)
+                 (if (> (re-search-forward here-filler nil t) here)
+                     (goto-char here))
+                 (when (>= (point) here)
+                   (forward-paragraph -2)
+                   (if (> (re-search-forward here-filler nil t) here)
+                       (goto-char here)))
+                 (point))))
+
+         ;; Now seek successively earlier sentence ends between PAR-BEG and
+         ;; HERE, until the "start of sentence" following it is earlier than
+         ;; HERE, or we hit PAR-BEG.  Beware of comment prefices!
+         (while (and (re-search-backward (c-sentence-end) par-beg 'limit)
+                     (setq last (point))
+                     (goto-char (match-end 0)) ; tentative beginning of sentence
+                     (or (>= (point) here)
+                         (and (not (bolp)) ; Found a non-blank comment-prefix?
+                              (save-excursion
+                                (if (re-search-backward prefix-at-bol-here nil t)
+                                    (/= (match-beginning 1) (match-end 1)))))
+                         (progn        ; Skip the crud to find a real b-o-s.
+                           (if (c-in-comment-line-prefix-p)
+                               (beginning-of-line))
+                           (re-search-forward here-filler) ; always succeeds.
+                           (>= (point) here))))
+           (goto-char last))
+         (re-search-forward here-filler)))
+
+      (if (< (point) start-point)
+         nil
+       (goto-char (car range))
+       t))))
+
+(defun c-end-of-sentence-in-comment (range)
+  ;; Move forward to the "end of a sentence" within the comment defined by
+  ;; RANGE, a cons of its starting and ending positions (enclosing the opening
+  ;; comment delimiter and the terminating */ or newline).  If we find an EOS,
+  ;; return NIL.  Otherwise, move point to just after the end of the comment
+  ;; and return T.
+  ;;
+  ;; The EOS is just after the non-WS part of the next match of the regexp
+  ;; sentence-end.  Typically, this is just after one of [.!?].  If there is
+  ;; no sentence-end match following point, any WS before the end of the
+  ;; comment will count as EOS, providing we're not already in it.
+  ;;
+  ;; This code was adapted from GNU Emacs's forward-sentence in paragraphs.el.
+  ;; It is not a general function, but is intended only for calling from
+  ;; c-move-over-sentence.
+  ;;
+  ;; This function might do hidden buffer changes.
+  (save-match-data
+    (let ((start-point (point))
+         ;; (lit-type (c-literal-type range))  ; Commented out, 2005/11/23, ACM
+         )
+      (save-restriction
+       (c-narrow-to-comment-innards range) ; This might move point forwards.
+       (let* ((here (point))
+              (par-end ; EOL position of last text in current/next paragraph.
+               (save-excursion
+                 ;; The cc-mode values of paragraph-\(start\|separate\), set
+                 ;; in c-setup-paragraph-variables, are used in the
+                 ;; following.
+                 (forward-paragraph 1)
+                 (if (eq (preceding-char) ?\n) (forward-char -1))
+                 (when (<= (point) here) ; can happen, e.g., when HERE is at EOL.
+                   (goto-char here)
+                   (forward-paragraph 2)
+                   (if (eq (preceding-char) ?\n) (forward-char -1)))
+                 (point)))
+
+              last
+              (prefix-at-bol-here
+               (concat "^[ \t]*\\(" c-current-comment-prefix "\\)\\=")))
+         ;; Go forward one "comment-prefix which looks like sentence-end"
+         ;; each time round the following:
+         (while (and (re-search-forward (c-sentence-end) par-end 'limit)
+                     (progn
+                       (setq last (point))
+                       (skip-chars-backward " \t\n")
+                       (or (and (not (bolp))
+                                (re-search-backward prefix-at-bol-here nil t)
+                                (/= (match-beginning 1) (match-end 1)))
+                           (<= (point) here))))
+           (goto-char last))
+
+         ;; Take special action if we're up against the end of a comment (of
+         ;; either sort): Leave point just after the last non-ws text.
+         (if (eq (point) (point-max))
+             (while (or (/= (skip-chars-backward " \t\n") 0)
+                        (and (re-search-backward prefix-at-bol-here nil t)
+                             (/= (match-beginning 1) (match-end 1))))))))
+
+      (if (> (point) start-point)
+             nil
+           (goto-char (cdr range))
+           t))))
+
+(defun c-beginning-of-sentence-in-string (range)
+  ;; Move backwards to the "beginning of a sentence" within the string defined
+  ;; by RANGE, a cons of its starting and ending positions (enclosing the
+  ;; string quotes).  If we find a BOS, return NIL.  Otherwise, move point to
+  ;; just before the start of the string and return T.
+  ;;
+  ;; The BOS is either the text which follows a regexp match of sentence-end
+  ;; or text which is a beginning of "paragraph".  For the purposes of
+  ;; determining paragraph boundaries, escaped newlines are treated as
+  ;; ordinary newlines.
+  ;;
+  ;; This code was adapted from GNU Emacs's forward-sentence in paragraphs.el.
+  ;; It is not a general function, but is intended only for calling from
+  ;; c-move-over-sentence.
+  ;;
+  ;; This function might do hidden buffer changes.
+  (save-match-data
+    (let* ((here (point)) last
+          (end (1- (cdr range)))
+          (here-filler            ; matches WS and escaped newlines at point.
+           "\\=\\([ \t\n\r\f]\\|\\\\[\n\r]\\)*")
+          ;; Enhance paragraph-start and paragraph-separate also to recognise
+          ;; blank lines terminated by escaped EOLs.  IT MAY WELL BE that
+          ;; these values should be customizable user options, or something.
+          (paragraph-start c-string-par-start)
+          (paragraph-separate c-string-par-separate)
+
+          (par-beg            ; beginning of current (or previous) paragraph.
+           (save-excursion
+             (save-restriction
+               (narrow-to-region (1+ (car range)) end)
+               (forward-paragraph -1)  ; uses above values of
+                                       ; paragraph-\(start\|separate\)
+               (if (> (re-search-forward here-filler nil t) here)
+                   (goto-char here))
+               (when (>= (point) here)
+                 (forward-paragraph -2)
+                 (if (> (re-search-forward here-filler nil t) here)
+                     (goto-char here)))
+               (point)))))
+      ;; Now see if we can find a sentence end after PAR-BEG.
+      (while (and (re-search-backward c-sentence-end-with-esc-eol par-beg 'limit)
+                 (setq last (point))
+                 (goto-char (match-end 0))
+                 (or (> (point) end)
+                     (progn
+                       (re-search-forward
+                        here-filler end t) ; always succeeds.  Use end rather
+                                       ; than here, in case point starts
+                                       ; beyond the closing quote.
+                       (>= (point) here))))
+       (goto-char last))
+      (re-search-forward here-filler here t)
+      (if (< (point) here)
+         nil
+       (goto-char (car range))
+       t))))
+
+(defun c-end-of-sentence-in-string (range)
+  ;; Move forward to the "end of a sentence" within the string defined by
+  ;; RANGE, a cons of its starting and ending positions.  If we find an EOS,
+  ;; return NIL.  Otherwise, move point to just after the end of the string
+  ;; and return T.
+  ;;
+  ;; The EOS is just after the non-WS part of the next match of the regexp
+  ;; sentence-end.  Typically, this is just after one of [.!?].  If there is
+  ;; no sentence-end match following point, any WS before the end of the
+  ;; string will count as EOS, providing we're not already in it.
+  ;;
+  ;; This code was adapted from GNU Emacs's forward-sentence in paragraphs.el.
+  ;; It is not a general function, but is intended only for calling from
+  ;; c-move-over-sentence.
+  ;;
+  ;; This function might do hidden buffer changes.
+  (save-match-data
+    (let* ((here (point))
+          last
+          ;; Enhance paragraph-start and paragraph-separate to recognise
+          ;; blank lines terminated by escaped EOLs.
+          (paragraph-start c-string-par-start)
+          (paragraph-separate c-string-par-separate)
+
+          (par-end     ; EOL position of last text in current/next paragraph.
+           (save-excursion
+             (save-restriction
+               (narrow-to-region (car range) (1- (cdr range)))
+               ;; The above values of paragraph-\(start\|separate\) are used
+               ;; in the following.
+               (forward-paragraph 1)
+               (setq last (point))
+               ;; (re-search-backward filler-here nil t) would find an empty
+               ;; string.  Therefore we simulate it by the following:
+               (while (or (/= (skip-chars-backward " \t\n\r\f") 0)
+                          (re-search-backward "\\\\\\($\\)\\=" nil t)))
+               (unless (> (point) here)
+                 (goto-char last)
+                 (forward-paragraph 1)
+                 (while (or (/= (skip-chars-backward " \t\n\r\f") 0)
+                            (re-search-backward "\\\\\\($\\)\\=" nil t))))
+               (point)))))
+      ;; Try to go forward a sentence.
+      (when (re-search-forward c-sentence-end-with-esc-eol par-end 'limit)
+       (setq last (point))
+       (while (or (/= (skip-chars-backward " \t\n") 0)
+                  (re-search-backward "\\\\\\($\\)\\=" nil t))))
+      ;; Did we move a sentence, or did we hit the end of the string?
+      (if (> (point) here)
+         nil
+       (goto-char (cdr range))
+       t))))
+
+(defun c-ascertain-preceding-literal ()
+  ;; Point is not in a literal (i.e. comment or string (include AWK regexp)).
+  ;; If a literal is the next thing (aside from whitespace) to be found before
+  ;; point, return a cons of its start.end positions (enclosing the
+  ;; delimiters).  Otherwise return NIL.
+  ;;
+  ;; This function might do hidden buffer changes.
+  (save-excursion
+    (c-collect-line-comments
+     (let ((here (point))
+          pos)
+       (if (c-backward-single-comment)
+          (cons (point) (progn (c-forward-single-comment) (point)))
+        (save-restriction
+          ;; to prevent `looking-at' seeing a " at point.
+          (narrow-to-region (point-min) here)
+          (when
+              (or
+               ;; An EOL can act as an "open string" terminator in AWK.
+               (looking-at c-ws*-string-limit-regexp)
+               (and (not (bobp))
+                    (progn (backward-char)
+                           (looking-at c-string-limit-regexp))))
+            (goto-char (match-end 0))  ; just after the string terminator.
+            (setq pos (point))
+            (c-safe (c-backward-sexp 1) ; move back over the string.
+                    (cons (point) pos)))))))))
+
+(defun c-ascertain-following-literal ()
+  ;; Point is not in a literal (i.e. comment or string (include AWK regexp)).
+  ;; If a literal is the next thing (aside from whitespace) following point,
+  ;; return a cons of its start.end positions (enclosing the delimiters).
+  ;; Otherwise return NIL.
+  ;;
+  ;; This function might do hidden buffer changes.
+  (save-excursion
+    (c-collect-line-comments
+     (let (pos)
+       (c-skip-ws-forward)
+       (if (looking-at c-string-limit-regexp) ; string-delimiter.
+          (cons (point) (or (c-safe (progn (c-forward-sexp 1) (point)))
+                            (point-max)))
+        (setq pos (point))
+        (if (c-forward-single-comment)
+            (cons pos (point))))))))
+
+(defun c-after-statement-terminator-p () ; Should we pass in LIM here?
+  ;; Does point immediately follow a statement "terminator"?  A virtual
+  ;; semicolon is regarded here as such.  So is a an opening brace ;-)
+  ;;
+  ;; This function might do hidden buffer changes.
+  (or (save-excursion
+       (backward-char)
+       (and (looking-at "[;{}]")
+            (not (and c-special-brace-lists ; Pike special brace lists.
+                      (eq (char-after) ?{)
+                      (c-looking-at-special-brace-list)))))
+      (c-at-vsemi-p)
+      ;; The following (for macros) is not strict about exactly where we are
+      ;; wrt white space at the end of the macro.  Doesn't seem to matter too
+      ;; much.  ACM 2004/3/29.
+      (let (eom)
+       (save-excursion
+         (if (c-beginning-of-macro)
+             (setq eom (progn (c-end-of-macro)
+                              (point)))))
+       (when eom
+         (save-excursion
+           (c-forward-comments)
+           (>= (point) eom))))))
+
+(defun c-back-over-illiterals (macro-start)
+  ;; Move backwards over code which isn't a literal (i.e. comment or string),
+  ;; stopping before reaching BOB or a literal or the boundary of a
+  ;; preprocessor statement or the "beginning of a statement".  MACRO-START is
+  ;; the position of the '#' beginning the current preprocessor directive, or
+  ;; NIL if we're not in such.
+  ;;
+  ;; Return a cons (A.B), where
+  ;;   A is NIL if we moved back to a BOS (and know it), T otherwise (we
+  ;;     didn't move, or we hit a literal, or we're not sure about BOS).
+  ;;   B is MACRO-BOUNDARY if we are about to cross the boundary out of or
+  ;;     into a macro, otherwise LITERAL if we've hit a literal, otherwise NIL
+  ;;
+  ;;   The total collection of returned values is as follows:
+  ;;     (nil . nil): Found a BOS whilst remaining inside the illiterals.
+  ;;     (t . literal): No BOS found: only a comment/string.  We _might_ be at
+  ;;                    a BOS - the caller must check this.
+  ;;     (nil . macro-boundary): only happens with non-nil macro-start.  We've
+  ;;                             moved and reached the opening # of the macro.
+  ;;     (t . macro-boundary): Every other circumstance in which we're at a
+  ;;                           macro-boundary.  We might be at a BOS.
+  ;;
+  ;; Point is left either at the beginning-of-statement, or at the last non-ws
+  ;; code before encountering the literal/BOB or macro-boundary.
+  ;;
+  ;; Note that this function moves within either preprocessor commands
+  ;; (macros) or normal code, but will not cross a boundary between the two,
+  ;; or between two distinct preprocessor commands.
+  ;;
+  ;; Stop before `{' and after `;', `{', `}' and `};' when not followed by `}'
+  ;; or `)', but on the other side of the syntactic ws.  Move by sexps and
+  ;; move into parens.  Also stop before `#' when it's at boi on a line.
+  ;;
+  ;; This function might do hidden buffer changes.
+  (save-match-data
+    (let ((here (point))
+         last) ; marks the position of non-ws code, what'll be BOS if, say, a
+                                       ; semicolon precedes it.
+      (catch 'done
+       (while t ;; We go back one "token" each iteration of the loop.
+         (setq last (point))
+         (cond
+         ;; Stop at the token after a comment.
+          ((c-backward-single-comment) ; Also functions as backwards-ws.
+           (goto-char last)
+           (throw 'done '(t . literal)))
+
+         ;; If we've gone back over a LF, we might have moved into or out of
+         ;; a preprocessor line.
+          ((and (save-excursion
+                  (beginning-of-line)
+                  (re-search-forward "\\(^\\|[^\\]\\)[\n\r]" last t))
+                (if macro-start
+                    (< (point) macro-start)
+                  (c-beginning-of-macro)))
+           (goto-char last)
+           ;; Return a car of NIL ONLY if we've hit the opening # of a macro.
+           (throw 'done (cons (or (eq (point) here)
+                                  (not macro-start))
+                              'macro-boundary)))
+
+          ;; Have we found a virtual semicolon?  If so, stop, unless the next
+          ;; statement is where we started from.
+          ((and (c-at-vsemi-p)
+                (< last here)
+                (not (memq (char-after last) '(?\) ?})))) ; we've moved back from ) or }
+           (goto-char last)
+           (throw 'done '(nil . nil)))
+
+          ;; Hit the beginning of the buffer/region?
+          ((bobp)
+           (if (/= here last)
+               (goto-char last))
+           (throw 'done '(nil . nil)))
+
+          ;; Move back a character.
+          ((progn (backward-char) nil))
+
+          ;; Stop at "{" (unless it's a PIKE special brace list.)
+          ((eq (char-after) ?\{)
+           (if (and c-special-brace-lists
+                    (c-looking-at-special-brace-list))
+               (skip-syntax-backward "w_") ; Speedup only.
+             (if (/= here last)
+                 (goto-char last))
+             (throw 'done '(nil . nil))))
+
+          ;; Have we reached the start of a macro?  This always counts as
+          ;; BOS.  (N.B. I don't think (eq (point) here) can ever be true
+          ;; here.  FIXME!!! ACM 2004/3/29)
+          ((and macro-start (eq (point) macro-start))
+           (throw 'done (cons (eq (point) here) 'macro-boundary)))
+
+          ;; Stop at token just after "}" or ";".
+          ((looking-at "[;}]")
+           ;; If we've gone back over ;, {, or }, we're done.
+           (if (or (= here last)
+                   (memq (char-after last) '(?\) ?}))) ; we've moved back from ) or }
+               (if (and (eq (char-before) ?}) ; If };, treat them as a unit.
+                        (eq (char-after) ?\;))
+                   (backward-char))
+             (goto-char last)   ; To the statement starting after the ; or }.
+             (throw 'done '(nil . nil))))
+
+          ;; Stop at the token after a string.
+          ((looking-at c-string-limit-regexp) ; Just gone back over a string terminator?
+           (goto-char last)
+           (throw 'done '(t . literal)))
+        
+          ;; Nothing special: go back word characters.
+          (t (skip-syntax-backward "w_")) ; Speedup only.
+          ))))))
+
+(defun c-forward-over-illiterals (macro-end allow-early-stop)
+  ;; Move forwards over code, stopping before reaching EOB or a literal
+  ;; (i.e. a comment/string) or the boundary of a preprocessor statement or
+  ;; the "end of a statement".  MACRO-END is the position of the EOL/EOB which
+  ;; terminates the current preprocessor directive, or NIL if we're not in
+  ;; such.
+  ;;
+  ;; ALLOW-EARLY-STOP is non-nil if it is permissible to return without moving
+  ;; forward at all, should we encounter a `{'.  This is an ugly kludge, but
+  ;; seems unavoidable.  Depending on the context this function is called
+  ;; from, we _sometimes_ need to stop there.  Currently (2004/4/3),
+  ;; ALLOW-EARLY-STOP is applied only to open braces, not to virtual
+  ;; semicolons, or anything else.
+  ;;
+  ;; Return a cons (A.B), where
+  ;;   A is NIL if we moved forward to an EOS, or stay at one (when
+  ;;     ALLOW-EARLY-STOP is set), T otherwise (we hit a literal).
+  ;;   B is 'MACRO-BOUNDARY if we are about to cross the boundary out of or
+  ;;     into a macro, otherwise 'LITERAL if we've hit a literal, otherwise NIL
+  ;;
+  ;; Point is left either after the end-of-statement, or at the last non-ws
+  ;; code before encountering the literal, or the # of the preprocessor
+  ;; statement, or at EOB [or just after last non-WS stuff??].
+  ;;
+  ;; As a clarification of "after the end-of-statement", if a comment or
+  ;; whitespace follows a completed AWK statement, that statement is treated
+  ;; as ending just after the last non-ws character before the comment.
+  ;; 
+  ;; Note that this function moves within either preprocessor commands
+  ;; (macros) or normal code, but not both within the same invocation.
+  ;;
+  ;; Stop before `{', `}', and `#' when it's at boi on a line, but on the
+  ;; other side of the syntactic ws, and after `;', `}' and `};'.  Only
+  ;; stop before `{' if at top level or inside braces, though.  Move by
+  ;; sexps and move into parens.  Also stop at eol of lines with `#' at
+  ;; the boi.
+  ;;
+  ;; This function might do hidden buffer changes.
+  (let ((here (point))
+       last)
+    (catch 'done
+      (while t ;; We go one "token" forward each time round this loop.
+       (setq last (point))
+
+       ;; If we've moved forward to a virtual semicolon, we're done.
+       (if (and (> last here) ; Should we check ALLOW-EARLY-STOP, here? 2004/4/3
+                (c-at-vsemi-p))
+           (throw 'done '(nil . nil)))
+
+       (c-skip-ws-forward)
+       (cond
+        ;; Gone past the end of a macro?
+        ((and macro-end (> (point) macro-end))
+         (goto-char last)
+         (throw 'done (cons (eq (point) here) 'macro-boundary)))
+
+        ;; About to hit a comment?
+        ((save-excursion (c-forward-single-comment))
+         (goto-char last)
+         (throw 'done '(t . literal)))
+
+        ;; End of buffer?
+        ((eobp)
+         (if (/= here last)
+             (goto-char last))
+         (throw 'done '(nil . nil)))
+
+        ;; If we encounter a '{', stop just after the previous token.
+        ((and (eq (char-after) ?{)
+              (not (and c-special-brace-lists
+                        (c-looking-at-special-brace-list)))
+              (or allow-early-stop (/= here last))
+              (save-excursion  ; Is this a check that we're NOT at top level?
+;;;; NO!  This seems to check that (i) EITHER we're at the top level; OR (ii) The next enclosing
+;;;; level of bracketing is a '{'.  HMM.  Doesn't seem to make sense.
+;;;; 2003/8/8 This might have something to do with the GCC extension "Statement Expressions", e.g.
+;;;; while ({stmt1 ; stmt2 ; exp ;}).  This form excludes such Statement Expressions.
+                (or (not (c-safe (up-list -1) t))
+                    (= (char-after) ?{))))
+         (goto-char last)
+         (throw 'done '(nil . nil)))
+
+        ;; End of a PIKE special brace list?  If so, step over it and continue.
+        ((and c-special-brace-lists
+              (eq (char-after) ?})
+              (save-excursion
+                (and (c-safe (up-list -1) t)
+                     (c-looking-at-special-brace-list))))
+         (forward-char)
+         (skip-syntax-forward "w_"))   ; Speedup only.
+
+        ;; Have we got a '}' after having moved?  If so, stop after the
+        ;; previous token.
+        ((and (eq (char-after) ?})
+              (/= here last))
+         (goto-char last)
+         (throw 'done '(nil . nil)))
+
+        ;; Stop if we encounter a preprocessor line.
+        ((and (not macro-end)
+              (eq (char-after) ?#)
+              (= (point) (c-point 'boi)))
+         (goto-char last)
+         ;(throw 'done (cons (eq (point) here) 'macro-boundary))) ; Changed 2003/3/26
+         (throw 'done '(t . macro-boundary)))
+
+        ;; Stop after a ';', '}', or "};"
+        ((looking-at ";\\|};?")
+         (goto-char (match-end 0))
+         (throw 'done '(nil . nil)))
+
+        ;; Found a string (this subsumes AWK regexps)?
+        ((looking-at c-string-limit-regexp)
+         (goto-char last)
+         (throw 'done '(t . literal)))
+
+        (t
+         (forward-char)          ; Can't fail - we checked (eobp) earlier on.
+         (skip-syntax-forward "w_")    ; Speedup only.
+         (when (and macro-end (> (point) macro-end))
+           (goto-char last)
+           (throw 'done (cons (eq (point) here) 'macro-boundary))))
+        )))))
+
+(defun c-one-line-string-p (range)
+  ;; Is the literal defined by RANGE a string contained in a single line?
+  ;;
+  ;; This function might do hidden buffer changes.
+  (save-excursion
+    (goto-char (car range))
+    (and (looking-at c-string-limit-regexp)
+        (progn (skip-chars-forward "^\n" (cdr range))
+               (eq (point) (cdr range))))))
+
 (defun c-beginning-of-statement (&optional count lim sentence-flag)
   "Go to the beginning of the innermost C statement.
 With prefix arg, go back N - 1 statements.  If already at the
@@ -1382,318 +2247,93 @@ repetition count, a buffer position limit which is the farthest back
 to search for the syntactic context, and a flag saying whether to do
 sentence motion in or near comments and multiline strings.
 
-Note that `c-beginning-of-statement-1' is usually better to use from
-programs.  It has much more well defined semantics than this one,
-which is intended for interactive use and might therefore change to be
-more \"DWIM:ey\"."
+Note that for use in programs, `c-beginning-of-statement-1' is
+usually better.  It has much better defined semantics than this one,
+which is intended for interactive use, and might therefore change to
+be more \"DWIM:ey\"."
   (interactive (list (prefix-numeric-value current-prefix-arg)
                     nil t))
-  (c-save-buffer-state
-      ((count (or count 1))
-       here
-       (range (c-collect-line-comments (c-literal-limits lim))))
-    (while (and (/= count 0)
-               (or (not lim) (> (point) lim)))
-      (setq here (point))
-      (if (and (not range) sentence-flag)
-         (save-excursion
-           ;; Find the comment next to point if we're not in one.
-           (if (> count 0)
-               (if (c-backward-single-comment)
-                   (setq range (cons (point)
-                                     (progn (c-forward-single-comment)
-                                            (point))))
-                 (c-skip-ws-backward)
-                 (setq range (point))
-                 (setq range
-                       (if (eq (char-before) ?\")
-                           (c-safe (c-backward-sexp 1)
-                                   (cons (point) range)))))
-             (c-skip-ws-forward)
-             (if (eq (char-after) ?\")
-                 (setq range (cons (point)
-                                   (progn
-                                     (c-forward-sexp 1)
-                                     (point))))
-               (setq range (point))
-               (setq range (if (c-forward-single-comment)
-                               (cons range (point))
-                             nil))))
-           (setq range (c-collect-line-comments range))))
-      (if (and (< count 0) (= here (point-max)))
-         ;; Special case because eob might be in a literal.
-         (setq range nil))
-      (if range
-         (if (and sentence-flag
-                  (or (/= (char-syntax (char-after (car range))) ?\")
-                      ;; Only visit a string if it spans more than one line.
-                      (save-excursion
-                        (goto-char (car range))
-                        (skip-chars-forward "^\n" (cdr range))
-                        (< (point) (cdr range)))))
-             (let* ((lit-type (c-literal-type range))
-                    (line-prefix (concat "[ \t]*\\("
-                                         c-current-comment-prefix
-                                         "\\)[ \t]*"))
-                    (beg (if (eq lit-type 'string)
-                             (1+ (car range))
-                           (save-excursion
-                             (goto-char (car range))
-                             (max (progn
-                                    (looking-at comment-start-skip)
-                                    (match-end 0))
-                                  (progn
-                                    (looking-at line-prefix)
-                                    (match-end 0))))))
-                    (end (- (cdr range) (if (eq lit-type 'c) 2 1)))
-                    (beg-of-para (if (eq lit-type 'string)
-                                     (lambda ())
-                                   (lambda ()
-                                     (beginning-of-line)
-                                     (if (looking-at line-prefix)
-                                         (goto-char (match-end 0)))))))
-               (save-restriction
-                 ;; Move by sentence, but not past the limit of the
-                 ;; literal, narrowed to the appropriate
-                 ;; paragraph(s).
-                 (narrow-to-region (save-excursion
-                                     (let ((pos (min here end)))
-                                       (goto-char pos)
-                                       (forward-paragraph -1)
-                                       (if (looking-at paragraph-separate)
-                                           (forward-line))
-                                       (when (> (point) beg)
-                                         (funcall beg-of-para)
-                                         (when (>= (point) pos)
-                                           (forward-paragraph -2)
-                                           (funcall beg-of-para)))
-                                       (max (point) beg)))
-                                   end)
-                 (c-safe (forward-sentence (if (< count 0) 1 -1)))
-                 (if (and (memq lit-type '(c c++))
-                          ;; Check if we stopped due to a comment
-                          ;; prefix and not a sentence end.
-                          (/= (point) (point-min))
-                          (/= (point) (point-max))
-                          (save-excursion
-                            (beginning-of-line)
-                            (looking-at line-prefix))
-                          (>= (point) (match-beginning 0))
-                          (/= (match-beginning 1) (match-end 1))
-                          (or (< (point) (match-end 0))
-                              (and
-                               (= (point) (match-end 0))
-                               ;; The comment prefix may contain
-                               ;; characters that is regarded as end
-                               ;; of sentence.
-                               (or (eolp)
-                                   (and
-                                    (save-excursion
-                                      (forward-paragraph -1)
-                                      (< (point) (match-beginning 0)))
-                                    (save-excursion
-                                      (beginning-of-line)
-                                      (or (not (re-search-backward
-                                                (sentence-end)
-                                                (c-point 'bopl)
-                                                t))
-                                          (< (match-end 0)
-                                             (c-point 'eol)))))))))
-                     (setq count (+ count (if (< count 0) -1 1)))
-                   (if (< count 0)
-                       (progn
-                         ;; In block comments, if there's only
-                         ;; horizontal ws between the text and the
-                         ;; comment ender, stop before it.  Stop after
-                         ;; the ender if there's either nothing or
-                         ;; newlines between.
-                         (when (and (eq lit-type 'c)
-                                    (eq (point) (point-max)))
-                           (widen)
-                           (when (or (= (skip-chars-backward " \t") 0)
-                                     (eq (point) (point-max))
-                                     (bolp))
-                             (goto-char (cdr range)))))
-                     (when (and (eq (point) (point-min))
-                                (looking-at "[ \t]*\\\\?$"))
-                       ;; Stop before instead of after the comment
-                       ;; starter if nothing follows it.
-                       (widen)
-                       (goto-char (car range))
-                       (if (and (eq lit-type 'string) (/= (point) here))
-                           (setq count (1+ count)
-                                 range nil))))))
-               ;; See if we should escape the literal.
-               (if (> count 0)
-                   (if (< (point) here)
-                       (setq count (1- count))
-                     (goto-char (car range))
-                     (setq range nil))
-                 (if (> (point) here)
-                     (setq count (1+ count))
-                   (goto-char (cdr range))
-                   (setq range nil))))
-           (goto-char (if (> count 0) (car range) (cdr range)))
-           (setq range nil))
-       (goto-char here)
-       (if (> count 0)
-           (condition-case nil
-               ;; Stop before `{' and after `;', `{', `}' and `};'
-               ;; when not followed by `}' or `)', but on the other
-               ;; side of the syntactic ws.  Move by sexps and move
-               ;; into parens.  Also stop before `#' when it's at boi
-               ;; on a line.
-               (let ((literal-pos (not sentence-flag))
-                     last last-below-line)
-                 (catch 'done
-                   (while t
-                     (setq last (point))
-                     (when (and (or (eq (char-after) ?\{)
-                                    (and (eq (char-after) ?#)
-                                         (eq (point) (c-point 'boi)))
-                                    )
-                                (/= here last))
-                       (unless (and c-special-brace-lists
-                                    (eq (char-after) ?{)
-                                    (c-looking-at-special-brace-list))
-                         (if (and (eq (char-after) ?#)
-                                  (numberp last-below-line)
-                                  (not (eq last-below-line here)))
-                             (goto-char last-below-line))
-                         (throw 'done t)))
-                     ;; Don't know why I added the following, but it
-                     ;; doesn't work when point is preceded by a line
-                     ;; style comment. /mast
-                     ;;(c-skip-ws-backward)
-                     (if literal-pos
-                         (c-backward-comments)
-                       (when (c-backward-single-comment)
-                         ;; Record position of first comment.
-                         (save-excursion
-                           (c-forward-single-comment)
-                           (setq literal-pos (point)))
-                         (c-backward-comments)))
-                     (unless last-below-line
-                       (if (save-excursion
-                             (re-search-forward "\\(^\\|[^\\]\\)$" last t))
-                           (setq last-below-line last)))
-                     (cond ((bobp)     ; Must handle bob specially.
-                            (if (= here last)
-                                (throw 'done t)
-                              (goto-char last)
-                              (throw 'done t)))
-                           ((progn (backward-char)
-                                   (looking-at "[;{}]"))
-                            (if (and c-special-brace-lists
-                                     (eq (char-after) ?{)
-                                     (c-looking-at-special-brace-list))
-                                (skip-syntax-backward "w_") ; Speedup only.
-                              (if (or (= here last)
-                                      (memq (char-after last) '(?\) ?})))
-                                  (if (and (eq (char-before) ?})
-                                           (eq (char-after) ?\;))
-                                      (backward-char))
-                                (goto-char last)
-                                (throw 'done t))))
-                           ((= (char-syntax (char-after)) ?\")
-                            (let ((end (point)))
-                              (forward-char)
-                              (c-backward-sexp)
-                              (save-excursion
-                                (skip-chars-forward "^\n" end)
-                                (when (< (point) end)
-                                  ;; Break at multiline string.
-                                  (setq literal-pos (1+ end))
-                                  (throw 'done t)))))
-                           (t (skip-syntax-backward "w_")) ; Speedup only.
-                           )))
-                 (if (and (numberp literal-pos)
-                          (< (point) literal-pos))
-                     ;; We jumped over a comment or string that
-                     ;; should be investigated.
-                     (goto-char literal-pos)
-                   (setq count (1- count))))
-             (error
-              (goto-char (point-min))
-              (setq count 0)))
-         (condition-case nil
-             ;; Stop before `{', `}', and `#' when it's at boi on a
-             ;; line, but on the other side of the syntactic ws, and
-             ;; after `;', `}' and `};'.  Only stop before `{' if at
-             ;; top level or inside braces, though.  Move by sexps
-             ;; and move into parens.  Also stop at eol of lines
-             ;; with `#' at the boi.
-             (let ((literal-pos (not sentence-flag))
-                   last)
-               (catch 'done
-                 (while t
-                   (setq last (point))
-                   (if literal-pos
-                       (c-forward-comments)
-                     (if (progn
-                           (c-skip-ws-forward)
-                           ;; Record position of first comment.
-                           (setq literal-pos (point))
-                           (c-forward-single-comment))
-                         (c-forward-comments)
-                       (setq literal-pos nil)))
-                   (cond ((and (eq (char-after) ?{)
-                               (not (and c-special-brace-lists
-                                         (c-looking-at-special-brace-list)))
-                               (/= here last)
-                               (save-excursion
-                                 (or (not (c-safe (up-list -1) t))
-                                     (= (char-after) ?{))))
-                          (goto-char last)
-                          (throw 'done t))
-                         ((and c-special-brace-lists
-                               (eq (char-after) ?})
-                               (save-excursion
-                                 (and (c-safe (up-list -1) t)
-                                      (c-looking-at-special-brace-list))))
-                          (forward-char 1)
-                          (skip-syntax-forward "w_")) ; Speedup only.
-                         ((and (eq (char-after) ?})
-                               (/= here last))
-                          (goto-char last)
-                          (throw 'done t))
-;                        ((and (eq (char-after) ?#)
-;                              (= (point) (c-point 'boi)))
-;                         (if (= here last)
-;                             (or (re-search-forward "\\(^\\|[^\\]\\)$" nil t)
-;                                 (goto-char (point-max)))
-;                           (goto-char last))
-;                         (throw 'done t))
-                         ((looking-at ";\\|};?")
-                          (goto-char (match-end 0))
-                          (throw 'done t))
-                         ((= (char-syntax (char-after)) ?\")
-                          (let ((beg (point)))
-                            (c-forward-sexp)
-                            (save-excursion
-                              (skip-chars-backward "^\n" beg)
-                              (when (> (point) beg)
-                                ;; Break at multiline string.
-                                (setq literal-pos beg)
-                                (throw 'done t)))))
-                         (t
-                          (forward-char 1)
-                          (skip-syntax-forward "w_")) ; Speedup only.
-                         )))
-               (if (and (numberp literal-pos)
-                        (> (point) literal-pos))
-                   ;; We jumped over a comment that should be investigated.
-                   (goto-char literal-pos)
-                 (setq count (1+ count))))
-           (error
-            (goto-char (point-max))
-            (setq count 0)))
-         ))
-      ;; If we haven't moved we're near a buffer limit.
-      (when (and (not (zerop count)) (= (point) here))
-       (goto-char (if (> count 0) (point-min) (point-max)))
-       (setq count 0))))
-  (c-keep-region-active))
+  (if (< count 0)
+      (c-end-of-statement (- count) lim sentence-flag)
+    (c-save-buffer-state
+       ((count (or count 1))
+        last ; start point for going back ONE chunk.  Updated each chunk movement.
+        (macro-fence
+         (save-excursion (and (not (bobp)) (c-beginning-of-macro) (point))))
+        res                            ; result from sub-function call
+        not-bos                        ; "not beginning-of-statement"
+        (range (c-collect-line-comments (c-literal-limits lim)))) ; (start.end) of current literal or NIL
+
+      ;; Go back one statement at each iteration of the following loop.
+      (while (and (/= count 0)
+                 (or (not lim) (> (point) lim)))
+       ;; Go back one "chunk" each time round the following loop, stopping
+       ;; when we reach a statement boundary, etc.
+       (setq last (point))
+       (while
+           (cond ; Each arm of this cond returns NIL on reaching a desired
+                 ; statement boundary, non-NIL otherwise.
+            ((bobp)
+             (setq count 0)
+             nil)
+
+            (range                ; point is within or approaching a literal.
+             (cond
+              ;; Single line string or sentence-flag is null => skip the
+              ;; entire literal.
+              ((or (null sentence-flag)
+                   (c-one-line-string-p range))
+               (goto-char (car range))
+               (setq range (c-ascertain-preceding-literal))
+               ;; N.B. The following is essentially testing for an AWK regexp
+               ;; at BOS:
+               ;; Was the previous non-ws thing an end of statement?
+               (save-excursion
+                 (if macro-fence
+                     (c-backward-comments)
+                   (c-backward-syntactic-ws))
+                 (not (or (bobp) (c-after-statement-terminator-p)))))
+
+              ;; Comment inside a statement or a multi-line string.
+              (t (when (setq res ; returns non-nil when we go out of the literal
+                             (if (eq (c-literal-type range) 'string)
+                                 (c-beginning-of-sentence-in-string range)
+                               (c-beginning-of-sentence-in-comment range)))
+                   (setq range (c-ascertain-preceding-literal)))
+                 res)))
+
+            ;; Non-literal code.
+            (t (setq res (c-back-over-illiterals macro-fence))
+               (setq not-bos          ; "not reached beginning-of-statement".
+                     (or (= (point) last)
+                         (memq (char-after) '(?\) ?\}))
+                         (and
+                          (car res)
+                          ;; We're at a tentative BOS.  The next form goes
+                          ;; back over WS looking for an end of previous
+                          ;; statement.
+                          (not (save-excursion
+                                 (if macro-fence
+                                     (c-backward-comments)
+                                   (c-backward-syntactic-ws))
+                                 (or (bobp) (c-after-statement-terminator-p)))))))
+               ;; Are we about to move backwards into or out of a
+               ;; preprocessor command?  If so, locate it's beginning.
+               (when (eq (cdr res) 'macro-boundary)
+                 (save-excursion
+                   (beginning-of-line)
+                   (setq macro-fence
+                         (and (not (bobp))
+                              (progn (c-skip-ws-backward) (c-beginning-of-macro))
+                              (point)))))
+               ;; Are we about to move backwards into a literal?
+               (when (memq (cdr res) '(macro-boundary literal))
+                 (setq range (c-ascertain-preceding-literal)))
+               not-bos))
+         (setq last (point)))
+
+       (if (/= count 0) (setq count (1- count))))
+      (c-keep-region-active))))
 
 (defun c-end-of-statement (&optional count lim sentence-flag)
   "Go to the end of the innermost C statement.
@@ -1708,8 +2348,77 @@ to search for the syntactic context, and a flag saying whether to do
 sentence motion in or near comments and multiline strings."
   (interactive (list (prefix-numeric-value current-prefix-arg)
                     nil t))
-  (c-beginning-of-statement (- (or count 1)) lim sentence-flag)
-  (c-keep-region-active))
+  (setq count (or count 1))
+  (if (< count 0) (c-beginning-of-statement (- count) lim sentence-flag)
+
+    (c-save-buffer-state
+       (here ; start point for going forward ONE statement.  Updated each statement.
+        (macro-fence
+         (save-excursion
+           (and (not (eobp)) (c-beginning-of-macro)
+                (progn (c-end-of-macro) (point)))))
+        res
+        (range (c-collect-line-comments (c-literal-limits lim)))) ; (start.end) of current literal or NIL
+
+      ;; Go back/forward one statement at each iteration of the following loop.
+      (while (and (/= count 0)
+                 (or (not lim) (< (point) lim)))
+       (setq here (point))             ; ONLY HERE is HERE updated
+
+       ;; Go forward one "chunk" each time round the following loop, stopping
+       ;; when we reach a statement boundary, etc.
+       (while
+           (cond    ; Each arm of this cond returns NIL on reaching a desired
+                    ; statement boundary, non-NIL otherwise.
+            ((eobp)
+             (setq count 0)
+             nil)
+
+            (range                     ; point is within a literal.
+             (cond
+              ;; sentence-flag is null => skip the entire literal.
+              ;; or a Single line string.
+              ((or (null sentence-flag)
+                   (c-one-line-string-p range))
+               (goto-char (cdr range))
+               (setq range (c-ascertain-following-literal))
+               ;; Is there a virtual semicolon here (e.g. for AWK)?
+               (not (c-at-vsemi-p)))
+
+              ;; Comment or multi-line string.
+              (t (when (setq res ; gets non-nil when we go out of the literal
+                             (if (eq (c-literal-type range) 'string)
+                                 (c-end-of-sentence-in-string range)
+                               (c-end-of-sentence-in-comment range)))
+                   (setq range (c-ascertain-following-literal)))
+                 ;; If we've just come forward out of a literal, check for
+                 ;; vsemi.  (N.B. AWK can't have a vsemi after a comment, but
+                 ;; some other language may do in the future)
+                 (and res
+                      (not (c-at-vsemi-p))))))
+
+            ;; Non-literal code.
+            (t (setq res (c-forward-over-illiterals macro-fence
+                                                    (> (point) here)))
+               ;; Are we about to move forward into or out of a
+               ;; preprocessor command?
+               (when (eq (cdr res) 'macro-boundary)
+                 (save-excursion
+                   (end-of-line)
+                   (setq macro-fence
+                         (and (not (eobp))
+                              (progn (c-skip-ws-forward)
+                                     (c-beginning-of-macro))
+                              (progn (c-end-of-macro)
+                                     (point))))))
+               ;; Are we about to move forward into a literal?
+               (when (memq (cdr res) '(macro-boundary literal))
+                 (setq range (c-ascertain-following-literal)))
+               (car res))))
+
+       (if (/= count 0) (setq count (1- count))))
+      (c-keep-region-active))))
+                              
 
 \f
 ;; set up electric character functions to work with pending-del,
@@ -1737,6 +2446,7 @@ sentence motion in or near comments and multiline strings."
 
 \f
 (defun c-calc-comment-indent (entry)
+  ;; This function might do hidden buffer changes.
   (if (symbolp entry)
       (setq entry (or (assq entry c-indent-comment-alist)
                      (assq 'other c-indent-comment-alist)
@@ -1760,7 +2470,7 @@ sentence motion in or near comments and multiline strings."
                   (let ((lim (c-literal-limits (c-point 'bol) t)))
                     (when (consp lim)
                       (goto-char (car lim))
-                      (when (looking-at "/[/*]")
+                      (when (looking-at "/[/*]") ; FIXME!!!  Adapt for AWK! (ACM, 2005/11/18)
                         ;; Found comment to align with.
                         (if (bolp)
                             ;; Do not pad with one space if we're at bol.
@@ -1835,15 +2545,16 @@ See `c-indent-comment-alist' for a description."
 A prefix argument acts as a repeat count.  With a negative argument,
 move forward to the end of the containing preprocessor conditional.
 
-`#elif' is treated like `#else' followed by `#if', so the function
-stops at them when going backward, but not when going forward."
+\"#elif\" is treated like \"#else\" followed by \"#if\", so the
+function stops at them when going backward, but not when going
+forward."
   (interactive "p")
   (c-forward-conditional (- count) -1)
   (c-keep-region-active))
   
 (defun c-up-conditional-with-else (count)
-  "Move back to the containing preprocessor conditional, including `#else'.
-Just like `c-up-conditional', except it also stops at `#else'
+  "Move back to the containing preprocessor conditional, including \"#else\".
+Just like `c-up-conditional', except it also stops at \"#else\"
 directives."
   (interactive "p")
   (c-forward-conditional (- count) -1 t)
@@ -1854,15 +2565,16 @@ directives."
 A prefix argument acts as a repeat count.  With a negative argument,
 move backward into the previous preprocessor conditional.
 
-`#elif' is treated like `#else' followed by `#if', so the function
-stops at them when going forward, but not when going backward."
+\"#elif\" is treated like \"#else\" followed by \"#if\", so the
+function stops at them when going forward, but not when going
+backward."
   (interactive "p")
   (c-forward-conditional count 1)
   (c-keep-region-active))
 
 (defun c-down-conditional-with-else (count)
-  "Move forward into the next preprocessor conditional, including `#else'.
-Just like `c-down-conditional', except it also stops at `#else'
+  "Move forward into the next preprocessor conditional, including \"#else\".
+Just like `c-down-conditional', except it also stops at \"#else\"
 directives."
   (interactive "p")
   (c-forward-conditional count 1 t)
@@ -1881,16 +2593,16 @@ move forward across a preprocessor conditional."
 A prefix argument acts as a repeat count.  With a negative argument,
 move backward across a preprocessor conditional.
 
-`#elif' is treated like `#else' followed by `#if', except that the
-nesting level isn't changed when tracking subconditionals.
+\"#elif\" is treated like \"#else\" followed by \"#if\", except that
+the nesting level isn't changed when tracking subconditionals.
 
 The optional argument TARGET-DEPTH specifies the wanted nesting depth
 after each scan.  I.e. if TARGET-DEPTH is -1, the function will move
 out of the enclosing conditional.  A non-integer non-nil TARGET-DEPTH
 counts as -1.
 
-If the optional argument WITH-ELSE is non-nil, `#else' directives are
-treated as conditional clause limits.  Normally they are ignored."
+If the optional argument WITH-ELSE is non-nil, \"#else\" directives
+are treated as conditional clause limits.  Normally they are ignored."
   (interactive "p")
   (let* ((forward (> count 0))
         (increment (if forward -1 1))
@@ -1996,15 +2708,15 @@ prefix argument is equivalent to -1.
   just inserts a tab character, or the equivalent number of spaces,
   depending on the variable `indent-tabs-mode'."
 
-  (interactive "p")
+  (interactive "P")
   (let ((indent-function
         (if c-syntactic-indentation
             (symbol-function 'indent-according-to-mode)
           (lambda ()
             (let ((c-macro-start c-macro-start)
-                  (steps (cond ((not current-prefix-arg) 1)
-                               ((equal current-prefix-arg '(4)) -1)
-                               (t arg))))
+                  (steps (if (equal arg '(4))
+                             -1
+                           (prefix-numeric-value arg))))
               (c-shift-line-indentation (* steps c-basic-offset))
               (when (and c-auto-align-backslashes
                          (save-excursion
@@ -2014,7 +2726,7 @@ prefix argument is equivalent to -1.
                 ;; Realign the line continuation backslash if inside a macro.
                 (c-backslash-region (point) (point) nil t)))
             ))))
-    (if (and c-syntactic-indentation current-prefix-arg)
+    (if (and c-syntactic-indentation arg)
        ;; If c-syntactic-indentation and got arg, always indent this
        ;; line as C and shift remaining lines of expression the same
        ;; amount.
@@ -2029,7 +2741,7 @@ prefix argument is equivalent to -1.
                             shift-amt))
          (save-excursion
            (if (eq c-tab-always-indent t)
-               (beginning-of-line))
+               (beginning-of-line))    ; FIXME!!! What is this here for?  ACM 2005/10/31
            (setq beg (point))
            (c-forward-sexp 1)
            (setq end (point))
@@ -2040,7 +2752,7 @@ prefix argument is equivalent to -1.
              (indent-code-rigidly beg end shift-amt "#")))
       ;; Else use c-tab-always-indent to determine behavior.
       (cond
-       ;; CASE 1: indent when at column zero or in lines indentation,
+       ;; CASE 1: indent when at column zero or in line's indentation,
        ;; otherwise insert a tab
        ((not c-tab-always-indent)
        (if (save-excursion
@@ -2054,7 +2766,7 @@ prefix argument is equivalent to -1.
        ;; CASE 3: if in a literal, insert a tab, but always indent the
        ;; line
        (t
-       (if (c-in-literal)
+       (if (c-save-buffer-state () (c-in-literal))
            (funcall c-insert-tab-function))
        (funcall indent-function)
        )))))
@@ -2135,7 +2847,8 @@ non-nil."
                    ;; shut up any echo msgs on indiv lines
                    (c-echo-syntactic-information-p nil)
                    (in-macro (and c-auto-align-backslashes
-                                  (save-excursion (c-beginning-of-macro))
+                                  (c-save-buffer-state ()
+                                    (save-excursion (c-beginning-of-macro)))
                                   start))
                    (c-fix-backslashes nil)
                    syntax)
@@ -2181,8 +2894,6 @@ non-nil."
 (defun c-fn-region-is-active-p ()
   ;; Function version of the macro for use in places that aren't
   ;; compiled, e.g. in the menus.
-  ;;
-  ;; This function does not do any hidden buffer changes.
   (c-region-is-active-p))
 
 (defun c-indent-line-or-region ()
@@ -2199,7 +2910,6 @@ indent the current line syntactically."
 (defvar c-progress-info nil)
 
 (defun c-progress-init (start end context)
-  ;; This function does not do any hidden buffer changes.
   (cond
    ;; Be silent
    ((not c-progress-interval))
@@ -2221,7 +2931,6 @@ indent the current line syntactically."
    ))
 
 (defun c-progress-update ()
-  ;; This function does not do any hidden buffer changes.
   (if (not (and c-progress-info c-progress-interval))
       nil
     (let ((now (nth 1 (current-time)))
@@ -2238,7 +2947,6 @@ indent the current line syntactically."
       )))
 
 (defun c-progress-fini (context)
-  ;; This function does not do any hidden buffer changes.
   (if (not c-progress-interval)
       nil
     (if (or (eq context (aref c-progress-info 3))
@@ -2399,7 +3107,6 @@ command to conveniently insert and align the necessary backslashes."
        (set-marker point-pos nil))))
 
 (defun c-append-backslashes-forward (to-mark column point-pos)
-  ;; This function does not do any hidden buffer changes.
   (let ((state (parse-partial-sexp (c-point 'bol) (point))))
     (if column
        (while
@@ -2473,7 +3180,6 @@ command to conveniently insert and align the necessary backslashes."
           (bolp))))))                  ; forward-line has funny behavior at eob.
 
 (defun c-delete-backslashes-forward (to-mark point-pos)
-  ;; This function does not do any hidden buffer changes.
   (while
       (and (<= (point) to-mark)
           (progn
@@ -2518,6 +3224,8 @@ command to conveniently insert and align the necessary backslashes."
   ;; comment.  Return a cons of the prefix string and the column where
   ;; it ends.  If fill-prefix is set, it'll override.  Note that this
   ;; function also uses the value of point in some heuristics.
+  ;;
+  ;; This function might do hidden buffer changes.
 
   (let* ((here (point))
         (prefix-regexp (concat "[ \t]*\\("
@@ -2877,7 +3585,7 @@ command to conveniently insert and align the necessary backslashes."
   ;; If APPLY-OUTSIDE-LITERAL is nil then the function will be called
   ;; only if the point turns out to be inside a comment or a string.
   ;;
-  ;; This function does not do any hidden buffer changes.
+  ;; Note that this function does not do any hidden buffer changes.
 
   (let (fill
        ;; beg and end limits the region to narrow.  end is a marker.
@@ -2892,6 +3600,10 @@ command to conveniently insert and align the necessary backslashes."
        ;; hanging.  In that case it's set to the number of spaces
        ;; that should be between the text and the ender.
        hang-ender-stuck
+       ;; auto-fill-spaces is the exact sequence of whitespace between a
+       ;; comment's last word and the comment ender, temporarily replaced
+       ;; with 'x's before calling FUN when FILL-PARAGRAPH is nil.  
+       auto-fill-spaces
        (here (point))
        (c-lit-limits c-lit-limits)
        (c-lit-type c-lit-type))
@@ -2902,29 +3614,30 @@ command to conveniently insert and align the necessary backslashes."
     (if (and buffer-undo-list (not (eq buffer-undo-list t)))
        (setq buffer-undo-list (cons (point) buffer-undo-list)))
 
-    (save-restriction
-      ;; Widen to catch comment limits correctly.
-      (widen)
-      (unless c-lit-limits
-       (setq c-lit-limits (c-literal-limits nil fill-paragraph)))
-      (setq c-lit-limits (c-collect-line-comments c-lit-limits))
-      (unless c-lit-type
-       (setq c-lit-type (c-literal-type c-lit-limits))))
+    (c-save-buffer-state ()
+      (save-restriction
+       ;; Widen to catch comment limits correctly.
+       (widen)
+       (unless c-lit-limits
+         (setq c-lit-limits (c-literal-limits nil fill-paragraph)))
+       (setq c-lit-limits (c-collect-line-comments c-lit-limits))
+       (unless c-lit-type
+         (setq c-lit-type (c-literal-type c-lit-limits))))
 
-    (save-excursion
-      (unless (c-safe (backward-char)
-                     (forward-paragraph)
-                     (>= (point) here))
-       (goto-char here)
-       (forward-paragraph))
-      (setq end (point-marker)))
-    (save-excursion
-      (unless (c-safe (forward-char)
-                     (backward-paragraph)
-                     (<= (point) here))
-       (goto-char here)
-       (backward-paragraph))
-      (setq beg (point)))
+      (save-excursion
+       (unless (c-safe (backward-char)
+                       (forward-paragraph)
+                       (>= (point) here))
+         (goto-char here)
+         (forward-paragraph))
+       (setq end (point-marker)))
+      (save-excursion
+       (unless (c-safe (forward-char)
+                       (backward-paragraph)
+                       (<= (point) here))
+         (goto-char here)
+         (backward-paragraph))
+       (setq beg (point))))
 
     (unwind-protect
        (progn
@@ -2965,73 +3678,76 @@ command to conveniently insert and align the necessary backslashes."
                             ;; own.  Keep it that way.
                             (set-marker end (point))))
 
-               (if fill-paragraph
-                   ;; The comment ender should hang.  Replace all
-                   ;; cruft between it and the last word with one or
-                   ;; two 'x' and include it in the region.  We'll
-                   ;; change them back to spaces afterwards.  This
-                   ;; isn't done when auto filling, since that'd
-                   ;; effectively make it impossible to insert extra
-                   ;; spaces before the comment ender.
-                   (let* ((ender-start (save-excursion
-                                         (goto-char (cdr c-lit-limits))
-                                         (skip-syntax-backward "^w ")
-                                         (point)))
-                          (point-rel (- ender-start here))
-                          spaces)
-
-                     (save-excursion
-                       (goto-char (cdr c-lit-limits))
-                       (setq tmp-post (point-marker))
-                       (insert ?\n)
-                       (set-marker end (point))
-                       (forward-line -1)
-                       (if (and (looking-at (concat "[ \t]*\\(\\("
-                                                    c-current-comment-prefix
-                                                    "\\)[ \t]*\\)"))
-                                (eq ender-start (match-end 0)))
-                           ;; The comment ender is prefixed by nothing
-                           ;; but a comment line prefix.  Remove it
-                           ;; along with surrounding ws.
-                           (setq spaces (- (match-end 1) (match-end 2)))
-                         (goto-char ender-start))
-                       (skip-chars-backward " \t\r\n")
-
-                       (if (/= (point) ender-start)
-                           (progn
-                             (if (<= here (point))
-                                 ;; Don't adjust point below if it's
-                                 ;; before the string we replace.
-                                 (setq point-rel -1))
-                             ;; Keep one or two spaces between the
-                             ;; text and the ender, depending on how
-                             ;; many there are now.
-                             (unless spaces
-                               (setq spaces (- ender-start (point))))
+               ;; The comment ender should hang.  Replace all space between
+               ;; it and the last word either by one or two 'x's (when
+               ;; FILL-PARAGRAPH is non-nil), or a row of x's the same width
+               ;; as the whitespace (when auto filling), and include it in
+               ;; the region.  We'll change them back to whitespace
+               ;; afterwards.  The effect of this is to glue the comment
+               ;; ender to the last word in the comment during filling.
+               (let* ((ender-start (save-excursion
+                                     (goto-char (cdr c-lit-limits))
+                                     (skip-syntax-backward "^w ")
+                                     (point)))
+                      (ender-column (save-excursion
+                                      (goto-char ender-start)
+                                      (current-column)))
+                      (point-rel (- ender-start here))
+                      spaces)
+
+                 (save-excursion
+                   (goto-char (cdr c-lit-limits))
+                   (setq tmp-post (point-marker))
+                   (insert ?\n)
+                   (set-marker end (point))
+                   (forward-line -1)   ; last line of the comment
+                   (if (and (looking-at (concat "[ \t]*\\(\\("
+                                                c-current-comment-prefix
+                                                "\\)[ \t]*\\)"))
+                            (eq ender-start (match-end 0)))
+                       ;; The comment ender is prefixed by nothing
+                       ;; but a comment line prefix.  Remove it
+                       ;; along with surrounding ws.
+                       (setq spaces (- (match-end 1) (match-end 2)))
+                     (goto-char ender-start))
+                   (skip-chars-backward " \t\r\n") ; Surely this can be
+                                       ; " \t"? "*/" is NOT alone on the line (ACM, 2005/8/18)
+
+                   (if (/= (point) ender-start)
+                       (progn
+                         (if (<= here (point))
+                             ;; Don't adjust point below if it's
+                             ;; before the string we replace.
+                             (setq point-rel -1))
+                         ;; Keep one or two spaces between the
+                         ;; text and the ender, depending on how
+                         ;; many there are now.
+                         (unless spaces
+                           (setq spaces (- ender-column (current-column))))
+                         (setq auto-fill-spaces (c-delete-and-extract-region
+                                                 (point) ender-start))
+                         ;; paragraph filling condenses multiple spaces to
+                         ;; single or double spaces.  auto-fill doesn't.
+                         (if fill-paragraph
                              (setq spaces
                                    (max
                                     (min spaces
                                          (if sentence-end-double-space 2 1))
-                                    1))
-                             ;; Insert the filler first to keep marks right.
-                             (insert-char ?x spaces t)
-                             (delete-region (point) (+ ender-start spaces))
-                             (setq hang-ender-stuck spaces)
-                             (setq point-rel
-                                   (and (>= point-rel 0)
-                                        (- (point) (min point-rel spaces)))))
-                         (setq point-rel nil)))
-
-                     (if point-rel
-                         ;; Point was in the middle of the string we
-                         ;; replaced above, so put it back in the same
-                         ;; relative position, counting from the end.
-                         (goto-char point-rel)))
-
-                 ;; We're doing auto filling.  Just move the marker
-                 ;; to the comment end to ignore any code after the
-                 ;; comment.
-                 (move-marker end (cdr c-lit-limits)))))
+                                    1)))
+                         ;; Insert the filler first to keep marks right.
+                         (insert-char ?x spaces t)
+                         (setq hang-ender-stuck spaces)
+                         (setq point-rel
+                               (and (>= point-rel 0)
+                                    (- (point) (min point-rel spaces)))))
+                     (setq point-rel nil)))
+
+                 (if point-rel
+                     ;; Point was in the middle of the string we
+                     ;; replaced above, so put it back in the same
+                     ;; relative position, counting from the end.
+                     (goto-char point-rel)))
+               ))
 
            (when (<= beg (car c-lit-limits))
              ;; The region includes the comment starter.
@@ -3068,14 +3784,15 @@ command to conveniently insert and align the necessary backslashes."
            ;; inside macros is bogus to begin with since the line
            ;; continuation backslashes aren't handled).
            (save-excursion
-             (c-beginning-of-macro)
-             (beginning-of-line)
-             (if (> (point) beg)
-                 (setq beg (point)))
-             (c-end-of-macro)
-             (forward-line)
-             (if (< (point) end)
-                 (set-marker end (point)))))
+             (c-save-buffer-state ()
+               (c-beginning-of-macro)
+               (beginning-of-line)
+               (if (> (point) beg)
+                   (setq beg (point)))
+               (c-end-of-macro)
+               (forward-line)
+               (if (< (point) end)
+                   (set-marker end (point))))))
 
           (t                           ; Other code.
            ;; Try to avoid comments and macros in the paragraph to
@@ -3192,7 +3909,10 @@ Warning: Regexp from `c-comment-prefix-regexp' doesn't match the comment prefix
          (goto-char tmp-post)
          (skip-syntax-backward "^w ")
          (forward-char (- hang-ender-stuck))
-         (insert-char ?\  hang-ender-stuck t)
+         (if (or fill-paragraph (not auto-fill-spaces))
+             (insert-char ?\  hang-ender-stuck t)
+           (insert auto-fill-spaces)
+           (setq here (- here (- hang-ender-stuck (length auto-fill-spaces)))))
          (delete-char hang-ender-stuck)
          (goto-char here))
        (set-marker tmp-post nil))
@@ -3233,8 +3953,6 @@ Optional prefix ARG means justify paragraph as well."
 (defun c-do-auto-fill ()
   ;; Do automatic filling if not inside a context where it should be
   ;; ignored.
-  ;;
-  ;; This function does not do any hidden buffer changes.
   (let ((c-auto-fill-prefix
         ;; The decision whether the line should be broken is actually
         ;; done in c-indent-new-comment-line, which do-auto-fill
@@ -3274,31 +3992,36 @@ If a fill prefix is specified, it overrides all the above."
        (c-lit-limits c-lit-limits)
        (c-lit-type c-lit-type)
        (c-macro-start c-macro-start))
-    (when (not (eq c-auto-fill-prefix t))
-      ;; Called from do-auto-fill.
-      (unless c-lit-limits
-       (setq c-lit-limits (c-literal-limits nil nil t)))
-      (unless c-lit-type
-       (setq c-lit-type (c-literal-type c-lit-limits)))
-      (if (memq (cond ((c-query-and-set-macro-start) 'cpp)
-                     ((null c-lit-type) 'code)
-                     (t c-lit-type))
-               c-ignore-auto-fill)
-         (setq fill-prefix t)          ; Used as flag in the cond.
-       (if (and (null c-auto-fill-prefix)
-                (eq c-lit-type 'c)
-                (<= (c-point 'bol) (car c-lit-limits)))
-           ;; The adaptive fill function has generated a prefix, but
-           ;; we're on the first line in a block comment so it'll be
-           ;; wrong.  Ignore it to guess a better one below.
-           (setq fill-prefix nil)
-         (when (and (eq c-lit-type 'c++)
-                    (not (string-match "\\`[ \t]*//" (or fill-prefix ""))))
-           ;; Kludge: If the function that adapted the fill prefix
-           ;; doesn't produce the required comment starter for line
-           ;; comments, then we ignore it.
-           (setq fill-prefix nil)))
-       ))
+
+    (c-save-buffer-state ()
+      (when (not (eq c-auto-fill-prefix t))
+       ;; Called from do-auto-fill.
+       (unless c-lit-limits
+         (setq c-lit-limits (c-literal-limits nil nil t)))
+       (unless c-lit-type
+         (setq c-lit-type (c-literal-type c-lit-limits)))
+       (if (memq (cond ((c-query-and-set-macro-start) 'cpp)
+                       ((null c-lit-type) 'code)
+                       (t c-lit-type))
+                 c-ignore-auto-fill)
+           (setq fill-prefix t)        ; Used as flag in the cond.
+         (if (and (null c-auto-fill-prefix)
+                  (eq c-lit-type 'c)
+                  (<= (c-point 'bol) (car c-lit-limits)))
+             ;; The adaptive fill function has generated a prefix, but
+             ;; we're on the first line in a block comment so it'll be
+             ;; wrong.  Ignore it to guess a better one below.
+             (setq fill-prefix nil)
+           (when (and (eq c-lit-type 'c++)
+                      (not (string-match (concat "\\`[ \t]*"
+                                                 c-line-comment-starter)
+                                         (or fill-prefix ""))))
+             ;; Kludge: If the function that adapted the fill prefix
+             ;; doesn't produce the required comment starter for line
+             ;; comments, then we ignore it.
+             (setq fill-prefix nil)))
+         )))
+
     (cond ((eq fill-prefix t)
           ;; A call from do-auto-fill which should be ignored.
           )
@@ -3306,7 +4029,7 @@ If a fill prefix is specified, it overrides all the above."
           ;; A fill-prefix overrides anything.
           (funcall do-line-break)
           (insert-and-inherit fill-prefix))
-         ((progn
+         ((c-save-buffer-state ()
             (unless c-lit-limits
               (setq c-lit-limits (c-literal-limits)))
             (unless c-lit-type
@@ -3440,31 +4163,38 @@ When point is inside a comment, continue it with the appropriate
 comment prefix (see the `c-comment-prefix-regexp' and
 `c-block-comment-prefix' variables for details).  The end of a
 C++-style line comment doesn't count as inside it."
+
   (interactive "*")
-  (let* ((c-lit-limits (c-literal-limits nil nil t))
-        (c-lit-type (c-literal-type c-lit-limits))
+  (let* (c-lit-limits c-lit-type
         (c-macro-start c-macro-start))
-    (if (or (eq c-lit-type 'c)
-           (and (eq c-lit-type 'c++)
-                (< (save-excursion
-                     (skip-chars-forward " \t")
-                     (point))
-                   (1- (cdr (setq c-lit-limits
-                                  (c-collect-line-comments c-lit-limits))))))
-           (and (or (not (looking-at "\\s *$"))
-                    (eq (char-before) ?\\))
-                (c-query-and-set-macro-start)
-                (<= (save-excursion
-                      (goto-char c-macro-start)
-                      (if (looking-at c-opt-cpp-start)
-                          (goto-char (match-end 0)))
-                      (point))
-                   (point))))
+
+    (if (c-save-buffer-state ()
+         (setq c-lit-limits (c-literal-limits nil nil t)
+               c-lit-type (c-literal-type c-lit-limits))
+         (or (eq c-lit-type 'c)
+             (and (eq c-lit-type 'c++)
+                  (< (save-excursion
+                       (skip-chars-forward " \t")
+                       (point))
+                     (1- (cdr (setq c-lit-limits (c-collect-line-comments
+                                                  c-lit-limits))))))
+             (and (or (not (looking-at "\\s *$"))
+                      (eq (char-before) ?\\))
+                  (c-query-and-set-macro-start)
+                  (<= (save-excursion
+                        (goto-char c-macro-start)
+                        (if (looking-at c-opt-cpp-start)
+                            (goto-char (match-end 0)))
+                        (point))
+                      (point)))))
+
        (let ((comment-multi-line t)
              (fill-prefix nil))
          (c-indent-new-comment-line nil t))
+
       (delete-horizontal-space)
       (newline)
+
       ;; c-indent-line may look at the current indentation, so let's
       ;; start out with the same indentation as the previous line.
       (let ((col (save-excursion
@@ -3473,6 +4203,7 @@ C++-style line comment doesn't count as inside it."
                               (= (forward-line -1) 0)))
                   (current-indentation))))
        (indent-to col))
+
       (indent-according-to-mode))))
 
 (defun c-context-open-line ()
index 60dcbd135d847ecd456a975097061064fd87fa74..66bf9a55d79f709b9e956240f52ad2b59e05a47e 100644 (file)
@@ -1,6 +1,7 @@
 ;;; cc-compat.el --- cc-mode compatibility with c-mode.el confusion
 
-;; Copyright (C) 1985,1987,1992-2003, 2004, 2005 Free Software Foundation, Inc.
+;; Copyright (C) 1985,1987,1992-2003, 2004, 2005 Free Software Foundation,
+;; Inc.
 
 ;; Authors:    1998- Martin Stjernholm
 ;;            1994-1999 Barry A. Warsaw
@@ -22,7 +23,7 @@
 ;; GNU General Public License for more details.
 
 ;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING.  If not, write to
+;; along with this program; see the file COPYING.  If not, write to
 ;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 ;; Boston, MA 02110-1301, USA.
 
index a78fd8f7f74a6bc9c0764f638869f9a25346a109..b68e167ffa01d4ee52272bbcd747368eea492cef 100644 (file)
@@ -1,6 +1,7 @@
 ;;; cc-defs.el --- compile time definitions for CC Mode
 
-;; Copyright (C) 1985,1987,1992-2003, 2004, 2005 Free Software Foundation, Inc.
+;; Copyright (C) 1985,1987,1992-2003, 2004, 2005 Free Software Foundation,
+;; Inc.
 
 ;; Authors:    1998- Martin Stjernholm
 ;;             1992-1999 Barry A. Warsaw
@@ -24,7 +25,7 @@
 ;; GNU General Public License for more details.
 
 ;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING.  If not, write to
+;; along with this program; see the file COPYING.  If not, write to
 ;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 ;; Boston, MA 02110-1301, USA.
 
@@ -43,8 +44,8 @@
           load-path)))
     (load "cc-bytecomp" nil t)))
 
-;; `require' in XEmacs doesn't have the third NOERROR argument.
-(condition-case nil (require 'regexp-opt) (file-error nil))
+(eval-when-compile (require 'cl)) ; was (cc-external-require 'cl).  ACM 2005/11/29.
+(cc-external-require 'regexp-opt)
 
 ;; Silence the compiler.
 (cc-bytecomp-defvar c-enable-xemacs-performance-kludge-p) ; In cc-vars.el
 (cc-bytecomp-defvar mark-active)       ; Emacs
 (cc-bytecomp-defvar deactivate-mark)   ; Emacs
 (cc-bytecomp-defvar inhibit-point-motion-hooks) ; Emacs
-(cc-bytecomp-defvar parse-sexp-lookup-properties) ; Emacs 20+
+(cc-bytecomp-defvar parse-sexp-lookup-properties) ; Emacs
 (cc-bytecomp-defvar text-property-default-nonsticky) ; Emacs 21
-(cc-bytecomp-defvar lookup-syntax-properties) ; XEmacs 21
+(cc-bytecomp-defvar lookup-syntax-properties) ; XEmacs
 (cc-bytecomp-defun string-to-syntax)   ; Emacs 21
-(cc-bytecomp-defun regexp-opt-depth)   ; (X)Emacs 20+
 
 \f
 ;; cc-fix.el contains compatibility macros that should be used if
 ;; needed.
 (eval-and-compile
-  (if (or (not (fboundp 'functionp))
-         (not (condition-case nil
-                  (progn (eval '(char-before)) t)
-                (error nil)))
-         (not (condition-case nil
-                  (progn (eval '(char-after)) t)
-                (error nil)))
-         (not (fboundp 'when))
-         (not (fboundp 'unless))
-         (not (fboundp 'regexp-opt))
-         (not (cc-bytecomp-fboundp 'regexp-opt-depth))
-         (/= (regexp-opt-depth "\\(\\(\\)\\)") 2))
-      (cc-load "cc-fix")
-    (defalias 'c-regexp-opt 'regexp-opt)
-    (defalias 'c-regexp-opt-depth 'regexp-opt-depth)))
+  (if (or (/= (regexp-opt-depth "\\(\\(\\)\\)") 2)
+         (not (fboundp 'push)))
+      (cc-load "cc-fix")))
 
 (eval-after-load "font-lock"
   '(if (and (not (featurep 'cc-fix)) ; only load the file once.
               font-lock-keywords)))
       (cc-load "cc-fix")))
 
-(eval-when-compile (require 'cl))
-
 \f
 ;;; Variables also used at compile time.
 
-(defconst c-version "5.30.10"
+(defconst c-version "5.31"
   "CC Mode version number.")
 
 (defconst c-version-sym (intern c-version))
@@ -192,29 +178,29 @@ This variant works around bugs in `eval-when-compile' in various
 The current point is used if POINT isn't specified.  POSITION can be
 one of the following symbols:
 
-`bol'  -- beginning of line
-`eol'  -- end of line
-`bod'  -- beginning of defun
-`eod'  -- end of defun
-`boi'  -- beginning of indentation
-`ionl' -- indentation of next line
-`iopl' -- indentation of previous line
-`bonl' -- beginning of next line
-`eonl' -- end of next line
-`bopl' -- beginning of previous line
-`eopl' -- end of previous line
+`bol'   -- beginning of line
+`eol'   -- end of line
+`bod'   -- beginning of defun
+`eod'   -- end of defun
+`boi'   -- beginning of indentation
+`ionl'  -- indentation of next line
+`iopl'  -- indentation of previous line
+`bonl'  -- beginning of next line
+`eonl'  -- end of next line
+`bopl'  -- beginning of previous line
+`eopl'  -- end of previous line
+`bosws' -- beginning of syntactic whitespace
+`eosws' -- end of syntactic whitespace
 
 If the referenced position doesn't exist, the closest accessible point
-to it is returned.  This function does not modify point or mark.
-
-This function does not do any hidden buffer changes."
+to it is returned.  This function does not modify the point or the mark."
 
   (if (eq (car-safe position) 'quote)
       (let ((position (eval position)))
        (cond
 
         ((eq position 'bol)
-         (if (and (fboundp 'line-beginning-position) (not point))
+         (if (and (cc-bytecomp-fboundp 'line-beginning-position) (not point))
              `(line-beginning-position)
            `(save-excursion
               ,@(if point `((goto-char ,point)))
@@ -222,7 +208,7 @@ This function does not do any hidden buffer changes."
               (point))))
 
         ((eq position 'eol)
-         (if (and (fboundp 'line-end-position) (not point))
+         (if (and (cc-bytecomp-fboundp 'line-end-position) (not point))
              `(line-end-position)
            `(save-excursion
               ,@(if point `((goto-char ,point)))
@@ -248,7 +234,7 @@ This function does not do any hidden buffer changes."
             (point)))
 
         ((eq position 'bopl)
-         (if (and (fboundp 'line-beginning-position) (not point))
+         (if (and (cc-bytecomp-fboundp 'line-beginning-position) (not point))
              `(line-beginning-position 0)
            `(save-excursion
               ,@(if point `((goto-char ,point)))
@@ -256,7 +242,7 @@ This function does not do any hidden buffer changes."
               (point))))
 
         ((eq position 'bonl)
-         (if (and (fboundp 'line-beginning-position) (not point))
+         (if (and (cc-bytecomp-fboundp 'line-beginning-position) (not point))
              `(line-beginning-position 2)
            `(save-excursion
               ,@(if point `((goto-char ,point)))
@@ -264,7 +250,7 @@ This function does not do any hidden buffer changes."
               (point))))
 
         ((eq position 'eopl)
-         (if (and (fboundp 'line-end-position) (not point))
+         (if (and (cc-bytecomp-fboundp 'line-end-position) (not point))
              `(line-end-position 0)
            `(save-excursion
               ,@(if point `((goto-char ,point)))
@@ -273,7 +259,7 @@ This function does not do any hidden buffer changes."
               (point))))
 
         ((eq position 'eonl)
-         (if (and (fboundp 'line-end-position) (not point))
+         (if (and (cc-bytecomp-fboundp 'line-end-position) (not point))
              `(line-end-position 2)
            `(save-excursion
               ,@(if point `((goto-char ,point)))
@@ -295,54 +281,138 @@ This function does not do any hidden buffer changes."
             (back-to-indentation)
             (point)))
 
+        ((eq position 'bosws)
+         `(save-excursion
+            ,@(if point `((goto-char ,point)))
+            (c-backward-syntactic-ws)
+            (point)))
+
+        ((eq position 'eosws)
+         `(save-excursion
+            ,@(if point `((goto-char ,point)))
+            (c-forward-syntactic-ws)
+            (point)))
+
         (t (error "Unknown buffer position requested: %s" position))))
 
-    ;;(message "c-point long expansion")
+    ;; The bulk of this should perhaps be in a function to avoid large
+    ;; expansions, but this case is not used anywhere in CC Mode (and
+    ;; probably not anywhere else either) so we only have it to be on
+    ;; the safe side.
+    (message "Warning: c-point long expansion")
     `(save-excursion
        ,@(if point `((goto-char ,point)))
        (let ((position ,position))
         (cond
-         ((eq position 'bol)  (beginning-of-line))
-         ((eq position 'eol)  (end-of-line))
-         ((eq position 'boi)  (back-to-indentation))
-         ((eq position 'bod)  (c-beginning-of-defun-1))
-         ((eq position 'eod)  (c-end-of-defun-1))
-         ((eq position 'bopl) (forward-line -1))
-         ((eq position 'bonl) (forward-line 1))
-         ((eq position 'eopl) (progn
-                                (beginning-of-line)
-                                (or (bobp) (backward-char))))
-         ((eq position 'eonl) (progn
-                                (forward-line 1)
-                                (end-of-line)))
-         ((eq position 'iopl) (progn
-                                (forward-line -1)
-                                (back-to-indentation)))
-         ((eq position 'ionl) (progn
-                                (forward-line 1)
-                                (back-to-indentation)))
+         ((eq position 'bol)   (beginning-of-line))
+         ((eq position 'eol)   (end-of-line))
+         ((eq position 'boi)   (back-to-indentation))
+         ((eq position 'bod)   (c-beginning-of-defun-1))
+         ((eq position 'eod)   (c-end-of-defun-1))
+         ((eq position 'bopl)  (forward-line -1))
+         ((eq position 'bonl)  (forward-line 1))
+         ((eq position 'eopl)  (progn
+                                 (beginning-of-line)
+                                 (or (bobp) (backward-char))))
+         ((eq position 'eonl)  (progn
+                                 (forward-line 1)
+                                 (end-of-line)))
+         ((eq position 'iopl)  (progn
+                                 (forward-line -1)
+                                 (back-to-indentation)))
+         ((eq position 'ionl)  (progn
+                                 (forward-line 1)
+                               (back-to-indentation)))
+         ((eq position 'bosws) (c-backward-syntactic-ws))
+         ((eq position 'eosws) (c-forward-syntactic-ws))
          (t (error "Unknown buffer position requested: %s" position))))
        (point))))
 
+(defmacro c-region-is-active-p ()
+  ;; Return t when the region is active.  The determination of region
+  ;; activeness is different in both Emacs and XEmacs.
+  (if (cc-bytecomp-fboundp 'region-active-p)
+      ;; XEmacs.
+      '(region-active-p)
+    ;; Emacs.
+    'mark-active))
+
+(defmacro c-set-region-active (activate)
+  ;; Activate the region if ACTIVE is non-nil, deactivate it
+  ;; otherwise.  Covers the differences between Emacs and XEmacs.
+  (if (cc-bytecomp-fboundp 'zmacs-activate-region)
+      ;; XEmacs.
+      `(if ,activate
+          (zmacs-activate-region)
+        (zmacs-deactivate-region))
+    ;; Emacs.
+    `(setq mark-active ,activate)))
+
+(defmacro c-delete-and-extract-region (start end)
+  "Delete the text between START and END and return it."
+  (if (cc-bytecomp-fboundp 'delete-and-extract-region)
+      ;; Emacs 21.1 and later
+      `(delete-and-extract-region ,start ,end)
+    ;; XEmacs and Emacs 20.x
+    `(prog1
+       (buffer-substring ,start ,end)
+       (delete-region ,start ,end))))
+
 (defmacro c-safe (&rest body)
   ;; safely execute BODY, return nil if an error occurred
-  ;;
-  ;; This function does not do any hidden buffer changes.
   `(condition-case nil
        (progn ,@body)
      (error nil)))
 (put 'c-safe 'lisp-indent-function 0)
 
+(defmacro c-int-to-char (integer)
+  ;; In GNU Emacs, a character is an integer.  In XEmacs, a character is a
+  ;; type distinct from an integer.  Sometimes we need to convert integers to
+  ;; characters.  `c-int-to-char' makes this conversion, if necessary.
+  (if (fboundp 'int-to-char)
+      `(int-to-char ,integer)
+    integer))
+
+(defmacro c-sentence-end ()
+  ;; Get the regular expression `sentence-end'.
+  (if (cc-bytecomp-fboundp 'sentence-end)
+      ;; Emacs 22:
+      `(sentence-end)
+    ;; Emacs <22 + XEmacs
+    `sentence-end))
+
+(defmacro c-default-value-sentence-end ()
+  ;; Get the default value of the variable sentence end.
+  (if (cc-bytecomp-fboundp 'sentence-end)
+      ;; Emacs 22:
+      `(let (sentence-end) (sentence-end))
+    ;; Emacs <22 + XEmacs
+    `(default-value 'sentence-end)))
+
 ;; The following is essentially `save-buffer-state' from lazy-lock.el.
 ;; It ought to be a standard macro.
 (defmacro c-save-buffer-state (varlist &rest body)
   "Bind variables according to VARLIST (in `let*' style) and eval BODY,
 then restore the buffer state under the assumption that no significant
-modification has been made.  A change is considered significant if it
-affects the buffer text in any way that isn't completely restored
-again.  Changes in text properties like `face' or `syntax-table' are
-considered insignificant.  This macro allows text properties to be
-changed, even in a read-only buffer.
+modification has been made in BODY.  A change is considered
+significant if it affects the buffer text in any way that isn't
+completely restored again.  Changes in text properties like `face' or
+`syntax-table' are considered insignificant.  This macro allows text
+properties to be changed, even in a read-only buffer.
+
+This macro should be placed around all calculations which set
+\"insignificant\" text properties in a buffer, even when the buffer is
+known to be writeable.  That way, these text properties remain set
+even if the user undoes the command which set them.
+
+This macro should ALWAYS be placed around \"temporary\" internal buffer
+changes \(like adding a newline to calculate a text-property then
+deleting it again\), so that the user never sees them on his
+`buffer-undo-list'.  See also `c-tentative-buffer-changes'.
+
+However, any user-visible changes to the buffer \(like auto-newlines\)
+must not be within a `c-save-buffer-state', since the user then
+wouldn't be able to undo them.
 
 The return value is the value of the last form in BODY."
   `(let* ((modified (buffer-modified-p)) (buffer-undo-list t)
@@ -350,12 +420,80 @@ The return value is the value of the last form in BODY."
          before-change-functions after-change-functions
          deactivate-mark
          ,@varlist)
-     (prog1 (progn ,@body)
+     (unwind-protect
+        (progn ,@body)
        (and (not modified)
            (buffer-modified-p)
            (set-buffer-modified-p nil)))))
 (put 'c-save-buffer-state 'lisp-indent-function 1)
 
+(defmacro c-tentative-buffer-changes (&rest body)
+  "Eval BODY and optionally restore the buffer contents to the state it
+was in before BODY.  Any changes are kept if the last form in BODY
+returns non-nil.  Otherwise it's undone using the undo facility, and
+various other buffer state that might be affected by the changes is
+restored.  That includes the current buffer, point, mark, mark
+activation \(similar to `save-excursion'), and the modified state.
+The state is also restored if BODY exits nonlocally.
+
+If BODY makes a change that unconditionally is undone then wrap this
+macro inside `c-save-buffer-state'.  That way the change can be done
+even when the buffer is read-only, and without interference from
+various buffer change hooks."
+  `(let (-tnt-chng-keep
+        -tnt-chng-state)
+     (unwind-protect
+        ;; Insert an undo boundary for use with `undo-more'.  We
+        ;; don't use `undo-boundary' since it doesn't insert one
+        ;; unconditionally.
+        (setq buffer-undo-list (cons nil buffer-undo-list)
+              -tnt-chng-state (c-tnt-chng-record-state)
+              -tnt-chng-keep (progn ,@body))
+       (c-tnt-chng-cleanup -tnt-chng-keep -tnt-chng-state))))
+(put 'c-tentative-buffer-changes 'lisp-indent-function 0)
+
+(defun c-tnt-chng-record-state ()
+  ;; Used internally in `c-tentative-buffer-changes'.
+  (vector buffer-undo-list             ; 0
+         (current-buffer)              ; 1
+         ;; No need to use markers for the point and mark; if the
+         ;; undo got out of synch we're hosed anyway.
+         (point)                       ; 2
+         (mark t)                      ; 3
+         (c-region-is-active-p)        ; 4
+         (buffer-modified-p)))         ; 5
+
+(defun c-tnt-chng-cleanup (keep saved-state)
+  ;; Used internally in `c-tentative-buffer-changes'.
+
+  (let ((saved-undo-list (elt saved-state 0)))
+    (if (eq buffer-undo-list saved-undo-list)
+       ;; No change was done afterall.
+       (setq buffer-undo-list (cdr saved-undo-list))
+
+      (if keep
+         ;; Find and remove the undo boundary.
+         (let ((p buffer-undo-list))
+           (while (not (eq (cdr p) saved-undo-list))
+             (setq p (cdr p)))
+           (setcdr p (cdr saved-undo-list)))
+
+       ;; `primitive-undo' will remove the boundary.
+       (setq saved-undo-list (cdr saved-undo-list))
+       (let ((undo-in-progress t))
+         (while (not (eq (setq buffer-undo-list
+                               (primitive-undo 1 buffer-undo-list))
+                         saved-undo-list))))
+
+       (when (buffer-live-p (elt saved-state 1))
+         (set-buffer (elt saved-state 1))
+         (goto-char (elt saved-state 2))
+         (set-mark (elt saved-state 3))
+         (c-set-region-active (elt saved-state 4))
+         (and (not (elt saved-state 5))
+              (buffer-modified-p)
+              (set-buffer-modified-p nil)))))))
+
 (defmacro c-forward-syntactic-ws (&optional limit)
   "Forward skip over syntactic whitespace.
 Syntactic whitespace is defined as whitespace characters, comments,
@@ -402,91 +540,127 @@ fails for any reason.
 This is like `forward-sexp' except that it isn't interactive and does
 not do any user friendly adjustments of the point and that it isn't
 susceptible to user configurations such as disabling of signals in
-certain situations.
-
-This function does not do any hidden buffer changes."
+certain situations."
   (or count (setq count 1))
-  `(goto-char (or (scan-sexps (point) ,count)
-                 ,(if (numberp count)
-                      (if (> count 0) `(point-max) `(point-min))
-                    `(if (> ,count 0) (point-max) (point-min))))))
+  `(goto-char (scan-sexps (point) ,count)))
 
 (defmacro c-backward-sexp (&optional count)
   "See `c-forward-sexp' and reverse directions."
   (or count (setq count 1))
   `(c-forward-sexp ,(if (numberp count) (- count) `(- ,count))))
 
-(defmacro c-safe-scan-lists (from count depth)
-  "Like `scan-lists' but returns nil instead of signaling errors.
-
-This function does not do any hidden buffer changes."
-  (if (featurep 'xemacs)
-      `(scan-lists ,from ,count ,depth nil t)
-    `(c-safe (scan-lists ,from ,count ,depth))))
+(defmacro c-safe-scan-lists (from count depth &optional limit)
+  "Like `scan-lists' but returns nil instead of signalling errors
+for unbalanced parens.
+
+A limit for the search may be given.  FROM is assumed to be on the
+right side of it."
+  (let ((res (if (featurep 'xemacs)
+                `(scan-lists ,from ,count ,depth nil t)
+              `(c-safe (scan-lists ,from ,count ,depth)))))
+    (if limit
+       `(save-restriction
+          ,(if (numberp count)
+               (if (< count 0)
+                   `(narrow-to-region ,limit (point-max))
+                 `(narrow-to-region (point-min) ,limit))
+             `(if (< ,count 0)
+                  (narrow-to-region ,limit (point-max))
+                (narrow-to-region (point-min) ,limit)))
+          ,res)
+      res)))
 
 \f
 ;; Wrappers for common scan-lists cases, mainly because it's almost
 ;; impossible to get a feel for how that function works.
 
-(defmacro c-up-list-forward (&optional pos)
+(defmacro c-up-list-forward (&optional pos limit)
   "Return the first position after the list sexp containing POS,
 or nil if no such position exists.  The point is used if POS is left out.
 
-This function does not do any hidden buffer changes."
-  `(c-safe-scan-lists ,(or pos `(point)) 1 1))
+A limit for the search may be given.  The start position is assumed to
+be before it."
+  `(c-safe-scan-lists ,(or pos `(point)) 1 1 ,limit))
 
-(defmacro c-up-list-backward (&optional pos)
+(defmacro c-up-list-backward (&optional pos limit)
   "Return the position of the start of the list sexp containing POS,
 or nil if no such position exists.  The point is used if POS is left out.
 
-This function does not do any hidden buffer changes."
-  `(c-safe-scan-lists ,(or pos `(point)) -1 1))
+A limit for the search may be given.  The start position is assumed to
+be after it."
+  `(c-safe-scan-lists ,(or pos `(point)) -1 1 ,limit))
 
-(defmacro c-down-list-forward (&optional pos)
+(defmacro c-down-list-forward (&optional pos limit)
   "Return the first position inside the first list sexp after POS,
 or nil if no such position exists.  The point is used if POS is left out.
 
-This function does not do any hidden buffer changes."
-  `(c-safe-scan-lists ,(or pos `(point)) 1 -1))
+A limit for the search may be given.  The start position is assumed to
+be before it."
+  `(c-safe-scan-lists ,(or pos `(point)) 1 -1 ,limit))
 
-(defmacro c-down-list-backward (&optional pos)
+(defmacro c-down-list-backward (&optional pos limit)
   "Return the last position inside the last list sexp before POS,
 or nil if no such position exists.  The point is used if POS is left out.
 
-This function does not do any hidden buffer changes."
-  `(c-safe-scan-lists ,(or pos `(point)) -1 -1))
+A limit for the search may be given.  The start position is assumed to
+be after it."
+  `(c-safe-scan-lists ,(or pos `(point)) -1 -1 ,limit))
 
-(defmacro c-go-up-list-forward (&optional pos)
+(defmacro c-go-up-list-forward (&optional pos limit)
   "Move the point to the first position after the list sexp containing POS,
-or the point if POS is left out.  Return t if such a position exists,
-otherwise nil is returned and the point isn't moved.
-
-This function does not do any hidden buffer changes."
-  `(c-safe (goto-char (scan-lists ,(or pos `(point)) 1 1)) t))
-
-(defmacro c-go-up-list-backward (&optional pos)
+or containing the point if POS is left out.  Return t if such a
+position exists, otherwise nil is returned and the point isn't moved.
+
+A limit for the search may be given.  The start position is assumed to
+be before it."
+  (let ((res `(c-safe (goto-char (scan-lists ,(or pos `(point)) 1 1)) t)))
+    (if limit
+       `(save-restriction
+          (narrow-to-region (point-min) ,limit)
+          ,res)
+      res)))
+
+(defmacro c-go-up-list-backward (&optional pos limit)
   "Move the point to the position of the start of the list sexp containing POS,
-or the point if POS is left out.  Return t if such a position exists,
-otherwise nil is returned and the point isn't moved.
-
-This function does not do any hidden buffer changes."
-  `(c-safe (goto-char (scan-lists ,(or pos `(point)) -1 1)) t))
-
-(defmacro c-go-down-list-forward (&optional pos)
+or containing the point if POS is left out.  Return t if such a
+position exists, otherwise nil is returned and the point isn't moved.
+
+A limit for the search may be given.  The start position is assumed to
+be after it."
+  (let ((res `(c-safe (goto-char (scan-lists ,(or pos `(point)) -1 1)) t)))
+    (if limit
+       `(save-restriction
+          (narrow-to-region ,limit (point-max))
+          ,res)
+      res)))
+
+(defmacro c-go-down-list-forward (&optional pos limit)
   "Move the point to the first position inside the first list sexp after POS,
-or the point if POS is left out.  Return t if such a position exists,
-otherwise nil is returned and the point isn't moved.
-
-This function does not do any hidden buffer changes."
-  `(c-safe (goto-char (scan-lists ,(or pos `(point)) 1 -1)) t))
-
-(defmacro c-go-down-list-backward (&optional pos)
+or before the point if POS is left out.  Return t if such a position
+exists, otherwise nil is returned and the point isn't moved.
+
+A limit for the search may be given.  The start position is assumed to
+be before it."
+  (let ((res `(c-safe (goto-char (scan-lists ,(or pos `(point)) 1 -1)) t)))
+    (if limit
+       `(save-restriction
+          (narrow-to-region (point-min) ,limit)
+          ,res)
+      res)))
+
+(defmacro c-go-down-list-backward (&optional pos limit)
   "Move the point to the last position inside the last list sexp before POS,
-or the point if POS is left out.  Return t if such a position exists,
-otherwise nil is returned and the point isn't moved.
-
-This function does not do any hidden buffer changes."
-  `(c-safe (goto-char (scan-lists ,(or pos `(point)) -1 -1)) t))
+or before the point if POS is left out.  Return t if such a position
+exists, otherwise nil is returned and the point isn't moved.
+
+A limit for the search may be given.  The start position is assumed to
+be after it."
+  (let ((res `(c-safe (goto-char (scan-lists ,(or pos `(point)) -1 -1)) t)))
+    (if limit
+       `(save-restriction
+          (narrow-to-region ,limit (point-max))
+          ,res)
+      res)))
 
 \f
 (defmacro c-beginning-of-defun-1 ()
@@ -501,8 +675,6 @@ This function does not do any hidden buffer changes."
   ;; This is really a bit too large to be a macro but that isn't a
   ;; problem as long as it only is used in one place in
   ;; `c-parse-state'.
-  ;;
-  ;; This function does not do any hidden buffer changes.
 
   `(progn
      (if (and ,(cc-bytecomp-fboundp 'buffer-syntactic-context-depth)
@@ -542,31 +714,84 @@ This function does not do any hidden buffer changes."
          (looking-at defun-prompt-regexp)
          (goto-char (match-end 0)))))
 
+\f
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; V i r t u a l   S e m i c o l o n s 
+;;
+;; In most CC Mode languages, statements are terminated explicitly by
+;; semicolons or closing braces.  In some of the CC modes (currently only AWK
+;; Mode (April 2004)), statements are (or can be) terminated by EOLs.  Such a
+;; statement is said to be terminated by a "virtual semicolon" (VS).  A
+;; statement terminated by an actual semicolon or brace is never considered to
+;; have a VS.
+;;
+;; The indentation engine (or whatever) tests for a VS at a specific position
+;; by invoking the macro `c-at-vsemi-p', which in its turn calls the mode
+;; specific function (if any) which is the value of the language variable
+;; `c-at-vsemi-p-fn'.  The actual details of what constitutes a VS in a
+;; language are thus encapsulated in code specific to that language
+;; (e.g. cc-awk.el).  `c-at-vsemi-p' returns non-nil if point (or the optional
+;; parameter POS) is at a VS, nil otherwise.
+;;
+;; The language specific function might well do extensive analysis of the
+;; source text, and may use a cacheing scheme to speed up repeated calls.
+;;
+;; The "virtual semicolon" lies just after the last non-ws token on the line.
+;; Like POINT, it is considered to lie between two characters.  For example,
+;; at the place shown in the following AWK source line:
+;;
+;;          kbyte = 1024             # 1000 if you're not picky
+;;                      ^
+;;                      |
+;;              Virtual Semicolon
+;;
+;; In addition to `c-at-vsemi-p-fn', a mode may need to supply a function for
+;; `c-vsemi-status-unknown-p-fn'.  The macro `c-vsemi-status-unknown-p' is a
+;; rather recondite kludge.  It exists because the function
+;; `c-beginning-of-statement-1' sometimes tests for VSs as an optimisation,
+;; but `c-at-vsemi-p' might well need to call `c-beginning-of-statement-1' in
+;; its calculations, thus potentially leading to infinite recursion.
+;;
+;; The macro `c-vsemi-status-unknown-p' resolves this problem; it may return
+;; non-nil at any time; returning nil is a guarantee that an immediate
+;; invocation of `c-at-vsemi-p' at point will NOT call
+;; `c-beginning-of-statement-1'.  `c-vsemi-status-unknown-p' may not itself
+;; call `c-beginning-of-statement-1'.
+;;
+;; The macro `c-vsemi-status-unknown-p' will typically check the cacheing
+;; scheme used by the `c-at-vsemp-p-fn', hence the name - the status is
+;; "unknown" if there is no cache entry current for the line. 
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defmacro c-at-vsemi-p (&optional pos)
+  ;; Is there a virtual semicolon (not a real one or a }) at POS (defaults to
+  ;; point)?  Always returns nil for languages which don't have Virtual
+  ;; semicolons.
+  ;; This macro might do hidden buffer changes.
+  `(if c-at-vsemi-p-fn
+       (funcall c-at-vsemi-p-fn ,@(if pos `(,pos)))))
+
+(defmacro c-vsemi-status-unknown-p ()
+  ;; Return NIL only if it can be guaranteed that an immediate
+  ;; (c-at-vsemi-p) will NOT call c-beginning-of-statement-1.  Otherwise,
+  ;; return non-nil.  (See comments above).  The function invoked by this
+  ;; macro MUST NOT UNDER ANY CIRCUMSTANCES itself call
+  ;; c-beginning-of-statement-1.
+  ;; Languages which don't have EOL terminated statements always return NIL
+  ;; (they _know_ there's no vsemi ;-).
+  `(if c-vsemi-status-unknown-p-fn (funcall c-vsemi-status-unknown-p-fn)))
+
+\f
 (defmacro c-benign-error (format &rest args)
   ;; Formats an error message for the echo area and dings, i.e. like
   ;; `error' but doesn't abort.
-  ;;
-  ;; This function does not do any hidden buffer changes.
   `(progn
      (message ,format ,@args)
      (ding)))
 
-(defmacro c-update-modeline ()
-  ;; set the c-auto-hungry-string for the correct designation on the modeline
-  ;;
-  ;; This function does not do any hidden buffer changes.
-  `(progn
-     (setq c-auto-hungry-string
-          (if c-auto-newline
-              (if c-hungry-delete-key "/ah" "/a")
-            (if c-hungry-delete-key "/h" nil)))
-     (force-mode-line-update)))
-
 (defmacro c-with-syntax-table (table &rest code)
   ;; Temporarily switches to the specified syntax table in a failsafe
   ;; way to execute code.
-  ;;
-  ;; This function does not do any hidden buffer changes.
   `(let ((c-with-syntax-table-orig-table (syntax-table)))
      (unwind-protect
         (progn
@@ -578,9 +803,7 @@ This function does not do any hidden buffer changes."
 (defmacro c-skip-ws-forward (&optional limit)
   "Skip over any whitespace following point.
 This function skips over horizontal and vertical whitespace and line
-continuations.
-
-This function does not do any hidden buffer changes."
+continuations."
   (if limit
       `(let ((limit (or ,limit (point-max))))
         (while (progn
@@ -601,9 +824,7 @@ This function does not do any hidden buffer changes."
 (defmacro c-skip-ws-backward (&optional limit)
   "Skip over any whitespace preceding point.
 This function skips over horizontal and vertical whitespace and line
-continuations.
-
-This function does not do any hidden buffer changes."
+continuations."
   (if limit
       `(let ((limit (or ,limit (point-min))))
         (while (progn
@@ -624,9 +845,7 @@ This function does not do any hidden buffer changes."
 
 (defmacro c-major-mode-is (mode)
   "Return non-nil if the current CC Mode major mode is MODE.
-MODE is either a mode symbol or a list of mode symbols.
-
-This function does not do any hidden buffer changes."
+MODE is either a mode symbol or a list of mode symbols."
 
   (if c-langs-are-parametric
       ;; Inside a `c-lang-defconst'.
@@ -643,28 +862,9 @@ This function does not do any hidden buffer changes."
             (memq c-buffer-is-cc-mode mode)
           (eq c-buffer-is-cc-mode mode))))))
 
-(defmacro c-mode-is-new-awk-p ()
-  ;; Is the current mode the "new" awk mode?  It is important for
-  ;; (e.g.) the cc-engine functions do distinguish between the old and
-  ;; new awk-modes.
-  '(and (c-major-mode-is 'awk-mode)
-       (memq 'syntax-properties c-emacs-features)))
-
-(defmacro c-parse-sexp-lookup-properties ()
-  ;; Return the value of the variable that says whether the
-  ;; syntax-table property affects the sexp routines.  Always return
-  ;; nil in (X)Emacsen without support for that.
-  ;;
-  ;; This function does not do any hidden buffer changes.
-  (cond ((cc-bytecomp-boundp 'parse-sexp-lookup-properties)
-        `parse-sexp-lookup-properties)
-       ((cc-bytecomp-boundp 'lookup-syntax-properties)
-        `lookup-syntax-properties)
-       (t nil)))
-
 \f
 ;; Macros/functions to handle so-called "char properties", which are
-;; properties set on a single character and that never spreads to any
+;; properties set on a single character and that never spread to any
 ;; other characters.
 
 (eval-and-compile
@@ -719,6 +919,8 @@ This function does not do any hidden buffer changes."
   ;;
   ;; If there's a `text-property-default-nonsticky' variable (Emacs
   ;; 21) then it's assumed that the property is present on it.
+  ;;
+  ;; This macro does a hidden buffer change.
   (setq property (eval property))
   (if (or c-use-extents
          (not (cc-bytecomp-boundp 'text-property-default-nonsticky)))
@@ -761,6 +963,8 @@ This function does not do any hidden buffer changes."
   ;; Remove the given property on the character at POS if it's been put
   ;; there by `c-put-char-property'.  PROPERTY is assumed to be
   ;; constant.
+  ;;
+  ;; This macro does a hidden buffer change.
   (setq property (eval property))
   (cond (c-use-extents
         ;; XEmacs.
@@ -785,6 +989,8 @@ This function does not do any hidden buffer changes."
   ;; lists of the `rear-nonsticky' properties in the region, if such
   ;; are used.  Thus it should not be used for common properties like
   ;; `syntax-table'.
+  ;;
+  ;; This macro does hidden buffer changes.
   (setq property (eval property))
   (if c-use-extents
       ;; XEmacs.
@@ -794,13 +1000,45 @@ This function does not do any hidden buffer changes."
     ;; Emacs.
     `(remove-text-properties ,from ,to '(,property nil))))
 
+\f
+;; Macros to put overlays (Emacs) or extents (XEmacs) on buffer text.
+;; For our purposes, these are characterized by being possible to
+;; remove again without affecting the other text properties in the
+;; buffer that got overridden when they were put.
+
+(defmacro c-put-overlay (from to property value)
+  ;; Put an overlay/extent covering the given range in the current
+  ;; buffer.  It's currently undefined whether it's front/end sticky
+  ;; or not.  The overlay/extent object is returned.
+  (if (cc-bytecomp-fboundp 'make-overlay)
+      ;; Emacs.
+      `(let ((ol (make-overlay ,from ,to)))
+        (overlay-put ol ,property ,value)
+        ol)
+    ;; XEmacs.
+    `(let ((ext (make-extent ,from ,to)))
+       (set-extent-property ext ,property ,value)
+       ext)))
+
+(defmacro c-delete-overlay (overlay)
+  ;; Deletes an overlay/extent object previously retrieved using
+  ;; `c-put-overlay'.
+  (if (cc-bytecomp-fboundp 'make-overlay)
+      ;; Emacs.
+      `(delete-overlay ,overlay)
+    ;; XEmacs.
+    `(delete-extent ,overlay)))
+
 \f
 ;; Make edebug understand the macros.
 (eval-after-load "edebug"
   '(progn
+     (def-edebug-spec cc-eval-when-compile t)
      (def-edebug-spec c-point t)
+     (def-edebug-spec c-set-region-active t)
      (def-edebug-spec c-safe t)
      (def-edebug-spec c-save-buffer-state let*)
+     (def-edebug-spec c-tentative-buffer-changes t)
      (def-edebug-spec c-forward-syntactic-ws t)
      (def-edebug-spec c-backward-syntactic-ws t)
      (def-edebug-spec c-forward-sexp t)
@@ -820,7 +1058,8 @@ This function does not do any hidden buffer changes."
      (def-edebug-spec c-get-char-property t)
      (def-edebug-spec c-clear-char-property t)
      (def-edebug-spec c-clear-char-properties t)
-     (def-edebug-spec cc-eval-when-compile t)))
+     (def-edebug-spec c-put-overlay t)
+     (def-edebug-spec c-delete-overlay t)))
 
 \f
 ;;; Functions.
@@ -847,25 +1086,23 @@ This function does not do any hidden buffer changes."
 
 (defsubst c-mark-<-as-paren (pos)
   ;; Mark the "<" character at POS as an sexp list opener using the
-  ;; syntax-table property.  Note that Emacs 19 and XEmacs <= 20
-  ;; doesn't support syntax properties, so this function might not
-  ;; have any effect.
+  ;; syntax-table property.
+  ;;
+  ;; This function does a hidden buffer change.
   (c-put-char-property pos 'syntax-table c-<-as-paren-syntax))
 
 (defconst c->-as-paren-syntax '(5 . ?<))
 
 (defsubst c-mark->-as-paren (pos)
   ;; Mark the ">" character at POS as an sexp list closer using the
-  ;; syntax-table property.  Note that Emacs 19 and XEmacs <= 20
-  ;; doesn't support syntax properties, so this function might not
-  ;; have any effect.
+  ;; syntax-table property.
+  ;;
+  ;; This function does a hidden buffer change.
   (c-put-char-property pos 'syntax-table c->-as-paren-syntax))
 
 (defsubst c-intersect-lists (list alist)
   ;; return the element of ALIST that matches the first element found
   ;; in LIST.  Uses assq.
-  ;;
-  ;; This function does not do any hidden buffer changes.
   (let (match)
     (while (and list
                (not (setq match (assq (car list) alist))))
@@ -875,41 +1112,33 @@ This function does not do any hidden buffer changes."
 (defsubst c-lookup-lists (list alist1 alist2)
   ;; first, find the first entry from LIST that is present in ALIST1,
   ;; then find the entry in ALIST2 for that entry.
-  ;;
-  ;; This function does not do any hidden buffer changes.
   (assq (car (c-intersect-lists list alist1)) alist2))
 
 (defsubst c-langelem-sym (langelem)
   "Return the syntactic symbol in LANGELEM.
 
-LANGELEM is a syntactic element, i.e. either a cons cell on the
-\"old\" form given as the first argument to lineup functions or a list
-on the \"new\" form as used in `c-syntactic-element'.
-
-This function does not do any hidden buffer changes."
+LANGELEM is either a cons cell on the \"old\" form given as the first
+argument to lineup functions or a syntactic element on the \"new\"
+form as used in `c-syntactic-element'."
   (car langelem))
 
 (defsubst c-langelem-pos (langelem)
-  "Return the (primary) anchor position in LANGELEM, or nil if there is none.
-
-LANGELEM is a syntactic element, i.e. either a cons cell on the
-\"old\" form given as the first argument to lineup functions or a list
-on the \"new\" form as used in `c-syntactic-element'.
+  "Return the anchor position in LANGELEM, or nil if there is none.
 
-This function does not do any hidden buffer changes."
+LANGELEM is either a cons cell on the \"old\" form given as the first
+argument to lineup functions or a syntactic element on the \"new\"
+form as used in `c-syntactic-element'."
   (if (consp (cdr langelem))
       (car-safe (cdr langelem))
     (cdr langelem)))
 
 (defun c-langelem-col (langelem &optional preserve-point)
-  "Return the column of the (primary) anchor position in LANGELEM.
-Leave point at that position unless PRESERVE-POINT is non-nil.
+  "Return the column of the anchor position in LANGELEM.
+Also move the point to that position unless PRESERVE-POINT is non-nil.
 
-LANGELEM is a syntactic element, i.e. either a cons cell on the
-\"old\" form given as the first argument to lineup functions or a list
-on the \"new\" form as used in `c-syntactic-element'.
-
-This function does not do any hidden buffer changes."
+LANGELEM is either a cons cell on the \"old\" form given as the first
+argument to lineup functions or a syntactic element on the \"new\"
+form as used in `c-syntactic-element'."
   (let ((pos (c-langelem-pos langelem))
        (here (point)))
     (if pos
@@ -923,38 +1152,18 @@ This function does not do any hidden buffer changes."
 (defsubst c-langelem-2nd-pos (langelem)
   "Return the secondary position in LANGELEM, or nil if there is none.
 
-LANGELEM is a syntactic element, typically on the \"new\" form as used
-in `c-syntactic-element'.  It may be on the \"old\" form that is used
-as the first argument to lineup functions, but then the returned value
-always will be nil.
-
-This function does not do any hidden buffer changes."
+LANGELEM is typically a syntactic element on the \"new\" form as used
+in `c-syntactic-element'.  It may also be a cons cell as passed in the
+first argument to lineup functions, but then the returned value always
+will be nil."
   (car-safe (cdr-safe (cdr-safe langelem))))
 
 (defsubst c-keep-region-active ()
   ;; Do whatever is necessary to keep the region active in XEmacs.
   ;; This is not needed for Emacs.
-  ;;
-  ;; This function does not do any hidden buffer changes.
   (and (boundp 'zmacs-region-stays)
        (setq zmacs-region-stays t)))
 
-(defsubst c-region-is-active-p ()
-  ;; Return t when the region is active.  The determination of region
-  ;; activeness is different in both Emacs and XEmacs.
-  ;;
-  ;; This function does not do any hidden buffer changes.
-  (cond
-   ;; XEmacs
-   ((and (fboundp 'region-active-p)
-        (boundp 'zmacs-regions)
-        zmacs-regions)
-    (region-active-p))
-   ;; Emacs
-   ((boundp 'mark-active) mark-active)
-   ;; fallback; shouldn't get here
-   (t (mark t))))
-
 (put 'c-mode    'c-mode-prefix "c-")
 (put 'c++-mode  'c-mode-prefix "c++-")
 (put 'objc-mode 'c-mode-prefix "objc-")
@@ -965,9 +1174,7 @@ This function does not do any hidden buffer changes."
 
 (defsubst c-mode-symbol (suffix)
   "Prefix the current mode prefix (e.g. \"c-\") to SUFFIX and return
-the corresponding symbol.
-
-This function does not do any hidden buffer changes."
+the corresponding symbol."
   (or c-buffer-is-cc-mode
       (error "Not inside a CC Mode based mode"))
   (let ((mode-prefix (get c-buffer-is-cc-mode 'c-mode-prefix)))
@@ -978,16 +1185,12 @@ This function does not do any hidden buffer changes."
 
 (defsubst c-mode-var (suffix)
   "Prefix the current mode prefix (e.g. \"c-\") to SUFFIX and return
-the value of the variable with that name.
-
-This function does not do any hidden buffer changes."
+the value of the variable with that name."
   (symbol-value (c-mode-symbol suffix)))
 
 (defsubst c-got-face-at (pos faces)
   "Return non-nil if position POS in the current buffer has any of the
-faces in the list FACES.
-
-This function does not do any hidden buffer changes."
+faces in the list FACES."
   (let ((pos-faces (get-text-property pos 'face)))
     (if (consp pos-faces)
        (progn
@@ -1003,31 +1206,72 @@ This function does not do any hidden buffer changes."
   ;; face objects (while it's only their names that are used just
   ;; about anywhere else) without providing a predicate that tests
   ;; face names.
-  ;;
-  ;; This function does not do any hidden buffer changes.
   (memq facename (face-list)))
 
+(defun c-concat-separated (list separator)
+  "Like `concat' on LIST, but separate each element with SEPARATOR.
+Notably, null elements in LIST are ignored."
+  (mapconcat 'identity (delete nil (append list nil)) separator))
+
 (defun c-make-keywords-re (adorn list &optional mode)
   "Make a regexp that matches all the strings the list.
-Duplicates in the list are removed.  The resulting regexp may contain
-zero or more submatch expressions.
+Duplicates and nil elements in the list are removed.  The resulting
+regexp may contain zero or more submatch expressions.
+
+If ADORN is t there will be at least one submatch and the first
+surrounds the matched alternative, and the regexp will also not match
+a prefix of any identifier.  Adorned regexps cannot be appended.  The
+language variable `c-nonsymbol-key' is used to make the adornment.
+
+A value 'appendable for ADORN is like above, but all alternatives in
+the list that end with a word constituent char will have \\> appended
+instead, so that the regexp remains appendable.  Note that this
+variant doesn't always guarantee that an identifier prefix isn't
+matched since the symbol constituent '_' is normally considered a
+nonword token by \\>.
 
-If ADORN is non-nil there will be at least one submatch and the first
-matches the whole keyword, and the regexp will also not match a prefix
-of any identifier.  Adorned regexps cannot be appended.  The language
-variable `c-nonsymbol-key' is used to make the adornment.  The
-optional MODE specifies the language to get it in.  The default is the
-current language (taken from `c-buffer-is-cc-mode')."
+The optional MODE specifies the language to get `c-nonsymbol-key' from
+when it's needed.  The default is the current language taken from
+`c-buffer-is-cc-mode'."
 
   (let (unique)
     (dolist (elt list)
       (unless (member elt unique)
        (push elt unique)))
-    (setq list unique))
+    (setq list (delete nil unique)))
   (if list
-      (let ((re (c-regexp-opt list)))
-
-       ;; Emacs < 21 and XEmacs (all versions so far) has a buggy
+      (let (re)
+
+       (if (eq adorn 'appendable)
+           ;; This is kludgy but it works: Search for a string that
+           ;; doesn't occur in any word in LIST.  Append it to all
+           ;; the alternatives where we want to add \>.  Run through
+           ;; `regexp-opt' and then replace it with \>.
+           (let ((unique "") pos)
+             (while (let (found)
+                      (setq unique (concat unique "@")
+                            pos list)
+                      (while (and pos
+                                  (if (string-match unique (car pos))
+                                      (progn (setq found t)
+                                             nil)
+                                    t))
+                        (setq pos (cdr pos)))
+                      found))
+             (setq pos list)
+             (while pos
+               (if (string-match "\\w\\'" (car pos))
+                   (setcar pos (concat (car pos) unique)))
+               (setq pos (cdr pos)))
+             (setq re (regexp-opt list))
+             (setq pos 0)
+             (while (string-match unique re pos)
+               (setq pos (+ (match-beginning 0) 2)
+                     re (replace-match "\\>" t t re))))
+
+         (setq re (regexp-opt list)))
+
+       ;; Emacs 20 and XEmacs (all versions so far) has a buggy
        ;; regexp-opt that doesn't always cope with strings containing
        ;; newlines.  This kludge doesn't handle shy parens correctly
        ;; so we can't advice regexp-opt directly with it.
@@ -1041,21 +1285,31 @@ current language (taken from `c-buffer-is-cc-mode')."
          (when fail-list
            (setq re (concat re
                             "\\|"
-                            (mapconcat 'regexp-quote
-                                       (sort fail-list
-                                             (lambda (a b)
-                                               (> (length a) (length b))))
-                                       "\\|")))))
+                            (mapconcat
+                             (if (eq adorn 'appendable)
+                                 (lambda (str)
+                                   (if (string-match "\\w\\'" str)
+                                       (concat (regexp-quote str)
+                                               "\\>")
+                                     (regexp-quote str)))
+                               'regexp-quote)
+                             (sort fail-list
+                                   (lambda (a b)
+                                     (> (length a) (length b))))
+                             "\\|")))))
 
        ;; Add our own grouping parenthesis around re instead of
        ;; passing adorn to `regexp-opt', since in XEmacs it makes the
        ;; top level grouping "shy".
-       (if adorn
-           (concat "\\(" re "\\)"
-                   "\\("
-                   (c-get-lang-constant 'c-nonsymbol-key nil mode)
-                   "\\|$\\)")
-         re))
+       (cond ((eq adorn 'appendable)
+              (concat "\\(" re "\\)"))
+             (adorn
+              (concat "\\(" re "\\)"
+                      "\\("
+                      (c-get-lang-constant 'c-nonsymbol-key nil mode)
+                      "\\|$\\)"))
+             (t
+              re)))
 
     ;; Produce a regexp that matches nothing.
     (if adorn
@@ -1064,6 +1318,35 @@ current language (taken from `c-buffer-is-cc-mode')."
 
 (put 'c-make-keywords-re 'lisp-indent-function 1)
 
+(defun c-make-bare-char-alt (chars &optional inverted)
+  "Make a character alternative string from the list of characters CHARS.
+The returned string is of the type that can be used with
+`skip-chars-forward' and `skip-chars-backward'.  If INVERTED is
+non-nil, a caret is prepended to invert the set."
+  ;; This function ought to be in the elisp core somewhere.
+  (let ((str (if inverted "^" "")) char char2)
+    (setq chars (sort (append chars nil) `<))
+    (while chars
+      (setq char (pop chars))
+      (if (memq char '(?\\ ?^ ?-))
+         ;; Quoting necessary (this method only works in the skip
+         ;; functions).
+         (setq str (format "%s\\%c" str char))
+       (setq str (format "%s%c" str char)))
+      ;; Check for range.
+      (setq char2 char)
+      (while (and chars (>= (1+ char2) (car chars)))
+       (setq char2 (pop chars)))
+      (unless (= char char2)
+       (if (< (1+ char) char2)
+           (setq str (format "%s-%c" str char2))
+         (push char2 chars))))
+    str))
+
+;; Leftovers from (X)Emacs 19 compatibility.
+(defalias 'c-regexp-opt 'regexp-opt)
+(defalias 'c-regexp-opt-depth 'regexp-opt-depth)
+
 \f
 ;; Figure out what features this Emacs has
 
@@ -1076,24 +1359,21 @@ current language (taken from `c-buffer-is-cc-mode')."
        ;; I've no idea what this actually is, but it's legacy. /mast
        (setq list (cons 'infodock list)))
 
-    ;; XEmacs 19 and beyond use 8-bit modify-syntax-entry flags.
-    ;; Emacs 19 uses a 1-bit flag.  We will have to set up our
+    ;; XEmacs uses 8-bit modify-syntax-entry flags.
+    ;; Emacs uses a 1-bit flag.  We will have to set up our
     ;; syntax tables differently to handle this.
     (let ((table (copy-syntax-table))
          entry)
       (modify-syntax-entry ?a ". 12345678" table)
       (cond
-       ;; XEmacs 19, and beyond Emacs 19.34
+       ;; Emacs
        ((arrayp table)
        (setq entry (aref table ?a))
        ;; In Emacs, table entries are cons cells
        (if (consp entry) (setq entry (car entry))))
-       ;; XEmacs 20
-       ((fboundp 'get-char-table) (setq entry (get-char-table ?a table)))
-       ;; before and including Emacs 19.34
-       ((and (fboundp 'char-table-p)
-            (char-table-p table))
-       (setq entry (car (char-table-range table [?a]))))
+       ;; XEmacs
+       ((fboundp 'get-char-table)
+       (setq entry (get-char-table ?a table)))
        ;; incompatible
        (t (error "CC Mode is incompatible with this version of Emacs")))
       (setq list (cons (if (= (logand (lsh entry -16) 255) 255)
@@ -1125,7 +1405,11 @@ current language (taken from `c-buffer-is-cc-mode')."
        (goto-char 1)
        (c-forward-sexp)
        (if (= (point) 5)
-           (setq list (cons 'syntax-properties list)))
+           (setq list (cons 'syntax-properties list))
+         (error (concat
+                 "CC Mode is incompatible with this version of Emacs - "
+                 "support for the `syntax-table' text property "
+                 "is required.")))
 
        ;; Find out if generic comment delimiters work.
        (c-safe
@@ -1153,7 +1437,7 @@ current language (taken from `c-buffer-is-cc-mode')."
          (setq list (cons 'posix-char-classes list)))
 
        ;; See if `open-paren-in-column-0-is-defun-start' exists and
-       ;; isn't buggy.
+       ;; isn't buggy (Emacs >= 21.4).
        (when (boundp 'open-paren-in-column-0-is-defun-start)
          (let ((open-paren-in-column-0-is-defun-start nil)
                (parse-sexp-ignore-comments t))
@@ -1180,8 +1464,11 @@ current language (taken from `c-buffer-is-cc-mode')."
       (kill-buffer buf))
 
     ;; See if `parse-partial-sexp' returns the eighth element.
-    (when (c-safe (>= (length (save-excursion (parse-partial-sexp 1 1))) 10))
-      (setq list (cons 'pps-extended-state list)))
+    (if (c-safe (>= (length (save-excursion (parse-partial-sexp 1 1))) 10))
+       (setq list (cons 'pps-extended-state list))
+      (error (concat
+             "CC Mode is incompatible with this version of Emacs - "
+             "`parse-partial-sexp' has to return at least 10 elements.")))
 
     ;;(message "c-emacs-features: %S" list)
     list)
@@ -1193,14 +1480,17 @@ might be present:
 '8-bit              8 bit syntax entry flags (XEmacs style).
 '1-bit              1 bit syntax entry flags (Emacs style).
 'syntax-properties  It works to override the syntax for specific characters
-                   in the buffer with the 'syntax-table property.
+                   in the buffer with the 'syntax-table property.  It's
+                   always set - CC Mode no longer works in emacsen without
+                   this feature.
 'gen-comment-delim  Generic comment delimiters work
                    (i.e. the syntax class `!').
 'gen-string-delim   Generic string delimiters work
                    (i.e. the syntax class `|').
 'pps-extended-state `parse-partial-sexp' returns a list with at least 10
-                   elements, i.e. it contains the position of the
-                   start of the last comment or string.
+                   elements, i.e. it contains the position of the start of
+                   the last comment or string. It's always set - CC Mode no
+                   longer works in emacsen without this feature.
 'posix-char-classes The regexp engine understands POSIX character classes.
 'col-0-paren        It's possible to turn off the ad-hoc rule that a paren
                    in column zero is the start of a defun.
@@ -1359,9 +1649,7 @@ To work well with repeated loads and interactive reevaluation, only
 one `c-lang-defconst' for each NAME is permitted per file.  If there
 already is one it will be completely replaced; the value in the
 earlier definition will not affect `c-lang-const' on the same
-constant.  A file is identified by its base name.
-
-This macro does not do any hidden buffer changes."
+constant.  A file is identified by its base name."
 
   (let* ((sym (intern (symbol-name name) c-lang-constants))
         ;; Make `c-lang-const' expand to a straightforward call to
@@ -1451,8 +1739,7 @@ This macro does not do any hidden buffer changes."
      (&define name [&optional stringp] [&rest sexp def-form])))
 
 (defun c-define-lang-constant (name bindings &optional pre-files)
-  ;; Used by `c-lang-defconst'.  This function does not do any hidden
-  ;; buffer changes.
+  ;; Used by `c-lang-defconst'.
 
   (let* ((sym (intern (symbol-name name) c-lang-constants))
         (source (get sym 'source))
@@ -1504,9 +1791,7 @@ LANG is the name of the language, i.e. the mode name without the
 \"-mode\" suffix.  If used inside `c-lang-defconst' or
 `c-lang-defvar', LANG may be left out to refer to the current
 language.  NAME and LANG are not evaluated so they should not be
-quoted.
-
-This macro does not do any hidden buffer changes."
+quoted."
 
   (or (symbolp name)
       (error "Not a symbol: %s" name))
@@ -1516,18 +1801,12 @@ This macro does not do any hidden buffer changes."
   (let ((sym (intern (symbol-name name) c-lang-constants))
        mode source-files args)
 
-    (if lang
-       (progn
-         (setq mode (intern (concat (symbol-name lang) "-mode")))
-         (unless (get mode 'c-mode-prefix)
-           (error
-            "Unknown language %S since it got no `c-mode-prefix' property"
-            (symbol-name lang))))
-      (if c-buffer-is-cc-mode
-         (setq lang c-buffer-is-cc-mode)
-       (or c-langs-are-parametric
-           (error
-            "`c-lang-const' requires a literal language in this context"))))
+    (when lang
+      (setq mode (intern (concat (symbol-name lang) "-mode")))
+      (unless (get mode 'c-mode-prefix)
+       (error
+        "Unknown language %S since it got no `c-mode-prefix' property"
+        (symbol-name lang))))
 
     (if (eq c-lang-const-expansion 'immediate)
        ;; No need to find out the source file(s) when we evaluate
@@ -1550,7 +1829,7 @@ This macro does not do any hidden buffer changes."
                                               (list (car elem))))
                                           (get sym 'source))))))
 
-      ;; Spend some effort to make a compact call to
+      ;; Make some effort to do a compact call to
       ;; `c-get-lang-constant' since it will be compiled in.
       (setq args (and mode `(',mode)))
       (if (or source-files args)
@@ -1558,12 +1837,15 @@ This macro does not do any hidden buffer changes."
                           args)))
 
       (if (or (eq c-lang-const-expansion 'call)
+             (and (not c-lang-const-expansion)
+                  (not mode))
              load-in-progress
              (not (boundp 'byte-compile-dest-file))
              (not (stringp byte-compile-dest-file)))
          ;; Either a straight call is requested in the context, or
-         ;; we're not being byte compiled so the compile time stuff
-         ;; below is unnecessary.
+         ;; we're in an "uncontrolled" context and got no language,
+         ;; or we're not being byte compiled so the compile time
+         ;; stuff below is unnecessary.
          `(c-get-lang-constant ',name ,@args)
 
        ;; Being compiled.  If the loading and compiling version is
@@ -1577,8 +1859,7 @@ This macro does not do any hidden buffer changes."
 (defvar c-lang-constants-under-evaluation nil)
 
 (defun c-get-lang-constant (name &optional source-files mode)
-  ;; Used by `c-lang-const'.  This function does not do any hidden
-  ;; buffer changes.
+  ;; Used by `c-lang-const'.
 
   (or mode
       (setq mode c-buffer-is-cc-mode)
index 71dc39a56e90aac7a0538fd12173e28970d6c3d4..c9f2b87b7f187758c07fcf653c8a13300284b5be 100644 (file)
@@ -1,6 +1,7 @@
 ;;; cc-engine.el --- core syntax guessing engine for CC mode
 
-;; Copyright (C) 1985,1987,1992-2003, 2004, 2005 Free Software Foundation, Inc.
+;; Copyright (C) 1985,1987,1992-2003, 2004, 2005 Free Software Foundation,
+;; Inc.
 
 ;; Authors:    1998- Martin Stjernholm
 ;;             1992-1999 Barry A. Warsaw
 ;;
 ;; Various functions in CC Mode use text properties for caching and
 ;; syntactic markup purposes, and those of them that might modify such
-;; properties are said to do "hidden buffer changes".  They should be
-;; used within `c-save-buffer-state' or a similar function that saves
-;; and restores buffer modifiedness etc.
+;; properties but still don't modify the buffer in a visible way are
+;; said to do "hidden buffer changes".  They should be used within
+;; `c-save-buffer-state' or a similar function that saves and restores
+;; buffer modifiedness, disables buffer change hooks, etc.
 ;;
-;; Interactive functions are assumed to not do hidden buffer changes
-;; (this isn't applicable in the specific parts of them that do real
-;; changes, though).
+;; Interactive functions are assumed to not do hidden buffer changes,
+;; except in the specific parts of them that do real changes.
 ;;
-;; All other functions are assumed to do hidden buffer changes and
-;; must thus be wrapped inside `c-save-buffer-state' if they're used
-;; from any function that does not do hidden buffer changes.
+;; Lineup functions are assumed to do hidden buffer changes.  They
+;; must not do real changes, though.
 ;;
-;; Every function, except the interactive ones, that doesn't do hidden
-;; buffer changes have that explicitly stated in their docstring or
-;; comment.
+;; All other functions that do hidden buffer changes have that noted
+;; in their doc string or comment.
+;;
+;; The intention with this system is to avoid wrapping every leaf
+;; function that do hidden buffer changes inside
+;; `c-save-buffer-state'.  It should be used as near the top of the
+;; interactive functions as possible.
+;;
+;; Functions called during font locking are allowed to do hidden
+;; buffer changes since the font-lock package run them in a context
+;; similar to `c-save-buffer-state' (in fact, that function is heavily
+;; inspired by `save-buffer-state' in the font-lock package).
 
 ;; Use of text properties
 ;;
@@ -86,8 +95,8 @@
 ;;
 ;; 'c-type
 ;;   This property is used on single characters to mark positions with
-;;   special syntactic relevance of various sorts.  It's primary use
-;;   is to avoid glitches when multiline constructs are refontified
+;;   special syntactic relevance of various sorts.  Its primary use is
+;;   to avoid glitches when multiline constructs are refontified
 ;;   interactively (on font lock decoration level 3).  It's cleared in
 ;;   a region before it's fontified and is then put on relevant chars
 ;;   in that region as they are encountered during the fontification.
 (cc-require-when-compile 'cc-langs)
 (cc-require 'cc-vars)
 
-;; Some functions/constants in cc-awk.el that are called/referenced here.
-;; (Can't use cc-require due to cyclicity.)
-(cc-bytecomp-defun c-awk-unstick-NL-prop)
-(cc-bytecomp-defun c-awk-clear-NL-props)
-(cc-bytecomp-defvar awk-mode-syntax-table)
-(cc-bytecomp-defun c-awk-backward-syntactic-ws)
-(cc-bytecomp-defun c-awk-after-logical-semicolon)
-(cc-bytecomp-defun c-awk-NL-prop-not-set)
-(cc-bytecomp-defun c-awk-completed-stmt-ws-ends-line-p)
-(cc-bytecomp-defun c-awk-completed-stmt-ws-ends-prev-line-p)
-(cc-bytecomp-defun c-awk-prev-line-incomplete-p)
-(cc-bytecomp-defun c-awk-after-change)
-
 ;; Silence the compiler.
 (cc-bytecomp-defun buffer-syntactic-context) ; XEmacs
 
 (defvar c-hungry-delete-key nil)
 (make-variable-buffer-local 'c-hungry-delete-key)
 
+;; The electric flag (toggled by `c-toggle-electric-state').
+;; If t, electric actions (like automatic reindentation, and (if
+;; c-auto-newline is also set) auto newlining) will happen when an electric
+;; key like `{' is pressed (or an electric keyword like `else').
+(defvar c-electric-flag t)
+(make-variable-buffer-local 'c-electric-flag)
+
 ;; Internal state of auto newline feature.
 (defvar c-auto-newline nil)
 (make-variable-buffer-local 'c-auto-newline)
 
-;; Internal auto-newline/hungry-delete designation string for mode line.
-(defvar c-auto-hungry-string nil)
-(make-variable-buffer-local 'c-auto-hungry-string)
+;; Included in the mode line to indicate the active submodes.
+(defvar c-submode-indicators nil)
+(make-variable-buffer-local 'c-submode-indicators)
 
 (defun c-calculate-state (arg prevstate)
   ;; Calculate the new state of PREVSTATE, t or nil, based on arg. If
 ;; Dynamically bound cache for `c-in-literal'.
 (defvar c-in-literal-cache t)
 
-;; Must be set in buffers where the `c-type' text property might be used
-;; with the value `c-decl-end'.
-(defvar c-type-decl-end-used nil)
-(make-variable-buffer-local 'c-type-decl-end-used)
-
 \f
 ;; Basic handling of preprocessor directives.
 
 (defvar c-macro-start 'unknown)
 
 (defsubst c-query-and-set-macro-start ()
-  ;; This function does not do any hidden buffer changes.
   (if (symbolp c-macro-start)
       (setq c-macro-start (save-excursion
-                           (and (c-beginning-of-macro)
-                                (point))))
+                           (c-save-buffer-state ()
+                             (and (c-beginning-of-macro)
+                                  (point)))))
     c-macro-start))
 
 (defsubst c-query-macro-start ()
-  ;; This function does not do any hidden buffer changes.
   (if (symbolp c-macro-start)
       (save-excursion
-       (and (c-beginning-of-macro)
-            (point)))
+       (c-save-buffer-state ()
+         (and (c-beginning-of-macro)
+              (point))))
     c-macro-start))
 
 (defun c-beginning-of-macro (&optional lim)
 Leave point at the beginning of the directive and return t if in one,
 otherwise return nil and leave point unchanged.
 
-This function does not do any hidden buffer changes."
+Note that this function might do hidden buffer changes.  See the
+comment at the start of cc-engine.el for more info."
   (when c-opt-cpp-prefix
     (let ((here (point)))
       (save-restriction
@@ -242,10 +241,12 @@ This function does not do any hidden buffer changes."
 
 (defun c-end-of-macro ()
   "Go to the end of a preprocessor directive.
-More accurately, move point to the end of the closest following line
-that doesn't end with a line continuation backslash.
+More accurately, move the point to the end of the closest following
+line that doesn't end with a line continuation backslash - no check is
+done that the point is inside a cpp directive to begin with.
 
-This function does not do any hidden buffer changes."
+Note that this function might do hidden buffer changes.  See the
+comment at the start of cc-engine.el for more info."
   (while (progn
           (end-of-line)
           (when (and (eq (char-before) ?\\)
@@ -256,45 +257,104 @@ This function does not do any hidden buffer changes."
 (defun c-forward-to-cpp-define-body ()
   ;; Assuming point is at the "#" that introduces a preprocessor
   ;; directive, it's moved forward to the start of the definition body
-  ;; if it's a "#define".  Non-nil is returned in this case, in all
-  ;; other cases nil is returned and point isn't moved.
-  (when (and (looking-at
-             (concat "#[ \t]*"
-                     "define[ \t]+\\(\\sw\\|_\\)+\\(\([^\)]*\)\\)?"
-                     "\\([ \t]\\|\\\\\n\\)*"))
+  ;; if it's a "#define" (or whatever c-opt-cpp-macro-define
+  ;; specifies).  Non-nil is returned in this case, in all other cases
+  ;; nil is returned and point isn't moved.
+  ;;
+  ;; This function might do hidden buffer changes.
+  (when (and c-opt-cpp-macro-define-start
+            (looking-at c-opt-cpp-macro-define-start)
             (not (= (match-end 0) (c-point 'eol))))
     (goto-char (match-end 0))))
 
 \f
 ;;; Basic utility functions.
 
-(defun c-syntactic-content (from to)
+(defun c-syntactic-content (from to paren-level)
   ;; Return the given region as a string where all syntactic
   ;; whitespace is removed or, where necessary, replaced with a single
-  ;; space.
+  ;; space.  If PAREN-LEVEL is given then all parens in the region are
+  ;; collapsed to "()", "[]" etc.
+  ;;
+  ;; This function might do hidden buffer changes.
+
   (save-excursion
-    (goto-char from)
-    (let* ((parts (list nil)) (tail parts) pos)
-      (while (re-search-forward c-syntactic-ws-start to t)
-       (goto-char (setq pos (match-beginning 0)))
-       (c-forward-syntactic-ws to)
-       (if (= (point) pos)
-           (forward-char)
-         (if (and (> pos from)
-                  (< (point) to)
-                  (looking-at "\\w\\|\\s_")
-                  (save-excursion
-                    (goto-char (1- pos))
-                    (looking-at "\\w\\|\\s_")))
-             (progn
-               (setcdr tail (list (buffer-substring-no-properties from pos)
-                                  " "))
-               (setq tail (cddr tail)))
-           (setcdr tail (list (buffer-substring-no-properties from pos)))
-           (setq tail (cdr tail)))
-         (setq from (point))))
-      (setcdr tail (list (buffer-substring-no-properties from to)))
-      (apply 'concat (cdr parts)))))
+    (save-restriction
+      (narrow-to-region from to)
+      (goto-char from)
+      (let* ((parts (list nil)) (tail parts) pos in-paren)
+
+       (while (re-search-forward c-syntactic-ws-start to t)
+         (goto-char (setq pos (match-beginning 0)))
+         (c-forward-syntactic-ws)
+         (if (= (point) pos)
+             (forward-char)
+
+           (when paren-level
+             (save-excursion
+               (setq in-paren (= (car (parse-partial-sexp from pos 1)) 1)
+                     pos (point))))
+
+           (if (and (> pos from)
+                    (< (point) to)
+                    (looking-at "\\w\\|\\s_")
+                    (save-excursion
+                      (goto-char (1- pos))
+                      (looking-at "\\w\\|\\s_")))
+               (progn
+                 (setcdr tail (list (buffer-substring-no-properties from pos)
+                                    " "))
+                 (setq tail (cddr tail)))
+             (setcdr tail (list (buffer-substring-no-properties from pos)))
+             (setq tail (cdr tail)))
+
+           (when in-paren
+             (when (= (car (parse-partial-sexp pos to -1)) -1)
+               (setcdr tail (list (buffer-substring-no-properties
+                                   (1- (point)) (point))))
+               (setq tail (cdr tail))))
+
+           (setq from (point))))
+
+       (setcdr tail (list (buffer-substring-no-properties from to)))
+       (apply 'concat (cdr parts))))))
+
+(defun c-shift-line-indentation (shift-amt)
+  ;; Shift the indentation of the current line with the specified
+  ;; amount (positive inwards).  The buffer is modified only if
+  ;; SHIFT-AMT isn't equal to zero.
+  (let ((pos (- (point-max) (point)))
+       (c-macro-start c-macro-start)
+       tmp-char-inserted)
+    (if (zerop shift-amt)
+       nil
+      ;; If we're on an empty line inside a macro, we take the point
+      ;; to be at the current indentation and shift it to the
+      ;; appropriate column. This way we don't treat the extra
+      ;; whitespace out to the line continuation as indentation.
+      (when (and (c-query-and-set-macro-start)
+                (looking-at "[ \t]*\\\\$")
+                (save-excursion
+                  (skip-chars-backward " \t")
+                  (bolp)))
+       (insert ?x)
+       (backward-char)
+       (setq tmp-char-inserted t))
+      (unwind-protect
+         (let ((col (current-indentation)))
+           (delete-region (c-point 'bol) (c-point 'boi))
+           (beginning-of-line)
+           (indent-to (+ col shift-amt)))
+       (when tmp-char-inserted
+         (delete-char 1))))
+    ;; If initial point was within line's indentation and we're not on
+    ;; a line with a line continuation in a macro, position after the
+    ;; indentation.  Else stay at same point in text.
+    (if (and (< (point) (c-point 'boi))
+            (not tmp-char-inserted))
+       (back-to-indentation)
+      (if (> (- (point-max) pos) (point))
+         (goto-char (- (point-max) pos))))))
 
 (defsubst c-keyword-sym (keyword)
   ;; Return non-nil if the string KEYWORD is a known keyword.  More
@@ -314,18 +374,21 @@ This function does not do any hidden buffer changes."
                               "\"|"
                             "\""))
 
-;; Regexp matching string start syntax.
+;; Regexp matching string limit syntax.
 (defconst c-string-limit-regexp (if (memq 'gen-string-delim c-emacs-features)
                                     "\\s\"\\|\\s|"
                                   "\\s\""))
 
+;; Regexp matching WS followed by string limit syntax.
+(defconst c-ws*-string-limit-regexp
+  (concat "[ \t]*\\(" c-string-limit-regexp "\\)"))
+
 ;; Holds formatted error strings for the few cases where parse errors
 ;; are reported.
 (defvar c-parsing-error nil)
 (make-variable-buffer-local 'c-parsing-error)
 
 (defun c-echo-parsing-error (&optional quiet)
-  ;; This function does not do any hidden buffer changes.
   (when (and c-report-syntactic-errors c-parsing-error (not quiet))
     (c-benign-error "%s" c-parsing-error))
   c-parsing-error)
@@ -335,39 +398,29 @@ This function does not do any hidden buffer changes."
 ;; locking is in use.  This variable is extended with the face in
 ;; `c-doc-face-name' when fontification is activated in cc-fonts.el.
 (defvar c-literal-faces
-  '(font-lock-comment-face font-lock-string-face
-                          font-lock-comment-delimiter-face))
-
-(defun c-shift-line-indentation (shift-amt)
-  ;; This function does not do any hidden buffer changes.
-  (let ((pos (- (point-max) (point)))
-       (c-macro-start c-macro-start)
-       tmp-char-inserted)
-    (if (zerop shift-amt)
-       nil
-      (when (and (c-query-and-set-macro-start)
-                (looking-at "[ \t]*\\\\$")
-                (save-excursion
-                  (skip-chars-backward " \t")
-                  (bolp)))
-       (insert ?x)
-       (backward-char)
-       (setq tmp-char-inserted t))
-      (unwind-protect
-         (let ((col (current-indentation)))
-           (delete-region (c-point 'bol) (c-point 'boi))
-           (beginning-of-line)
-           (indent-to (+ col shift-amt)))
-       (when tmp-char-inserted
-         (delete-char 1))))
-    ;; If initial point was within line's indentation and we're not on
-    ;; a line with a line continuation in a macro, position after the
-    ;; indentation.  Else stay at same point in text.
-    (if (and (< (point) (c-point 'boi))
-            (not tmp-char-inserted))
-       (back-to-indentation)
-      (if (> (- (point-max) pos) (point))
-         (goto-char (- (point-max) pos))))))
+  (append '(font-lock-comment-face font-lock-string-face)
+         (when (facep 'font-lock-comment-delimiter-face)
+           ;; New in Emacs 22.
+           '(font-lock-comment-delimiter-face))))
+
+(defsubst c-put-c-type-property (pos value)
+  ;; Put a c-type property with the given value at POS.
+  (c-put-char-property pos 'c-type value))
+
+(defun c-clear-c-type-property (from to value)
+  ;; Remove all occurences of the c-type property that has the given
+  ;; value in the region between FROM and TO.  VALUE is assumed to not
+  ;; be nil.
+  ;;
+  ;; Note: This assumes that c-type is put on single chars only; it's
+  ;; very inefficient if matching properties cover large regions.
+  (save-excursion
+    (goto-char from)
+    (while (progn
+            (when (eq (get-text-property (point) 'c-type) value)
+              (c-clear-char-property (point) 'c-type))
+            (goto-char (next-single-property-change (point) 'c-type nil to))
+            (< (point) to)))))
 
 \f
 ;; Some debug tools to visualize various special positions.  This
@@ -414,7 +467,7 @@ This function does not do any hidden buffer changes."
 ;; c-crosses-statement-barrier-p and c-beginning-of-statement-1.  A
 ;; better way should be implemented, but this will at least shut up
 ;; the byte compiler.
-(defvar c-maybe-labelp nil)
+(defvar c-maybe-labelp)
 
 ;; New awk-compatible version of c-beginning-of-statement-1, ACM 2002/6/22
 
@@ -470,11 +523,9 @@ corresponding statement start.  If at the beginning of a statement,
 move to the closest containing statement if there is any.  This might
 also stop at a continuation clause.
 
-Labels are treated as separate statements if IGNORE-LABELS is non-nil.
-The function is not overly intelligent in telling labels from other
-uses of colons; if used outside a statement context it might trip up
-on e.g. inherit colons, so IGNORE-LABELS should be used then.  There
-should be no such mistakes in a statement context, however.
+Labels are treated as part of the following statements if
+IGNORE-LABELS is non-nil.  (FIXME: Doesn't work if we stop at a known
+statement start keyword.)
 
 Macros are ignored unless point is within one, in which case the
 content of the macro is treated as normal code.  Aside from any normal
@@ -497,7 +548,10 @@ position if that is less ('same is returned in this case).
 NOERROR turns off error logging to `c-parsing-error'.
 
 Normally only ';' is considered to delimit statements, but if
-COMMA-DELIM is non-nil then ',' is treated likewise."
+COMMA-DELIM is non-nil then ',' is treated likewise.
+
+Note that this function might do hidden buffer changes.  See the
+comment at the start of cc-engine.el for more info."
 
   ;; The bulk of this function is a pushdown automaton that looks at statement
   ;; boundaries and the tokens (such as "while") in c-opt-block-stmt-key.  Its
@@ -587,20 +641,43 @@ COMMA-DELIM is non-nil then ',' is treated likewise."
        (c-stmt-delim-chars (if comma-delim
                                c-stmt-delim-chars-with-comma
                              c-stmt-delim-chars))
-       pos                             ; Current position.
-       boundary-pos      ; Position of last stmt boundary character (e.g. ;).
-       after-labels-pos                ; Value of tok after first found colon.
-       last-label-pos                  ; Value of tok after last found colon.
-       sym         ; Symbol just scanned back over (e.g. 'while or
-                   ; 'boundary). See above
-       state                     ; Current state in the automaton. See above.
-       saved-pos                       ; Current saved positions. See above
-       stack                           ; Stack of conses (state . saved-pos).
-       (cond-key (or c-opt-block-stmt-key ; regexp which matches "for", "if", etc.
+       c-in-literal-cache c-maybe-labelp saved
+       ;; Current position.
+       pos
+       ;; Position of last stmt boundary character (e.g. ;).
+       boundary-pos
+       ;; The position of the last sexp or bound that follows the
+       ;; first found colon, i.e. the start of the nonlabel part of
+       ;; the statement.  It's `start' if a colon is found just after
+       ;; the start.
+       after-labels-pos
+       ;; Like `after-labels-pos', but the first such position inside
+       ;; a label, i.e. the start of the last label before the start
+       ;; of the nonlabel part of the statement.
+       last-label-pos
+       ;; The last position where a label is possible provided the
+       ;; statement started there.  It's nil as long as no invalid
+       ;; label content has been found (according to
+       ;; `c-nonlabel-token-key'.  It's `start' if no valid label
+       ;; content was found in the label.  Note that we might still
+       ;; regard it a label if it starts with `c-label-kwds'.
+       label-good-pos
+       ;; Symbol just scanned back over (e.g. 'while or 'boundary).
+       ;; See above.
+       sym
+       ;; Current state in the automaton.  See above.
+       state
+       ;; Current saved positions.  See above.
+       saved-pos
+       ;; Stack of conses (state . saved-pos).
+       stack
+       ;; Regexp which matches "for", "if", etc.
+       (cond-key (or c-opt-block-stmt-key
                      "\\<\\>"))        ; Matches nothing.
-       (ret 'same)                     ; Return value.
-       tok ptok pptok                  ; Pos of last three sexps or bounds.
-       c-in-literal-cache c-maybe-labelp saved)
+       ;; Return value.
+       (ret 'same)
+       ;; Positions of the last three sexps or bounds we've stopped at.
+       tok ptok pptok)
 
     (save-restriction
       (if lim (narrow-to-region lim (point-max)))
@@ -614,32 +691,23 @@ COMMA-DELIM is non-nil then ',' is treated likewise."
       ;; that we've moved.
       (while (progn
               (setq pos (point))
-               (if (c-mode-is-new-awk-p)
-                   (c-awk-backward-syntactic-ws)
-                 (c-backward-syntactic-ws))
-              (/= (skip-chars-backward "-+!*&~@`#") 0))) ; ACM, 2002/5/31;
-                                                         ; Make a variable in
-                                                         ; cc-langs.el, maybe
+              (c-backward-syntactic-ws)
+              ;; Protect post-++/-- operators just before a virtual semicolon.
+              (and (not (c-at-vsemi-p))
+                   (/= (skip-chars-backward "-+!*&~@`#") 0))))
 
       ;; Skip back over any semicolon here.  If it was a bare semicolon, we're
-      ;; done.  Later on we ignore the boundaries for statements that doesn't
+      ;; done.  Later on we ignore the boundaries for statements that don't
       ;; contain any sexp.  The only thing that is affected is that the error
       ;; checking is a little less strict, and we really don't bother.
       (if (and (memq (char-before) delims)
               (progn (forward-char -1)
                      (setq saved (point))
-                     (if (c-mode-is-new-awk-p)
-                          (c-awk-backward-syntactic-ws)
-                        (c-backward-syntactic-ws))
+                     (c-backward-syntactic-ws)
                      (or (memq (char-before) delims)
                          (memq (char-before) '(?: nil))
                          (eq (char-syntax (char-before)) ?\()
-                          (and (c-mode-is-new-awk-p)
-                               (c-awk-after-logical-semicolon))))) ; ACM 2002/6/22
-          ;; ACM, 2002/7/20: What about giving a limit to the above function?
-          ;; ACM, 2003/6/16: The above two lines (checking for
-          ;; awk-logical-semicolon) are probably redundant after rewriting
-          ;; c-awk-backward-syntactic-ws.
+                         (c-at-vsemi-p))))
          (setq ret 'previous
                pos saved)
 
@@ -657,11 +725,8 @@ COMMA-DELIM is non-nil then ',' is treated likewise."
        (while
            (catch 'loop ;; Throw nil to break, non-nil to continue.
              (cond
-              ;; Check for macro start.  Take this out for AWK Mode (ACM, 2002/5/31)
-               ;; NO!! just make sure macro-start is nil in AWK Mode (ACM, 2002/6/22)
-               ;; It always is (ACM, 2002/6/23)
               ((save-excursion
-                 (and macro-start
+                 (and macro-start      ; Always NIL for AWK.
                       (progn (skip-chars-backward " \t")
                              (eq (char-before) ?#))
                       (progn (setq saved (1- (point)))
@@ -767,23 +832,22 @@ COMMA-DELIM is non-nil then ',' is treated likewise."
                           (c-bos-save-error-info 'if 'else)
                           (setq state 'else))
                          ((eq sym 'while)
+                          ;; Is this a real while, or a do-while?
+                          ;; The next `when' triggers unless we are SURE that
+                          ;; the `while' is not the tailend of a `do-while'.
                           (when (or (not pptok)
                                     (memq (char-after pptok) delims)
-                                     (and (c-mode-is-new-awk-p)
-                                          (or
-                                        ;; might we be calling this from
-                                        ;; c-awk-after-if-do-for-while-condition-p?
-                                        ;; If so, avoid infinite recursion.
-                                           (and (eq (point) start)
-                                                (c-awk-NL-prop-not-set))
-                                           ;; The following may recursively
-                                           ;; call this function.
-                                           (c-awk-completed-stmt-ws-ends-line-p pptok))))
+                                    ;; The following kludge is to prevent
+                                    ;; infinite recursion when called from
+                                    ;; c-awk-after-if-for-while-condition-p,
+                                    ;; or the like.
+                                    (and (eq (point) start)
+                                         (c-vsemi-status-unknown-p))
+                                    (c-at-vsemi-p pptok))
                             ;; Since this can cause backtracking we do a
                             ;; little more careful analysis to avoid it: If
-                            ;; the while isn't followed by a semicolon it
-                            ;; can't be a do-while.
-                             ;; ACM, 2002/5/31;  IT CAN IN AWK Mode. ;-(
+                            ;; the while isn't followed by a (possibly
+                            ;; virtual) semicolon it can't be a do-while.
                             (c-bos-push-state)
                             (setq state 'while)))
                          ((memq sym '(catch finally))
@@ -805,80 +869,95 @@ COMMA-DELIM is non-nil then ',' is treated likewise."
                  (setq ret 'previous)
 
                 ;; HERE IS THE SINGLE PLACE INSIDE THE PDA LOOP WHERE WE MOVE
-                ;; BACKWARDS THROUGH THE SOURCE. The following loop goes back
-                ;; one sexp and then only loops in special circumstances (line
-                ;; continuations and skipping past entire macros).
-               (while
-                   (progn
-                     (or (c-safe (goto-char (scan-sexps (point) -1)) t)
-                         ;; Give up if we hit an unbalanced block.
-                         ;; Since the stack won't be empty the code
-                         ;; below will report a suitable error.
+               ;; BACKWARDS THROUGH THE SOURCE.
+
+               ;; This is typically fast with the caching done by
+               ;; c-(backward|forward)-sws.
+               (c-backward-syntactic-ws)
+
+               (let ((before-sws-pos (point))
+                     ;; Set as long as we have to continue jumping by sexps.
+                     ;; It's the position to use as end in the next round.
+                     sexp-loop-continue-pos
+                     ;; The end position of the area to search for statement
+                     ;; barriers in this round.
+                     (sexp-loop-end-pos pos))
+
+                 (while
+                     (progn
+                       (unless (c-safe (c-backward-sexp) t)
+                         ;; Give up if we hit an unbalanced block.  Since the
+                         ;; stack won't be empty the code below will report a
+                         ;; suitable error.
                          (throw 'loop nil))
-                     (cond ((looking-at "\\\\$")
-                            ;; Step again if we hit a line continuation.
-                            t)
-                           (macro-start
-                            ;; If we started inside a macro then this
-                            ;; sexp is always interesting.
-                            nil)
-                           ((not (c-mode-is-new-awk-p)) ; Changed from t, ACM 2002/6/25
-                            ;; Otherwise check that we didn't step
-                            ;; into a macro from the end.
-                            (let ((macro-start
-                                   (save-excursion
-                                     (and (c-beginning-of-macro)
-                                          (point)))))
-                              (when macro-start
-                                (goto-char macro-start)
-                                t))))))
-
-               ;; Did the last movement by a sexp cross a statement boundary?
-               (when (save-excursion
-                       (if (if (eq (char-after) ?{)
-                               (c-looking-at-inexpr-block lim nil)
-                             (looking-at "\\s\("))
-
-                           ;; Should not include the paren sexp we've
-                           ;; passed over in the boundary check.
-                           (if (> (point) (- pos 100))
-                               (c-forward-sexp 1)
-
-                             ;; Find its end position this way instead of
-                             ;; moving forward if the sexp is large.
-                             (goto-char pos)
-                             (while
-                                 (progn
-                                   (goto-char (1+ (c-down-list-backward)))
-                                   (unless macro-start
-                                     ;; Check that we didn't step into
-                                     ;; a macro from the end.
-                                     (let ((macro-start
-                                            (save-excursion
-                                              (and (c-beginning-of-macro)
-                                                   (point)))))
-                                       (when macro-start
-                                         (goto-char macro-start)
-                                         t)))))))
-
-                       (setq boundary-pos (c-crosses-statement-barrier-p
-                                           (point) pos)))
-
-                 (setq pptok ptok
-                       ptok tok
-                       tok boundary-pos
-                       sym 'boundary)
-                 (throw 'loop t))) ; like a C "continue".  Analyze the next sexp.
-
-             (when (and (numberp c-maybe-labelp)
-                        (not ignore-labels)
-                        (not (looking-at "\\s\(")))
-               ;; c-crosses-statement-barrier-p has found a colon, so
-               ;; we might be in a label now.
-               (if (not after-labels-pos)
-                   (setq after-labels-pos tok))
-               (setq last-label-pos tok
-                     c-maybe-labelp t))
+
+                       ;; Check if the sexp movement crossed a statement or
+                       ;; declaration boundary.  But first modify the point
+                       ;; so that `c-crosses-statement-barrier-p' only looks
+                       ;; at the non-sexp chars following the sexp.
+                       (save-excursion
+                         (when (setq
+                                boundary-pos
+                                (cond
+                                 ((if macro-start
+                                      nil
+                                    (save-excursion
+                                      (when (c-beginning-of-macro)
+                                        ;; Set continuation position in case
+                                        ;; `c-crosses-statement-barrier-p'
+                                        ;; doesn't detect anything below.
+                                        (setq sexp-loop-continue-pos (point)))))
+                                  ;; If the sexp movement took us into a
+                                  ;; macro then there were only some non-sexp
+                                  ;; chars after it.  Skip out of the macro
+                                  ;; to analyze them but not the non-sexp
+                                  ;; chars that might be inside the macro.
+                                  (c-end-of-macro)
+                                  (c-crosses-statement-barrier-p
+                                   (point) sexp-loop-end-pos))
+
+                                 ((and
+                                   (eq (char-after) ?{)
+                                   (not (c-looking-at-inexpr-block lim nil t)))
+                                  ;; Passed a block sexp.  That's a boundary
+                                  ;; alright.
+                                  (point))
+
+                                 ((looking-at "\\s\(")
+                                  ;; Passed some other paren.  Only analyze
+                                  ;; the non-sexp chars after it.
+                                  (goto-char (1+ (c-down-list-backward
+                                                  before-sws-pos)))
+                                  ;; We're at a valid token start position
+                                  ;; (outside the `save-excursion') if
+                                  ;; `c-crosses-statement-barrier-p' failed.
+                                  (c-crosses-statement-barrier-p
+                                   (point) sexp-loop-end-pos))
+
+                                 (t
+                                  ;; Passed a symbol sexp or line
+                                  ;; continuation.  It doesn't matter that
+                                  ;; it's included in the analyzed region.
+                                  (if (c-crosses-statement-barrier-p
+                                       (point) sexp-loop-end-pos)
+                                      t
+                                    ;; If it was a line continuation then we
+                                    ;; have to continue looping.
+                                    (if (looking-at "\\\\$")
+                                        (setq sexp-loop-continue-pos (point)))
+                                    nil))))
+
+                           (setq pptok ptok
+                                 ptok tok
+                                 tok boundary-pos
+                                 sym 'boundary)
+                           ;; Like a C "continue".  Analyze the next sexp.
+                           (throw 'loop t)))
+
+                       sexp-loop-continue-pos)
+                   (goto-char sexp-loop-continue-pos)
+                   (setq sexp-loop-end-pos sexp-loop-continue-pos
+                         sexp-loop-continue-pos nil))))
 
              ;; ObjC method def?
              (when (and c-opt-method-key
@@ -887,7 +966,26 @@ COMMA-DELIM is non-nil then ',' is treated likewise."
                      ignore-labels t)  ; Avoid the label check on exit.
                (throw 'loop nil))
 
-              ;; We've moved back by a sexp, so update the token positions. 
+             ;; Handle labels.
+             (unless (eq ignore-labels t)
+               (when (numberp c-maybe-labelp)
+                 ;; `c-crosses-statement-barrier-p' has found a
+                 ;; colon, so we might be in a label now.
+                 (if after-labels-pos
+                     (if (not last-label-pos)
+                         (setq last-label-pos (or tok start)))
+                   (setq after-labels-pos (or tok start)))
+                 (setq c-maybe-labelp t
+                       label-good-pos nil))
+
+               (when (and (not label-good-pos)
+                          (looking-at c-nonlabel-token-key))
+                 ;; We're in a potential label and it's the first
+                 ;; time we've found something that isn't allowed in
+                 ;; one.
+                 (setq label-good-pos (or tok start))))
+
+             ;; We've moved back by a sexp, so update the token positions.
              (setq sym nil
                    pptok ptok
                    ptok tok
@@ -911,25 +1009,34 @@ COMMA-DELIM is non-nil then ',' is treated likewise."
              (cond ((> start saved) (setq pos saved))
                    ((= start saved) (setq ret 'up)))))
 
-       (when (and c-maybe-labelp
-                  (not ignore-labels)
+       (when (and (not ignore-labels)
+                  (eq c-maybe-labelp t)
                   (not (eq ret 'beginning))
-                  after-labels-pos)
+                  after-labels-pos
+                  (or (not label-good-pos)
+                      (<= label-good-pos pos)
+                      (progn
+                        (goto-char (if (and last-label-pos
+                                            (< last-label-pos start))
+                                       last-label-pos
+                                     pos))
+                        (looking-at c-label-kwds-regexp))))
          ;; We're in a label.  Maybe we should step to the statement
          ;; after it.
          (if (< after-labels-pos start)
              (setq pos after-labels-pos)
            (setq ret 'label)
-           (if (< last-label-pos start)
+           (if (and last-label-pos (< last-label-pos start))
+               ;; Might have jumped over several labels.  Go to the last one.
                (setq pos last-label-pos)))))
 
       ;; Skip over the unary operators that can start the statement.
       (goto-char pos)
       (while (progn
-              (if (c-mode-is-new-awk-p)
-                   (c-awk-backward-syntactic-ws)
-                 (c-backward-syntactic-ws))
-              (/= (skip-chars-backward "-+!*&~@`#") 0)) ; Hopefully the # won't hurt awk.
+              (c-backward-syntactic-ws)
+              ;; protect AWK post-inc/decrement operators, etc.
+              (and (not (c-at-vsemi-p (point)))
+                   (/= (skip-chars-backward "-+!*&~@`#") 0)))
        (setq pos (point)))
       (goto-char pos)
       ret)))
@@ -942,7 +1049,14 @@ a string or comment.
 
 The variable `c-maybe-labelp' is set to the position of the first `:' that
 might start a label (i.e. not part of `::' and not preceded by `?').  If a
-single `?' is found, then `c-maybe-labelp' is cleared."
+single `?' is found, then `c-maybe-labelp' is cleared.
+
+For AWK, a statement which is terminated by an EOL (not a \; or a }) is
+regarded as having a \"virtual semicolon\" immediately after the last token on
+the line.  If this virtual semicolon is _at_ from, the function recognises it.
+
+Note that this function might do hidden buffer changes.  See the
+comment at the start of cc-engine.el for more info."
   (let ((skip-chars c-stmt-delim-chars)
        lit-range)
     (save-excursion
@@ -950,30 +1064,85 @@ single `?' is found, then `c-maybe-labelp' is cleared."
        (goto-char from)
        (while (progn (skip-chars-forward skip-chars to)
                      (< (point) to))
-         (if (setq lit-range (c-literal-limits from)) ; Have we landed in a string/comment?
-             (progn (goto-char (setq from (cdr lit-range)))
-                     (if (and (c-mode-is-new-awk-p) (bolp)) ; ACM 2002/7/17. Make sure we
-                         (backward-char))) ; don't skip over a virtual semi-colon after an awk comment.  :-(
-           (cond ((eq (char-after) ?:)
-                  (forward-char)
-                  (if (and (eq (char-after) ?:)
-                           (< (point) to))
-                      ;; Ignore scope operators.
-                      (forward-char)
-                    (setq c-maybe-labelp (1- (point)))))
-                 ((eq (char-after) ??)
-                  ;; A question mark.  Can't be a label, so stop
-                  ;; looking for more : and ?.
-                  (setq c-maybe-labelp nil
-                        skip-chars (substring c-stmt-delim-chars 0 -2)))
-                  ((and (eolp)  ; Can only happen in AWK Mode
-                        (not (c-awk-completed-stmt-ws-ends-line-p)))
-                   (forward-char))
-                  ((and (c-mode-is-new-awk-p)
-                        (bolp) lit-range ; awk: comment/string ended prev line.
-                        (not (c-awk-completed-stmt-ws-ends-prev-line-p))))
-                 (t (throw 'done (point))))))
-       nil))))
+         (cond
+          ((setq lit-range (c-literal-limits from)) ; Have we landed in a string/comment?
+           (goto-char (cdr lit-range)))
+          ((eq (char-after) ?:)
+           (forward-char)
+           (if (and (eq (char-after) ?:)
+                    (< (point) to))
+               ;; Ignore scope operators.
+               (forward-char)
+             (setq c-maybe-labelp (1- (point)))))
+          ((eq (char-after) ??)
+           ;; A question mark.  Can't be a label, so stop
+           ;; looking for more : and ?.
+           (setq c-maybe-labelp nil
+                 skip-chars (substring c-stmt-delim-chars 0 -2)))
+          ((memq (char-after) '(?# ?\n ?\r)) ; A virtual semicolon?
+           (if (and (eq (char-before) ?\\) (memq (char-after) '(?\n ?\r)))
+               (backward-char))
+           (skip-chars-backward " \t" from)
+           (if (c-at-vsemi-p)
+               (throw 'done (point))
+             (forward-line)))
+          (t (throw 'done (point)))))
+       ;; In trailing space after an as yet undetected virtual semicolon?
+       (c-backward-syntactic-ws from)
+       (if (and (< (point) to)
+                (c-at-vsemi-p))
+           (point)
+         nil)))))
+
+(defun c-at-statement-start-p ()
+  "Return non-nil if the point is at the first token in a statement
+or somewhere in the syntactic whitespace before it.
+
+A \"statement\" here is not restricted to those inside code blocks.
+Any kind of declaration-like construct that occur outside function
+bodies is also considered a \"statement\".
+
+Note that this function might do hidden buffer changes.  See the
+comment at the start of cc-engine.el for more info."
+
+  (save-excursion
+    (let ((end (point))
+         c-maybe-labelp)
+      (c-syntactic-skip-backward (substring c-stmt-delim-chars 1) nil t)
+      (or (bobp)
+         (eq (char-before) ?})
+         (and (eq (char-before) ?{)
+              (not (and c-special-brace-lists
+                        (progn (backward-char)
+                               (c-looking-at-special-brace-list)))))
+         (c-crosses-statement-barrier-p (point) end)))))
+
+(defun c-at-expression-start-p ()
+  "Return non-nil if the point is at the first token in an expression or
+statement, or somewhere in the syntactic whitespace before it.
+
+An \"expression\" here is a bit different from the normal language
+grammar sense: It's any sequence of expression tokens except commas,
+unless they are enclosed inside parentheses of some kind.  Also, an
+expression never continues past an enclosing parenthesis, but it might
+contain parenthesis pairs of any sort except braces.
+
+Since expressions never cross statement boundaries, this function also
+recognizes statement beginnings, just like `c-at-statement-start-p'.
+
+Note that this function might do hidden buffer changes.  See the
+comment at the start of cc-engine.el for more info."
+
+  (save-excursion
+    (let ((end (point))
+         (c-stmt-delim-chars c-stmt-delim-chars-with-comma)
+         c-maybe-labelp)
+      (c-syntactic-skip-backward (substring c-stmt-delim-chars 1) nil t)
+      (or (bobp)
+         (memq (char-before) '(?{ ?}))
+         (save-excursion (backward-char)
+                         (looking-at "\\s("))
+         (c-crosses-statement-barrier-p (point) end)))))
 
 \f
 ;; A set of functions that covers various idiosyncrasies in
@@ -1020,7 +1189,8 @@ This function does not do any hidden buffer changes."
 Line continuations, i.e. a backslashes followed by line breaks, are
 treated as whitespace.
 
-This function does not do any hidden buffer changes."
+Note that this function might do hidden buffer changes.  See the
+comment at the start of cc-engine.el for more info."
 
   (while (or
          ;; If forward-comment in at least XEmacs 21 is given a large
@@ -1054,8 +1224,7 @@ This function does not do any hidden buffer changes."
     (while (progn
             (skip-chars-backward " \t\n\r\f\v")
             (and (looking-at "[\n\r]")
-                 (eq (char-before) ?\\)
-                 (< (point) start)))
+                 (eq (char-before) ?\\)))
       (backward-char))
 
     (if (bobp)
@@ -1088,13 +1257,16 @@ This function does not do any hidden buffer changes."
 Line continuations, i.e. a backslashes followed by line breaks, are
 treated as whitespace.  The line breaks that end line comments are
 considered to be the comment enders, so the point cannot be at the end
-of the same line to move over a line comment.
+of the same line to move over a line comment.  Unlike
+c-backward-syntactic-ws, this function doesn't move back over
+preprocessor directives.
 
-This function does not do any hidden buffer changes."
+Note that this function might do hidden buffer changes.  See the
+comment at the start of cc-engine.el for more info."
 
   (let ((start (point)))
     (while (and
-           ;; `forward-comment' in some emacsen (e.g. Emacs 19.34)
+           ;; `forward-comment' in some emacsen (e.g. XEmacs 21.4)
            ;; return t when moving backwards at bob.
            (not (bobp))
 
@@ -1189,7 +1361,7 @@ This function does not do any hidden buffer changes."
 ;   ;; properties in the buffer.
 ;   (interactive)
 ;   (save-excursion
-;     (let (in-face)
+;     (c-save-buffer-state (in-face)
 ;       (goto-char (point-min))
 ;       (setq in-face (if (get-text-property (point) 'c-is-sws)
 ;                      (point)))
@@ -1220,30 +1392,35 @@ This function does not do any hidden buffer changes."
   )
 
 (defmacro c-put-is-sws (beg end)
+  ;; This macro does a hidden buffer change.
   `(let ((beg ,beg) (end ,end))
      (put-text-property beg end 'c-is-sws t)
      ,@(when (facep 'c-debug-is-sws-face)
         `((c-debug-add-face beg end 'c-debug-is-sws-face)))))
 
 (defmacro c-put-in-sws (beg end)
+  ;; This macro does a hidden buffer change.
   `(let ((beg ,beg) (end ,end))
      (put-text-property beg end 'c-in-sws t)
      ,@(when (facep 'c-debug-is-sws-face)
         `((c-debug-add-face beg end 'c-debug-in-sws-face)))))
 
 (defmacro c-remove-is-sws (beg end)
+  ;; This macro does a hidden buffer change.
   `(let ((beg ,beg) (end ,end))
      (remove-text-properties beg end '(c-is-sws nil))
      ,@(when (facep 'c-debug-is-sws-face)
         `((c-debug-remove-face beg end 'c-debug-is-sws-face)))))
 
 (defmacro c-remove-in-sws (beg end)
+  ;; This macro does a hidden buffer change.
   `(let ((beg ,beg) (end ,end))
      (remove-text-properties beg end '(c-in-sws nil))
      ,@(when (facep 'c-debug-is-sws-face)
         `((c-debug-remove-face beg end 'c-debug-in-sws-face)))))
 
 (defmacro c-remove-is-and-in-sws (beg end)
+  ;; This macro does a hidden buffer change.
   `(let ((beg ,beg) (end ,end))
      (remove-text-properties beg end '(c-is-sws nil c-in-sws nil))
      ,@(when (facep 'c-debug-is-sws-face)
@@ -1255,6 +1432,8 @@ This function does not do any hidden buffer changes."
   ;; `c-forward-sws' or `c-backward-sws' are used outside
   ;; `c-save-buffer-state' or similar then this will remove the cache
   ;; properties right after they're added.
+  ;;
+  ;; This function does hidden buffer changes.
 
   (save-excursion
     ;; Adjust the end to remove the properties in any following simple
@@ -1291,6 +1470,8 @@ This function does not do any hidden buffer changes."
 
 (defun c-forward-sws ()
   ;; Used by `c-forward-syntactic-ws' to implement the unbounded search.
+  ;;
+  ;; This function might do hidden buffer changes.
 
   (let (;; `rung-pos' is set to a position as early as possible in the
        ;; unmarked part of the simple ws region.
@@ -1483,6 +1664,8 @@ This function does not do any hidden buffer changes."
 
 (defun c-backward-sws ()
   ;; Used by `c-backward-syntactic-ws' to implement the unbounded search.
+  ;;
+  ;; This function might do hidden buffer changes.
 
   (let (;; `rung-pos' is set to a position as late as possible in the unmarked
        ;; part of the simple ws region.
@@ -1703,12 +1886,13 @@ This function does not do any hidden buffer changes."
       )))
 
 \f
-;; A system for handling noteworthy parens before the point.
+;; A system for finding noteworthy parens before the point.
 
 (defvar c-state-cache nil)
 (make-variable-buffer-local 'c-state-cache)
 ;; The state cache used by `c-parse-state' to cut down the amount of
 ;; searching.  It's the result from some earlier `c-parse-state' call.
+;;
 ;; The use of the cached info is more effective if the next
 ;; `c-parse-state' call is on a line close by the one the cached state
 ;; was made at; the cache can actually slow down a little if the
@@ -1722,24 +1906,58 @@ This function does not do any hidden buffer changes."
 ;; change of narrowing is likely to affect the parens that are visible
 ;; before the point.
 
+(defvar c-state-cache-good-pos 1)
+(make-variable-buffer-local 'c-state-cache-good-pos)
+;; This is a position where `c-state-cache' is known to be correct.
+;; It's a position inside one of the recorded unclosed parens or the
+;; top level, but not further nested inside any literal or subparen
+;; that is closed before the last recorded position.
+;;
+;; The exact position is chosen to try to be close to yet earlier than
+;; the position where `c-state-cache' will be called next.  Right now
+;; the heuristic is to set it to the position after the last found
+;; closing paren (of any type) before the line on which
+;; `c-parse-state' was called.  That is chosen primarily to work well
+;; with refontification of the current line.
+
 (defsubst c-invalidate-state-cache (pos)
   ;; Invalidate all info on `c-state-cache' that applies to the buffer
   ;; at POS or higher.  This is much like `c-whack-state-after', but
   ;; it never changes a paren pair element into an open paren element.
   ;; Doing that would mean that the new open paren wouldn't have the
   ;; required preceding paren pair element.
-  ;;
-  ;; This function does not do any hidden buffer changes.
-  (while (and c-state-cache
+  (while (and (or c-state-cache
+                 (when (< pos c-state-cache-good-pos)
+                   (setq c-state-cache-good-pos 1)
+                   nil))
              (let ((elem (car c-state-cache)))
                (if (consp elem)
-                   (or (<= pos (car elem))
-                       (< pos (cdr elem)))
-                 (<= pos elem))))
+                   (or (< pos (cdr elem))
+                       (when (< pos c-state-cache-good-pos)
+                         (setq c-state-cache-good-pos (cdr elem))
+                         nil))
+                 (or (<= pos elem)
+                     (when (< pos c-state-cache-good-pos)
+                       (setq c-state-cache-good-pos (1+ elem))
+                       nil)))))
     (setq c-state-cache (cdr c-state-cache))))
 
+(defun c-get-fallback-start-pos (here)
+  ;; Return the start position for building `c-state-cache' from
+  ;; scratch.
+  (save-excursion
+    ;; Go back 2 bods, but ignore any bogus positions returned by
+    ;; beginning-of-defun (i.e. open paren in column zero).
+    (goto-char here)
+    (let ((cnt 2))
+      (while (not (or (bobp) (zerop cnt)))
+       (c-beginning-of-defun-1)
+       (if (eq (char-after) ?\{)
+           (setq cnt (1- cnt)))))
+    (point)))
+
 (defun c-parse-state ()
-  ;; Finds and records all noteworthy parens between some good point
+  ;; Find and record all noteworthy parens between some good point
   ;; earlier in the file and point.  That good point is at least the
   ;; beginning of the top-level construct we are in, or the beginning
   ;; of the preceding top-level construct if we aren't in one.
@@ -1750,22 +1968,32 @@ This function does not do any hidden buffer changes."
   ;; the point.  If an element is a cons, it gives the position of a
   ;; closed brace paren pair; the car is the start paren position and
   ;; the cdr is the position following the closing paren.  Only the
-  ;; last closed brace paren pair before each open paren is recorded,
-  ;; and thus the state never contains two cons elements in
-  ;; succession.
+  ;; last closed brace paren pair before each open paren and before
+  ;; the point is recorded, and thus the state never contains two cons
+  ;; elements in succession.
   ;;
   ;; Currently no characters which are given paren syntax with the
   ;; syntax-table property are recorded, i.e. angle bracket arglist
   ;; parens are never present here.  Note that this might change.
   ;;
-  ;; This function does not do any hidden buffer changes.
+  ;; BUG: This function doesn't cope entirely well with unbalanced
+  ;; parens in macros.  E.g. in the following case the brace before
+  ;; the macro isn't balanced with the one after it:
+  ;;
+  ;;     {
+  ;;     #define X {
+  ;;     }
+  ;;
+  ;; This function might do hidden buffer changes.
 
   (save-restriction
     (let* ((here (point))
+          (here-bol (c-point 'bol))
           (c-macro-start (c-query-macro-start))
           (in-macro-start (or c-macro-start (point)))
-          old-state last-pos pairs pos save-pos)
-      (c-invalidate-state-cache (point))
+          old-state last-pos brace-pair-open brace-pair-close
+          pos save-pos)
+      (c-invalidate-state-cache here)
 
       ;; If the minimum position has changed due to narrowing then we
       ;; have to fix the tail of `c-state-cache' accordingly.
@@ -1780,12 +2008,14 @@ This function does not do any hidden buffer changes."
                (setq ptr (cdr ptr)))
              (when (consp ptr)
                (if (eq (cdr ptr) c-state-cache)
-                   (setq c-state-cache nil)
+                   (setq c-state-cache nil
+                         c-state-cache-good-pos 1)
                  (setcdr ptr nil))))
          ;; If point-min has moved backward then we drop the state
          ;; completely.  It's possible to do a better job here and
          ;; recalculate the top only.
-         (setq c-state-cache nil))
+         (setq c-state-cache nil
+               c-state-cache-good-pos 1))
        (setq c-state-cache-start (point-min)))
 
       ;; Get the latest position we know are directly inside the
@@ -1794,115 +2024,152 @@ This function does not do any hidden buffer changes."
                          (if (consp (car c-state-cache))
                              (cdr (car c-state-cache))
                            (1+ (car c-state-cache)))))
-
-      ;; Check if the found last-pos is in a macro.  If it is, and
-      ;; we're not in the same macro, we must discard everything on
-      ;; c-state-cache that is inside the macro before using it.
-      (when last-pos
-       (save-excursion
-         (goto-char last-pos)
-         (when (and (c-beginning-of-macro)
-                    (/= (point) in-macro-start))
-           (c-invalidate-state-cache (point))
-           ;; Set last-pos again, just like above.
-           (setq last-pos (and c-state-cache
-                               (if (consp (car c-state-cache))
-                                   (cdr (car c-state-cache))
-                                 (1+ (car c-state-cache))))))))
-
-      (setq pos
-           ;; Find the start position for the forward search.  (Can't
-           ;; search in the backward direction since point might be
-           ;; in some kind of literal.)
-           (or (when last-pos
-
-                 ;; There's a cached state with a containing paren.  Pop
-                 ;; off the stale containing sexps from it by going
-                 ;; forward out of parens as far as possible.
-                 (narrow-to-region (point-min) here)
-                 (let (placeholder pair-beg)
-                   (while (and c-state-cache
-                               (setq placeholder
-                                     (c-up-list-forward last-pos)))
-                     (setq last-pos placeholder)
-                     (if (consp (car c-state-cache))
-                         (setq pair-beg (car-safe (cdr c-state-cache))
-                               c-state-cache (cdr-safe (cdr c-state-cache)))
-                       (setq pair-beg (car c-state-cache)
-                             c-state-cache (cdr c-state-cache))))
-
-                   (when (and pair-beg (eq (char-after pair-beg) ?{))
-                     ;; The last paren pair we moved out from was a brace
-                     ;; pair.  Modify the state to record this as a closed
-                     ;; pair now.
-                     (if (consp (car-safe c-state-cache))
-                         (setq c-state-cache (cdr c-state-cache)))
-                     (setq c-state-cache (cons (cons pair-beg last-pos)
-                                               c-state-cache))))
-
-                 ;; Check if the preceding balanced paren is within a
-                 ;; macro; it should be ignored if we're outside the
-                 ;; macro.  There's no need to check any further upwards;
-                 ;; if the macro contains an unbalanced opening paren then
-                 ;; we're smoked anyway.
-                 (when (and (<= (point) in-macro-start)
-                            (consp (car c-state-cache)))
-                   (save-excursion
-                     (goto-char (car (car c-state-cache)))
-                     (when (c-beginning-of-macro)
-                       (setq here (point)
-                             c-state-cache (cdr c-state-cache)))))
-
-                 (when c-state-cache
-                   (setq old-state c-state-cache)
-                   last-pos))
-
-               (save-excursion
-                 ;; go back 2 bods, but ignore any bogus positions
-                 ;; returned by beginning-of-defun (i.e. open paren in
-                 ;; column zero)
-                 (goto-char here)
-                 (let ((cnt 2))
-                   (while (not (or (bobp) (zerop cnt)))
-                     (c-beginning-of-defun-1)
-                     (if (eq (char-after) ?\{)
-                         (setq cnt (1- cnt)))))
-                 (point))))
+      (if (or (not last-pos)
+             (< last-pos c-state-cache-good-pos))
+         (setq last-pos c-state-cache-good-pos)
+       ;; Take the opportunity to move the cached good position
+       ;; further down.
+       (if (< last-pos here-bol)
+           (setq c-state-cache-good-pos last-pos)))
+
+      ;; Check if `last-pos' is in a macro.  If it is, and we're not
+      ;; in the same macro, we must discard everything on
+      ;; `c-state-cache' that is inside the macro before using it.
+      (save-excursion
+       (goto-char last-pos)
+       (when (and (c-beginning-of-macro)
+                  (/= (point) in-macro-start))
+         (c-invalidate-state-cache (point))
+         ;; Set `last-pos' again just like above except that there's
+         ;; no use looking at `c-state-cache-good-pos' here.
+         (setq last-pos (if c-state-cache
+                            (if (consp (car c-state-cache))
+                                (cdr (car c-state-cache))
+                              (1+ (car c-state-cache)))
+                          1))))
+
+      ;; If we've moved very far from the last cached position then
+      ;; it's probably better to redo it from scratch, otherwise we
+      ;; might spend a lot of time searching from `last-pos' down to
+      ;; here.
+      (when (< last-pos (- here 20000))
+       ;; First get the fallback start position.  If it turns out
+       ;; that it's so far back that the cached state is closer then
+       ;; we'll keep it afterall.
+       (setq pos (c-get-fallback-start-pos here))
+       (if (<= pos last-pos)
+           (setq pos nil)
+         (setq last-pos nil
+               c-state-cache nil
+               c-state-cache-good-pos 1)))
+
+      ;; Find the start position for the forward search.  (Can't
+      ;; search in the backward direction since the point might be in
+      ;; some kind of literal.)
+
+      (unless pos
+       (setq old-state c-state-cache)
+
+       ;; There's a cached state with a containing paren.  Pop off
+       ;; the stale containing sexps from it by going forward out of
+       ;; parens as far as possible.
+       (narrow-to-region (point-min) here)
+       (let (placeholder pair-beg)
+         (while (and c-state-cache
+                     (setq placeholder
+                           (c-up-list-forward last-pos)))
+           (setq last-pos placeholder)
+           (if (consp (car c-state-cache))
+               (setq pair-beg (car-safe (cdr c-state-cache))
+                     c-state-cache (cdr-safe (cdr c-state-cache)))
+             (setq pair-beg (car c-state-cache)
+                   c-state-cache (cdr c-state-cache))))
+
+         (when (and pair-beg (eq (char-after pair-beg) ?{))
+           ;; The last paren pair we moved out from was a brace
+           ;; pair.  Modify the state to record this as a closed
+           ;; pair now.
+           (if (consp (car-safe c-state-cache))
+               (setq c-state-cache (cdr c-state-cache)))
+           (setq c-state-cache (cons (cons pair-beg last-pos)
+                                     c-state-cache))))
+
+       ;; Check if the preceding balanced paren is within a
+       ;; macro; it should be ignored if we're outside the
+       ;; macro.  There's no need to check any further upwards;
+       ;; if the macro contains an unbalanced opening paren then
+       ;; we're smoked anyway.
+       (when (and (<= (point) in-macro-start)
+                  (consp (car c-state-cache)))
+         (save-excursion
+           (goto-char (car (car c-state-cache)))
+           (when (c-beginning-of-macro)
+             (setq here (point)
+                   c-state-cache (cdr c-state-cache)))))
+
+       (unless (eq c-state-cache old-state)
+         ;; Have to adjust the cached good position if state has been
+         ;; popped off.
+         (setq c-state-cache-good-pos
+               (if c-state-cache
+                   (if (consp (car c-state-cache))
+                       (cdr (car c-state-cache))
+                     (1+ (car c-state-cache)))
+                 1)
+               old-state c-state-cache))
+
+       (when c-state-cache
+         (setq pos last-pos)))
+
+      ;; Get the fallback start position.
+      (unless pos
+       (setq pos (c-get-fallback-start-pos here)
+             c-state-cache nil
+             c-state-cache-good-pos 1))
 
       (narrow-to-region (point-min) here)
 
       (while pos
-       ;; Find the balanced brace pairs.
        (setq save-pos pos
-             pairs nil)
-       (while (and (setq last-pos (c-down-list-forward pos))
-                   (setq pos (c-up-list-forward last-pos)))
-         (if (eq (char-before last-pos) ?{)
-             (setq pairs (cons (cons last-pos pos) pairs))))
-
-       ;; Should ignore any pairs that are in a macro, providing
-       ;; we're not in the same one.
-       (when (and pairs (< (car (car pairs)) in-macro-start))
-         (while (and (save-excursion
-                       (goto-char (car (car pairs)))
-                       (c-beginning-of-macro))
-                     (setq pairs (cdr pairs)))))
+             brace-pair-open nil)
+
+       ;; Find the balanced brace pairs.  This loop is hot, so it
+       ;; does ugly tricks to go faster.
+       (c-safe
+         (let (set-good-pos set-brace-pair)
+           (while t
+             (setq last-pos nil
+                   last-pos (scan-lists pos 1 -1)) ; Might signal.
+             (setq pos (scan-lists last-pos 1 1) ; Might signal.
+                   set-good-pos (< pos here-bol)
+                   set-brace-pair (eq (char-before last-pos) ?{))
+
+             ;; Update the cached good position and record the brace
+             ;; pair, whichever is applicable for the paren we've
+             ;; just jumped over.  But first check that it isn't
+             ;; inside a macro and the point isn't inside the same
+             ;; one.
+             (when (and (or set-good-pos set-brace-pair)
+                        (or (>= pos in-macro-start)
+                            (save-excursion
+                              (goto-char pos)
+                              (not (c-beginning-of-macro)))))
+               (if set-good-pos
+                   (setq c-state-cache-good-pos pos))
+               (if set-brace-pair
+                   (setq brace-pair-open last-pos
+                         brace-pair-close pos))))))
 
        ;; Record the last brace pair.
-       (when pairs
-         (if (and (eq c-state-cache old-state)
-                  (consp (car-safe c-state-cache)))
-             ;; There's a closed pair on the cached state but we've
-             ;; found a later one, so remove it.
-             (setq c-state-cache (cdr c-state-cache)))
-         (setq pairs (car pairs))
-         (setcar pairs (1- (car pairs)))
-         (when (consp (car-safe c-state-cache))
-           ;; There could already be a cons first in `c-state-cache'
-           ;; if we've e.g. jumped over an unbalanced open paren in a
-           ;; macro below.
-           (setq c-state-cache (cdr c-state-cache)))
-         (setq c-state-cache (cons pairs c-state-cache)))
+       (when brace-pair-open
+         (let ((head (car-safe c-state-cache)))
+           (if (consp head)
+               (progn
+                 (setcar head (1- brace-pair-open))
+                 (setcdr head brace-pair-close))
+             (setq c-state-cache (cons (cons (1- brace-pair-open)
+                                             brace-pair-close)
+                                       c-state-cache)))))
 
        (if last-pos
            ;; Prepare to loop, but record the open paren only if it's
@@ -1911,16 +2178,18 @@ This function does not do any hidden buffer changes."
            ;; that got an open paren syntax-table property.
            (progn
              (setq pos last-pos)
-             (if (and (or (>= last-pos in-macro-start)
-                          (save-excursion
-                            (goto-char last-pos)
-                            (not (c-beginning-of-macro))))
-                      ;; Check for known types of parens that we want
-                      ;; to record.  The syntax table is not to be
-                      ;; trusted here since the caller might be using
-                      ;; e.g. `c++-template-syntax-table'.
-                      (memq (char-before last-pos) '(?{ ?\( ?\[)))
-                 (setq c-state-cache (cons (1- last-pos) c-state-cache))))
+             (when (and (or (>= last-pos in-macro-start)
+                            (save-excursion
+                              (goto-char last-pos)
+                              (not (c-beginning-of-macro))))
+                        ;; Check for known types of parens that we
+                        ;; want to record.  The syntax table is not to
+                        ;; be trusted here since the caller might be
+                        ;; using e.g. `c++-template-syntax-table'.
+                        (memq (char-before last-pos) '(?{ ?\( ?\[)))
+               (if (< last-pos here-bol)
+                   (setq c-state-cache-good-pos last-pos))
+               (setq c-state-cache (cons (1- last-pos) c-state-cache))))
 
          (if (setq last-pos (c-up-list-forward pos))
              ;; Found a close paren without a corresponding opening
@@ -1928,7 +2197,8 @@ This function does not do any hidden buffer changes."
              ;; scan backward for the start paren and then start over.
              (progn
                (setq pos (c-up-list-backward pos)
-                     c-state-cache nil)
+                     c-state-cache nil
+                     c-state-cache-good-pos c-state-cache-start)
                (when (or (not pos)
                          ;; Emacs (up to at least 21.2) can get confused by
                          ;; open parens in column zero inside comments: The
@@ -1943,6 +2213,7 @@ This function does not do any hidden buffer changes."
                                                 (c-point 'bol last-pos)))))))
            (setq pos nil))))
 
+      ;;(message "c-parse-state: %S end: %S" c-state-cache c-state-cache-good-pos)
       c-state-cache)))
 
 ;; Debug tool to catch cache inconsistencies.
@@ -1952,11 +2223,23 @@ This function does not do any hidden buffer changes."
 (cc-bytecomp-defun c-real-parse-state)
 (defun c-debug-parse-state ()
   (let ((res1 (c-real-parse-state)) res2)
-    (let ((c-state-cache nil))
+    (let ((c-state-cache nil)
+         (c-state-cache-start 1)
+         (c-state-cache-good-pos 1))
       (setq res2 (c-real-parse-state)))
     (unless (equal res1 res2)
-      (error "c-parse-state inconsistency: using cache: %s, from scratch: %s"
-            res1 res2))
+      ;; The cache can actually go further back due to the ad-hoc way
+      ;; the first paren is found, so try to whack off a bit of its
+      ;; start before complaining.
+      (save-excursion
+       (goto-char (or (c-least-enclosing-brace res2) (point)))
+       (c-beginning-of-defun-1)
+       (while (not (or (bobp) (eq (char-after) ?{)))
+         (c-beginning-of-defun-1))
+       (unless (equal (c-whack-state-before (point) res1) res2)
+         (message (concat "c-parse-state inconsistency: "
+                          "using cache: %s, from scratch: %s")
+                  res1 res2))))
     res1))
 (defun c-toggle-parse-state-debug (&optional arg)
   (interactive "P")
@@ -1965,12 +2248,12 @@ This function does not do any hidden buffer changes."
                                            'c-debug-parse-state
                                          'c-real-parse-state)))
   (c-keep-region-active))
+(when c-debug-parse-state
+  (c-toggle-parse-state-debug 1))
 
 (defun c-whack-state-before (bufpos paren-state)
   ;; Whack off any state information from PAREN-STATE which lies
   ;; before BUFPOS.  Not destructive on PAREN-STATE.
-  ;;
-  ;; This function does not do any hidden buffer changes.
   (let* ((newstate (list nil))
         (ptr newstate)
         car)
@@ -1986,8 +2269,6 @@ This function does not do any hidden buffer changes."
 (defun c-whack-state-after (bufpos paren-state)
   ;; Whack off any state information from PAREN-STATE which lies at or
   ;; after BUFPOS.  Not destructive on PAREN-STATE.
-  ;;
-  ;; This function does not do any hidden buffer changes.
   (catch 'done
     (while paren-state
       (let ((car (car paren-state)))
@@ -2018,9 +2299,7 @@ This function does not do any hidden buffer changes."
 
 (defun c-most-enclosing-brace (paren-state &optional bufpos)
   ;; Return the bufpos of the innermost enclosing open paren before
-  ;; bufpos that hasn't been narrowed out, or nil if none was found.
-  ;;
-  ;; This function does not do any hidden buffer changes.
+  ;; bufpos, or nil if none was found.
   (let (enclosingp)
     (or bufpos (setq bufpos 134217727))
     (while paren-state
@@ -2029,34 +2308,31 @@ This function does not do any hidden buffer changes."
       (if (or (consp enclosingp)
              (>= enclosingp bufpos))
          (setq enclosingp nil)
-       (if (< enclosingp (point-min))
-           (setq enclosingp nil))
        (setq paren-state nil)))
     enclosingp))
 
-(defun c-least-enclosing-brace (paren-state &optional bufpos)
-  ;; Return the bufpos of the outermost enclosing open paren before
-  ;; bufpos that hasn't been narrowed out, or nil if none was found.
-  ;;
-  ;; This function does not do any hidden buffer changes.
+(defun c-least-enclosing-brace (paren-state)
+  ;; Return the bufpos of the outermost enclosing open paren, or nil
+  ;; if none was found.
   (let (pos elem)
-    (or bufpos (setq bufpos 134217727))
     (while paren-state
       (setq elem (car paren-state)
            paren-state (cdr paren-state))
-      (unless (or (consp elem)
-                 (>= elem bufpos))
-       (if (>= elem (point-min))
-           (setq pos elem))))
+      (if (integerp elem)
+         (setq pos elem)))
     pos))
 
 (defun c-safe-position (bufpos paren-state)
-  ;; Return the closest known safe position higher up than BUFPOS, or
-  ;; nil if PAREN-STATE doesn't contain one.  Return nil if BUFPOS is
-  ;; nil, which is useful to find the closest limit before a given
-  ;; limit that might be nil.
+  ;; Return the closest "safe" position recorded on PAREN-STATE that
+  ;; is higher up than BUFPOS.  Return nil if PAREN-STATE doesn't
+  ;; contain any.  Return nil if BUFPOS is nil, which is useful to
+  ;; find the closest limit before a given limit that might be nil.
   ;;
-  ;; This function does not do any hidden buffer changes.
+  ;; A "safe" position is a position at or after a recorded open
+  ;; paren, or after a recorded close paren.  The returned position is
+  ;; thus either the first position after a close brace, or the first
+  ;; position after an enclosing paren, or at the enclosing paren in
+  ;; case BUFPOS is immediately after it.
   (when bufpos
     (let (elem)
       (catch 'done
@@ -2118,33 +2394,61 @@ This function does not do any hidden buffer changes."
   "Return non-nil if the point is on or directly after an identifier.
 Keywords are recognized and not considered identifiers.  If an
 identifier is detected, the returned value is its starting position.
-If an identifier both starts and stops at the point \(can only happen
-in Pike) then the point for the preceding one is returned.
+If an identifier ends at the point and another begins at it \(can only
+happen in Pike) then the point for the preceding one is returned.
 
-This function does not do any hidden buffer changes."
+Note that this function might do hidden buffer changes.  See the
+comment at the start of cc-engine.el for more info."
+
+  ;; FIXME: Shouldn't this function handle "operator" in C++?
 
   (save-excursion
-    (if (zerop (skip-syntax-backward "w_"))
-
-       (when (c-major-mode-is 'pike-mode)
-         ;; Handle the `<operator> syntax in Pike.
-         (let ((pos (point)))
-           (skip-chars-backward "-!%&*+/<=>^|~[]()")
-           (and (if (< (skip-chars-backward "`") 0)
-                    t
-                  (goto-char pos)
-                  (eq (char-after) ?\`))
-                (looking-at c-symbol-key)
-                (>= (match-end 0) pos)
-                (point))))
-
-      (and (not (looking-at c-keywords-regexp))
-          (point)))))
+    (skip-syntax-backward "w_")
+
+    (or
+
+     ;; Check for a normal (non-keyword) identifier.
+     (and (looking-at c-symbol-start)
+         (not (looking-at c-keywords-regexp))
+         (point))
+
+     (when (c-major-mode-is 'pike-mode)
+       ;; Handle the `<operator> syntax in Pike.
+       (let ((pos (point)))
+        (skip-chars-backward "-!%&*+/<=>^|~[]()")
+        (and (if (< (skip-chars-backward "`") 0)
+                 t
+               (goto-char pos)
+               (eq (char-after) ?\`))
+             (looking-at c-symbol-key)
+             (>= (match-end 0) pos)
+             (point))))
+
+     ;; Handle the "operator +" syntax in C++.
+     (when (and c-overloadable-operators-regexp
+               (= (c-backward-token-2 0) 0))
+
+       (cond ((and (looking-at c-overloadable-operators-regexp)
+                  (or (not c-opt-op-identitier-prefix)
+                      (and (= (c-backward-token-2 1) 0)
+                           (looking-at c-opt-op-identitier-prefix))))
+             (point))
+
+            ((save-excursion
+               (and c-opt-op-identitier-prefix
+                    (looking-at c-opt-op-identitier-prefix)
+                    (= (c-forward-token-2 1) 0)
+                    (looking-at c-overloadable-operators-regexp)))
+             (point))))
+
+     )))
 
 (defsubst c-simple-skip-symbol-backward ()
   ;; If the point is at the end of a symbol then skip backward to the
   ;; beginning of it.  Don't move otherwise.  Return non-nil if point
   ;; moved.
+  ;;
+  ;; This function might do hidden buffer changes.
   (or (< (skip-syntax-backward "w_") 0)
       (and (c-major-mode-is 'pike-mode)
           ;; Handle the `<operator> syntax in Pike.
@@ -2157,11 +2461,13 @@ This function does not do any hidden buffer changes."
               (goto-char pos)
               nil)))))
 
-(defsubst c-beginning-of-current-token (&optional back-limit)
+(defun c-beginning-of-current-token (&optional back-limit)
   ;; Move to the beginning of the current token.  Do not move if not
   ;; in the middle of one.  BACK-LIMIT may be used to bound the
   ;; backward search; if given it's assumed to be at the boundary
   ;; between two tokens.
+  ;;
+  ;; This function might do hidden buffer changes.
   (if (looking-at "\\w\\|\\s_")
       (skip-syntax-backward "w_" back-limit)
     (let ((start (point)))
@@ -2183,6 +2489,8 @@ This function does not do any hidden buffer changes."
   ;; middle of one.  BACK-LIMIT may be used to bound the backward
   ;; search; if given it's assumed to be at the boundary between two
   ;; tokens.  Return non-nil if the point is moved, nil otherwise.
+  ;;
+  ;; This function might do hidden buffer changes.
   (let ((start (point)))
     (cond ((< (skip-syntax-backward "w_" (1- start)) 0)
           (skip-syntax-forward "w_"))
@@ -2228,7 +2536,10 @@ BALANCED is true, a move over a balanced paren counts as one.  Note
 that if COUNT is 0 and no appropriate token beginning is found, 1 will
 be returned.  Thus, a return value of 0 guarantees that point is at
 the requested position and a return value less \(without signs) than
-COUNT guarantees that point is at the beginning of some token."
+COUNT guarantees that point is at the beginning of some token.
+
+Note that this function might do hidden buffer changes.  See the
+comment at the start of cc-engine.el for more info."
 
   (or count (setq count 1))
   (if (< count 0)
@@ -2417,7 +2728,10 @@ matches syntactic whitespace.
 
 Bug: Unbalanced parens inside cpp directives are currently not handled
 correctly \(i.e. they don't get ignored as they should) when
-PAREN-LEVEL is set."
+PAREN-LEVEL is set.
+
+Note that this function might do hidden buffer changes.  See the
+comment at the start of cc-engine.el for more info."
 
   (or bound (setq bound (point-max)))
   (if paren-level (setq paren-level -1))
@@ -2601,23 +2915,39 @@ PAREN-LEVEL is set."
        (goto-char bound))
       nil)))
 
-(defun c-syntactic-skip-backward (skip-chars &optional limit)
+(defun c-syntactic-skip-backward (skip-chars &optional limit paren-level)
   "Like `skip-chars-backward' but only look at syntactically relevant chars,
 i.e. don't stop at positions inside syntactic whitespace or string
 literals.  Preprocessor directives are also ignored, with the exception
 of the one that the point starts within, if any.  If LIMIT is given,
-it's assumed to be at a syntactically relevant position."
+it's assumed to be at a syntactically relevant position.
+
+If PAREN-LEVEL is non-nil, the function won't stop in nested paren
+sexps, and the search will also not go outside the current paren sexp.
+However, if LIMIT or the buffer limit is reached inside a nested paren
+then the point will be left at the limit.
+
+Non-nil is returned if the point moved, nil otherwise.
+
+Note that this function might do hidden buffer changes.  See the
+comment at the start of cc-engine.el for more info."
 
   (let ((start (point))
+       state
        ;; A list of syntactically relevant positions in descending
        ;; order.  It's used to avoid scanning repeatedly over
        ;; potentially large regions with `parse-partial-sexp' to verify
        ;; each position.
        safe-pos-list
+       ;; The position at the beginning of `safe-pos-list'.
+       safe-pos
        ;; The result from `c-beginning-of-macro' at the start position or the
        ;; start position itself if it isn't within a macro.  Evaluated on
        ;; demand.
-       start-macro-beg)
+       start-macro-beg
+       ;; The earliest position after the current one with the same paren
+       ;; level.  Used only when `paren-level' is set.
+       (paren-level-pos (point)))
 
     (while (progn
             (while (and
@@ -2626,7 +2956,7 @@ it's assumed to be at a syntactically relevant position."
                     ;; Use `parse-partial-sexp' from a safe position down to
                     ;; the point to check if it's outside comments and
                     ;; strings.
-                    (let ((pos (point)) safe-pos state)
+                    (let ((pos (point)) state-2 pps-end-pos)
                       ;; Pick a safe position as close to the point as
                       ;; possible.
                       ;;
@@ -2643,13 +2973,18 @@ it's assumed to be at a syntactically relevant position."
                                             (point-min))
                               safe-pos-list (list safe-pos)))
 
+                      ;; Cache positions along the way to use if we have to
+                      ;; back up more.  We cache every closing paren on the
+                      ;; same level.  If the paren cache is relevant in this
+                      ;; region then we're typically already on the same
+                      ;; level as the target position.  Note that we might
+                      ;; cache positions after opening parens in case
+                      ;; safe-pos is in a nested list.  That's both uncommon
+                      ;; and harmless.
                       (while (progn
                                (setq state (parse-partial-sexp
                                             safe-pos pos 0))
                                (< (point) pos))
-                        ;; Cache positions along the way to use if we have to
-                        ;; back up more.  Every closing paren on the same
-                        ;; level seems like fairly well spaced positions.
                         (setq safe-pos (point)
                               safe-pos-list (cons safe-pos safe-pos-list)))
 
@@ -2657,13 +2992,50 @@ it's assumed to be at a syntactically relevant position."
                        ((or (elt state 3) (elt state 4))
                         ;; Inside string or comment.  Continue search at the
                         ;; beginning of it.
-                        (if (setq pos (nth 8 state))
-                            ;; It's an emacs where `parse-partial-sexp'
-                            ;; supplies the starting position.
-                            (goto-char pos)
-                          (goto-char (car (c-literal-limits safe-pos))))
+                        (goto-char (elt state 8))
                         t)
 
+                       ((and paren-level
+                             (save-excursion
+                               (setq state-2 (parse-partial-sexp
+                                              pos paren-level-pos -1)
+                                     pps-end-pos (point))
+                               (/= (car state-2) 0)))
+                        ;; Not at the right level.
+
+                        (if (and (< (car state-2) 0)
+                                 ;; We stop above if we go out of a paren.
+                                 ;; Now check whether it precedes or is
+                                 ;; nested in the starting sexp.
+                                 (save-excursion
+                                   (setq state-2
+                                         (parse-partial-sexp
+                                          pps-end-pos paren-level-pos
+                                          nil nil state-2))
+                                   (< (car state-2) 0)))
+
+                            ;; We've stopped short of the starting position
+                            ;; so the hit was inside a nested list.  Go up
+                            ;; until we are at the right level.
+                            (condition-case nil
+                                (progn
+                                  (goto-char (scan-lists pos -1
+                                                         (- (car state-2))))
+                                  (setq paren-level-pos (point))
+                                  (if (and limit (>= limit paren-level-pos))
+                                      (progn
+                                        (goto-char limit)
+                                        nil)
+                                    t))
+                              (error
+                               (goto-char (or limit (point-min)))
+                               nil))
+
+                          ;; The hit was outside the list at the start
+                          ;; position.  Go to the start of the list and exit.
+                          (goto-char (1+ (elt state-2 1)))
+                          nil))
+
                        ((c-beginning-of-macro limit)
                         ;; Inside a macro.
                         (if (< (point)
@@ -2674,10 +3046,20 @@ it's assumed to be at a syntactically relevant position."
                                            (c-beginning-of-macro limit)
                                            (point)))))
                             t
+
                           ;; It's inside the same macro we started in so it's
                           ;; a relevant match.
                           (goto-char pos)
-                          nil))))))
+                          nil)))))
+
+              ;; If the state contains the start of the containing sexp we
+              ;; cache that position too, so that parse-partial-sexp in the
+              ;; next run has a bigger chance of starting at the same level
+              ;; as the target position and thus will get more good safe
+              ;; positions into the list.
+              (if (elt state 1)
+                  (setq safe-pos (1+ (elt state 1))
+                        safe-pos-list (cons safe-pos safe-pos-list))))
 
             (> (point)
                (progn
@@ -2686,7 +3068,124 @@ it's assumed to be at a syntactically relevant position."
                  (c-backward-syntactic-ws)
                  (point)))))
 
-    (- (point) start)))
+    ;; We might want to extend this with more useful return values in
+    ;; the future.
+    (/= (point) start)))
+
+;; The following is an alternative implementation of
+;; `c-syntactic-skip-backward' that uses backward movement to keep
+;; track of the syntactic context.  It turned out to be generally
+;; slower than the one above which uses forward checks from earlier
+;; safe positions.
+;;
+;;(defconst c-ssb-stop-re
+;;  ;; The regexp matching chars `c-syntactic-skip-backward' needs to
+;;  ;; stop at to avoid going into comments and literals.
+;;  (concat
+;;   ;; Match comment end syntax and string literal syntax.  Also match
+;;   ;; '/' for block comment endings (not covered by comment end
+;;   ;; syntax).
+;;   "\\s>\\|/\\|\\s\""
+;;   (if (memq 'gen-string-delim c-emacs-features)
+;;      "\\|\\s|"
+;;     "")
+;;   (if (memq 'gen-comment-delim c-emacs-features)
+;;      "\\|\\s!"
+;;     "")))
+;;
+;;(defconst c-ssb-stop-paren-re
+;;  ;; Like `c-ssb-stop-re' but also stops at paren chars.
+;;  (concat c-ssb-stop-re "\\|\\s(\\|\\s)"))
+;;
+;;(defconst c-ssb-sexp-end-re
+;;  ;; Regexp matching the ending syntax of a complex sexp.
+;;  (concat c-string-limit-regexp "\\|\\s)"))
+;;
+;;(defun c-syntactic-skip-backward (skip-chars &optional limit paren-level)
+;;  "Like `skip-chars-backward' but only look at syntactically relevant chars,
+;;i.e. don't stop at positions inside syntactic whitespace or string
+;;literals.  Preprocessor directives are also ignored.  However, if the
+;;point is within a comment, string literal or preprocessor directory to
+;;begin with, its contents is treated as syntactically relevant chars.
+;;If LIMIT is given, it limits the backward search and the point will be
+;;left there if no earlier position is found.
+;;
+;;If PAREN-LEVEL is non-nil, the function won't stop in nested paren
+;;sexps, and the search will also not go outside the current paren sexp.
+;;However, if LIMIT or the buffer limit is reached inside a nested paren
+;;then the point will be left at the limit.
+;;
+;;Non-nil is returned if the point moved, nil otherwise.
+;;
+;;Note that this function might do hidden buffer changes.  See the
+;;comment at the start of cc-engine.el for more info."
+;;
+;;  (save-restriction
+;;    (when limit
+;;     (narrow-to-region limit (point-max)))
+;;
+;;    (let ((start (point)))
+;;     (catch 'done
+;;       (while (let ((last-pos (point))
+;;                    (stop-pos (progn
+;;                                (skip-chars-backward skip-chars)
+;;                                (point))))
+;;
+;;                ;; Skip back over the same region as
+;;                ;; `skip-chars-backward' above, but keep to
+;;                ;; syntactically relevant positions.
+;;                (goto-char last-pos)
+;;                (while (and
+;;                        ;; `re-search-backward' with a single char regexp
+;;                        ;; should be fast.
+;;                        (re-search-backward
+;;                         (if paren-level c-ssb-stop-paren-re c-ssb-stop-re)
+;;                         stop-pos 'move)
+;;
+;;                        (progn
+;;                          (cond
+;;                           ((looking-at "\\s(")
+;;                            ;; `paren-level' is set and we've found the
+;;                            ;; start of the containing paren.
+;;                            (forward-char)
+;;                            (throw 'done t))
+;;
+;;                           ((looking-at c-ssb-sexp-end-re)
+;;                            ;; We're at the end of a string literal or paren
+;;                            ;; sexp (if `paren-level' is set).
+;;                            (forward-char)
+;;                            (condition-case nil
+;;                                (c-backward-sexp)
+;;                              (error
+;;                               (goto-char limit)
+;;                               (throw 'done t))))
+;;
+;;                           (t
+;;                            (forward-char)
+;;                            ;; At the end of some syntactic ws or possibly
+;;                            ;; after a plain '/' operator.
+;;                            (let ((pos (point)))
+;;                              (c-backward-syntactic-ws)
+;;                              (if (= pos (point))
+;;                                  ;; Was a plain '/' operator.  Go past it.
+;;                                  (backward-char)))))
+;;
+;;                          (> (point) stop-pos))))
+;;
+;;                ;; Now the point is either at `stop-pos' or at some
+;;                ;; position further back if `stop-pos' was at a
+;;                ;; syntactically irrelevant place.
+;;
+;;                ;; Skip additional syntactic ws so that we don't stop
+;;                ;; at the end of a comment if `skip-chars' is
+;;                ;; something like "^/".
+;;                (c-backward-syntactic-ws)
+;;
+;;                (< (point) stop-pos))))
+;;
+;;     ;; We might want to extend this with more useful return values
+;;     ;; in the future.
+;;     (/= (point) start))))
 
 \f
 ;; Tools for handling comments and string literals.
@@ -2702,7 +3201,9 @@ or nil, `c-beginning-of-defun' is used.
 The last point calculated is cached if the cache is enabled, i.e. if
 `c-in-literal-cache' is bound to a two element vector.
 
-This function does not do any hidden buffer changes."
+Note that this function might do hidden buffer changes.  See the
+comment at the start of cc-engine.el for more info."
+
   (if (and (vectorp c-in-literal-cache)
           (= (point) (aref c-in-literal-cache 0)))
       (aref c-in-literal-cache 1)
@@ -2748,6 +3249,7 @@ This function does not do any hidden buffer changes."
 ;; (Alan Mackenzie, 2003/4/30).
 
 (defun c-fast-in-literal (&optional lim detect-cpp)
+  ;; This function might do hidden buffer changes.
   (let ((context (buffer-syntactic-context)))
     (cond
      ((eq context 'string) 'string)
@@ -2775,7 +3277,8 @@ non-nil, the case when point is inside a starting delimiter won't be
 recognized.  This only has effect for comments, which have starting
 delimiters with more than one character.
 
-This function does not do any hidden buffer changes."
+Note that this function might do hidden buffer changes.  See the
+comment at the start of cc-engine.el for more info."
 
   (save-excursion
     (let* ((pos (point))
@@ -2784,32 +3287,13 @@ This function does not do any hidden buffer changes."
                          (point))))
           (state (parse-partial-sexp lim pos)))
 
-      (cond ((elt state 3)
-            ;; String.  Search backward for the start.
-            (while (elt state 3)
-              (search-backward (make-string 1 (elt state 3)))
-              (setq state (parse-partial-sexp lim (point))))
+      (cond ((elt state 3)             ; String.
+            (goto-char (elt state 8))
             (cons (point) (or (c-safe (c-forward-sexp 1) (point))
                               (point-max))))
 
-           ((elt state 7)
-            ;; Line comment.  Search from bol for the comment starter.
-            (beginning-of-line)
-            (setq state (parse-partial-sexp lim (point))
-                  lim (point))
-            (while (not (elt state 7))
-              (search-forward "//")    ; Should never fail.
-              (setq state (parse-partial-sexp
-                           lim (point) nil nil state)
-                    lim (point)))
-            (backward-char 2)
-            (cons (point) (progn (c-forward-single-comment) (point))))
-
-           ((elt state 4)
-            ;; Block comment.  Search backward for the comment starter.
-            (while (elt state 4)
-              (search-backward "/*")   ; Should never fail.
-              (setq state (parse-partial-sexp lim (point))))
+           ((elt state 4)              ; Comment.
+            (goto-char (elt state 8))
             (cons (point) (progn (c-forward-single-comment) (point))))
 
            ((and (not not-in-delimiter)
@@ -2857,122 +3341,46 @@ This function does not do any hidden buffer changes."
                 (if beg (cons beg end))))))
            ))))
 
-(defun c-literal-limits-fast (&optional lim near not-in-delimiter)
-  ;; Like c-literal-limits, but for emacsen whose `parse-partial-sexp'
-  ;; returns the pos of the comment start.
+;; In case external callers use this; it did have a docstring.
+(defalias 'c-literal-limits-fast 'c-literal-limits)
 
-  "Return a cons of the beginning and end positions of the comment or
-string surrounding point (including both delimiters), or nil if point
-isn't in one.  If LIM is non-nil, it's used as the \"safe\" position
-to start parsing from.  If NEAR is non-nil, then the limits of any
-literal next to point is returned.  \"Next to\" means there's only
-spaces and tabs between point and the literal.  The search for such a
-literal is done first in forward direction.  If NOT-IN-DELIMITER is
-non-nil, the case when point is inside a starting delimiter won't be
-recognized.  This only has effect for comments, which have starting
-delimiters with more than one character.
+(defun c-collect-line-comments (range)
+  "If the argument is a cons of two buffer positions (such as returned by
+`c-literal-limits'), and that range contains a C++ style line comment,
+then an extended range is returned that contains all adjacent line
+comments (i.e. all comments that starts in the same column with no
+empty lines or non-whitespace characters between them).  Otherwise the
+argument is returned.
 
-This function does not do any hidden buffer changes."
+Note that this function might do hidden buffer changes.  See the
+comment at the start of cc-engine.el for more info."
 
   (save-excursion
-    (let* ((pos (point))
-          (lim (or lim (progn
-                         (c-beginning-of-syntax)
-                         (point))))
-          (state (parse-partial-sexp lim pos)))
-
-      (cond ((elt state 3)             ; String.
-            (goto-char (elt state 8))
-            (cons (point) (or (c-safe (c-forward-sexp 1) (point))
-                              (point-max))))
-
-           ((elt state 4)              ; Comment.
-            (goto-char (elt state 8))
-            (cons (point) (progn (c-forward-single-comment) (point))))
-
-           ((and (not not-in-delimiter)
-                 (not (elt state 5))
-                 (eq (char-before) ?/)
-                 (looking-at "[/*]"))
-            ;; We're standing in a comment starter.
-            (backward-char 1)
-            (cons (point) (progn (c-forward-single-comment) (point))))
-
-           (near
-            (goto-char pos)
-
-            ;; Search forward for a literal.
-            (skip-chars-forward " \t")
-
-            (cond
-             ((looking-at c-string-limit-regexp) ; String.
-              (cons (point) (or (c-safe (c-forward-sexp 1) (point))
-                                (point-max))))
-
-             ((looking-at c-comment-start-regexp) ; Line or block comment.
-              (cons (point) (progn (c-forward-single-comment) (point))))
-
-             (t
-              ;; Search backward.
-              (skip-chars-backward " \t")
-
-              (let ((end (point)) beg)
-                (cond
-                 ((save-excursion
-                    (< (skip-syntax-backward c-string-syntax) 0)) ; String.
-                  (setq beg (c-safe (c-backward-sexp 1) (point))))
-
-                 ((and (c-safe (forward-char -2) t)
-                       (looking-at "*/"))
-                  ;; Block comment.  Due to the nature of line
-                  ;; comments, they will always be covered by the
-                  ;; normal case above.
-                  (goto-char end)
-                  (c-backward-single-comment)
-                  ;; If LIM is bogus, beg will be bogus.
-                  (setq beg (point))))
-
-                (if beg (cons beg end))))))
-           ))))
-
-(if (memq 'pps-extended-state c-emacs-features)
-    (defalias 'c-literal-limits 'c-literal-limits-fast))
-
-(defun c-collect-line-comments (range)
-  "If the argument is a cons of two buffer positions (such as returned by
-`c-literal-limits'), and that range contains a C++ style line comment,
-then an extended range is returned that contains all adjacent line
-comments (i.e. all comments that starts in the same column with no
-empty lines or non-whitespace characters between them).  Otherwise the
-argument is returned.
-
-This function does not do any hidden buffer changes."
-  (save-excursion
-    (condition-case nil
-       (if (and (consp range) (progn
-                                (goto-char (car range))
-                                (looking-at "//")))
-           (let ((col (current-column))
-                 (beg (point))
-                 (bopl (c-point 'bopl))
-                 (end (cdr range)))
-             ;; Got to take care in the backward direction to handle
-             ;; comments which are preceded by code.
-             (while (and (c-backward-single-comment)
-                         (>= (point) bopl)
-                         (looking-at "//")
-                         (= col (current-column)))
-               (setq beg (point)
-                     bopl (c-point 'bopl)))
-             (goto-char end)
-             (while (and (progn (skip-chars-forward " \t")
-                                (looking-at "//"))
-                         (= col (current-column))
-                         (prog1 (zerop (forward-line 1))
-                           (setq end (point)))))
-             (cons beg end))
-         range)
-      (error range))))
+    (condition-case nil
+       (if (and (consp range) (progn
+                                (goto-char (car range))
+                                (looking-at c-line-comment-starter)))
+           (let ((col (current-column)) 
+                 (beg (point))
+                 (bopl (c-point 'bopl))
+                 (end (cdr range)))
+             ;; Got to take care in the backward direction to handle
+             ;; comments which are preceded by code.
+             (while (and (c-backward-single-comment)
+                         (>= (point) bopl)
+                         (looking-at c-line-comment-starter)
+                         (= col (current-column)))
+               (setq beg (point)
+                     bopl (c-point 'bopl)))
+             (goto-char end)
+             (while (and (progn (skip-chars-forward " \t")
+                                (looking-at c-line-comment-starter))
+                         (= col (current-column))
+                         (prog1 (zerop (forward-line 1))
+                           (setq end (point)))))
+             (cons beg end))
+         range)
+      (error range))))
 
 (defun c-literal-type (range)
   "Convenience function that given the result of `c-literal-limits',
@@ -2980,7 +3388,9 @@ returns nil or the type of literal that the range surrounds.  It's
 much faster than using `c-in-literal' and is intended to be used when
 you need both the type of a literal and its limits.
 
-This function does not do any hidden buffer changes."
+Note that this function might do hidden buffer changes.  See the
+comment at the start of cc-engine.el for more info."
+
   (if (consp range)
       (save-excursion
        (goto-char (car range))
@@ -3032,14 +3442,14 @@ This function does not do any hidden buffer changes."
 
 (defmacro c-debug-put-decl-spot-faces (match-pos decl-pos)
   (when (facep 'c-debug-decl-spot-face)
-    `(let ((match-pos ,match-pos) (decl-pos ,decl-pos))
+    `(c-save-buffer-state ((match-pos ,match-pos) (decl-pos ,decl-pos))
        (c-debug-add-face (max match-pos (point-min)) decl-pos
                         'c-debug-decl-sws-face)
        (c-debug-add-face decl-pos (min (1+ decl-pos) (point-max))
                         'c-debug-decl-spot-face))))
 (defmacro c-debug-remove-decl-spot-faces (beg end)
   (when (facep 'c-debug-decl-spot-face)
-    `(progn
+    `(c-save-buffer-state ()
        (c-debug-remove-face ,beg ,end 'c-debug-decl-spot-face)
        (c-debug-remove-face ,beg ,end 'c-debug-decl-sws-face))))
 
@@ -3048,6 +3458,8 @@ This function does not do any hidden buffer changes."
   ;; but it contains lots of free variables that refer to things
   ;; inside `c-find-decl-spots'.  The point is left at `cfd-match-pos'
   ;; if there is a match, otherwise at `cfd-limit'.
+  ;;
+  ;; This macro might do hidden buffer changes.
 
   '(progn
      ;; Find the next property match position if we haven't got one already.
@@ -3061,21 +3473,46 @@ This function does not do any hidden buffer changes."
                                'c-decl-end)))))
         (setq cfd-prop-match (point))))
 
-     ;; Find the next `c-decl-prefix-re' match if we haven't got one already.
+     ;; Find the next `c-decl-prefix-or-start-re' match if we haven't
+     ;; got one already.
      (unless cfd-re-match
-       (while (and (setq cfd-re-match
-                        (re-search-forward c-decl-prefix-re cfd-limit 'move))
-                  (c-got-face-at (1- (setq cfd-re-match (match-end 1)))
-                                 c-literal-faces))
-        ;; Search again if the match is within a comment or a string literal.
+
+       (if (> cfd-re-match-end (point))
+          (goto-char cfd-re-match-end))
+
+       (while (if (setq cfd-re-match-end
+                       (re-search-forward c-decl-prefix-or-start-re
+                                          cfd-limit 'move))
+
+                 ;; Match.  Check if it's inside a comment or string literal.
+                 (c-got-face-at
+                  (if (setq cfd-re-match (match-end 1))
+                      ;; Matched the end of a token preceding a decl spot.
+                      (progn
+                        (goto-char cfd-re-match)
+                        (1- cfd-re-match))
+                    ;; Matched a token that start a decl spot.
+                    (goto-char (match-beginning 0))
+                    (point))
+                  c-literal-faces)
+
+               ;; No match.  Finish up and exit the loop.
+               (setq cfd-re-match cfd-limit)
+               nil)
+
+        ;; Skip out of comments and string literals.
         (while (progn
                  (goto-char (next-single-property-change
-                             cfd-re-match 'face nil cfd-limit))
+                             (point) 'face nil cfd-limit))
                  (and (< (point) cfd-limit)
-                      (c-got-face-at (point) c-literal-faces)))
-          (setq cfd-re-match (point))))
+                      (c-got-face-at (point) c-literal-faces)))))
+
+       ;; If we matched at the decl start, we have to back up over the
+       ;; preceding syntactic ws to set `cfd-match-pos' and to catch
+       ;; any decl spots in the syntactic ws.
        (unless cfd-re-match
-        (setq cfd-re-match cfd-limit)))
+        (c-backward-syntactic-ws)
+        (setq cfd-re-match (point))))
 
      ;; Choose whichever match is closer to the start.
      (if (< cfd-re-match cfd-prop-match)
@@ -3098,14 +3535,21 @@ This function does not do any hidden buffer changes."
                                (point))))))
 
 (defun c-find-decl-spots (cfd-limit cfd-decl-re cfd-face-checklist cfd-fun)
-  ;; Call CFD-FUN for each possible spot for a declaration from the
-  ;; point to CFD-LIMIT.  A spot for a declaration is the first token
-  ;; in the buffer and each token after the ones matched by
-  ;; `c-decl-prefix-re' and after the occurrences of the `c-type'
-  ;; property with the value `c-decl-end' (if `c-type-decl-end-used'
-  ;; is set).  Only a spot that match CFD-DECL-RE and whose face is in
-  ;; the CFD-FACE-CHECKLIST list causes CFD-FUN to be called.  The
-  ;; face check is disabled if CFD-FACE-CHECKLIST is nil.
+  ;; Call CFD-FUN for each possible spot for a declaration, cast or
+  ;; label from the point to CFD-LIMIT.  Such a spot is:
+  ;;
+  ;; o  The first token after bob.
+  ;; o  The first token after the end of submatch 1 in
+  ;;    `c-decl-prefix-or-start-re' when that submatch matches.
+  ;; o  The start of each `c-decl-prefix-or-start-re' match when
+  ;;    submatch 1 doesn't match.
+  ;; o  The first token after the end of each occurence of the
+  ;;    `c-type' text property with the value `c-decl-end', provided
+  ;;    `c-type-decl-end-used' is set.
+  ;;
+  ;; Only a spot that match CFD-DECL-RE and whose face is in the
+  ;; CFD-FACE-CHECKLIST list causes CFD-FUN to be called.  The face
+  ;; check is disabled if CFD-FACE-CHECKLIST is nil.
   ;;
   ;; If the match is inside a macro then the buffer is narrowed to the
   ;; end of it, so that CFD-FUN can investigate the following tokens
@@ -3115,11 +3559,21 @@ This function does not do any hidden buffer changes."
   ;;
   ;; CFD-FUN is called with point at the start of the spot.  It's
   ;; passed two arguments: The first is the end position of the token
-  ;; that `c-decl-prefix-re' matched, or 0 for the implicit match at
-  ;; bob.  The second is a flag that is t when the match is inside a
-  ;; macro.
+  ;; preceding the spot, or 0 for the implicit match at bob.  The
+  ;; second is a flag that is t when the match is inside a macro.  If
+  ;; CFD-FUN adds `c-decl-end' properties somewhere below the current
+  ;; spot, it should return non-nil to ensure that the next search
+  ;; will find them.
   ;;
-  ;; It's assumed that comment and strings are fontified in the
+  ;; The spots are visited approximately in order from top to bottom.
+  ;; It's however the positions where `c-decl-prefix-or-start-re'
+  ;; matches and where `c-decl-end' properties are found that are in
+  ;; order.  Since the spots often are at the following token, they
+  ;; might be visited out of order insofar as more spots are reported
+  ;; later on within the syntactic whitespace between the match
+  ;; positions and their spots.
+  ;;
+  ;; It's assumed that comments and strings are fontified in the
   ;; searched range.
   ;;
   ;; This is mainly used in fontification, and so has an elaborate
@@ -3128,19 +3582,28 @@ This function does not do any hidden buffer changes."
   ;;
   ;; All variables in this function begin with `cfd-' to avoid name
   ;; collision with the (dynamically bound) variables used in CFD-FUN.
+  ;;
+  ;; This function might do hidden buffer changes.
 
-  (let ((cfd-buffer-end (point-max))
-       ;; The last regexp match found by `c-find-decl-prefix-search'.
+  (let ((cfd-start-pos (point))
+       (cfd-buffer-end (point-max))
+       ;; The end of the token preceding the decl spot last found
+       ;; with `c-decl-prefix-or-start-re'.  `cfd-limit' if there's
+       ;; no match.
        cfd-re-match
-       ;; The last `c-decl-end' found by `c-find-decl-prefix-search'.
-       ;; If searching for the property isn't needed then we disable
-       ;; it by faking a first match at the limit.
+       ;; The end position of the last `c-decl-prefix-or-start-re'
+       ;; match.  If this is greater than `cfd-continue-pos', the
+       ;; next regexp search is started here instead.
+       (cfd-re-match-end (point-min))
+       ;; The end of the last `c-decl-end' found by
+       ;; `c-find-decl-prefix-search'.  `cfd-limit' if there's no
+       ;; match.  If searching for the property isn't needed then we
+       ;; disable it by setting it to `cfd-limit' directly.
        (cfd-prop-match (unless c-type-decl-end-used cfd-limit))
-       ;; The position of the last match found by
-       ;; `c-find-decl-prefix-search'.  For regexp matches it's the
-       ;; end of the matched token, for property matches it's the end
-       ;; of the property.  0 for the implicit match at bob.
-       ;; `cfd-limit' if there's no match.
+       ;; The end of the token preceding the decl spot last found by
+       ;; `c-find-decl-prefix-search'.  0 for the implicit match at
+       ;; bob.  `cfd-limit' if there's no match.  In other words,
+       ;; this is the minimum of `cfd-re-match' and `cfd-prop-match'.
        (cfd-match-pos cfd-limit)
        ;; The position to continue searching at.
        cfd-continue-pos
@@ -3153,127 +3616,219 @@ This function does not do any hidden buffer changes."
        (cfd-macro-end 0))
 
     ;; Initialize by finding a syntactically relevant start position
-    ;; before the point, and do the first `c-decl-prefix-re' search
-    ;; unless we're at bob.
+    ;; before the point, and do the first `c-decl-prefix-or-start-re'
+    ;; search unless we're at bob.
 
-    (let ((start-pos (point)) syntactic-pos)
+    (let (start-in-literal start-in-macro syntactic-pos)
       ;; Must back up a bit since we look for the end of the previous
       ;; statement or declaration, which is earlier than the first
       ;; returned match.
 
-      (when (c-got-face-at (point) c-literal-faces)
-       ;; But first we need to move to a syntactically relevant
-       ;; position.  Use the faces to back up to the start of the
-       ;; comment or string literal.
-       (when (and (not (bobp))
-                  (c-got-face-at (1- (point)) c-literal-faces))
-         (while (progn
-                  (goto-char (previous-single-property-change
-                              (point) 'face nil (point-min)))
-                  (and (> (point) (point-min))
-                       (c-got-face-at (point) c-literal-faces)))))
-
-       ;; XEmacs doesn't fontify the quotes surrounding string
-       ;; literals.
-       (and (featurep 'xemacs)
-            (eq (get-text-property (point) 'face)
-                'font-lock-string-face)
-            (not (bobp))
-            (progn (backward-char)
-                   (not (looking-at c-string-limit-regexp)))
-            (forward-char))
-
-       ;; The font lock package might not have fontified the start of
-       ;; the literal at all so check that we have arrived at
-       ;; something that looks like a start or else resort to
-       ;; `c-literal-limits'.
-       (unless (looking-at c-literal-start-regexp)
-         (let ((range (c-literal-limits)))
-           (if range (goto-char (car range))))))
-
-      ;; Must back out of any macro so that we don't miss any
-      ;; declaration that could follow after it, unless the limit is
-      ;; inside the macro.  We only check that for the current line to
-      ;; save some time; it's enough for the by far most common case
-      ;; when font-lock refontifies the current line only.
-      (when (save-excursion
-             (and (= (forward-line 1) 0)
-                  (bolp)               ; forward-line has funny behavior at eob.
-                  (or (< (c-point 'eol) cfd-limit)
-                      (progn (backward-char)
-                             (not (eq (char-before) ?\\))))))
-       (c-beginning-of-macro))
-
-      ;; Clear the cache if it applied further down.
-      (c-invalidate-find-decl-cache start-pos)
-
-      (setq syntactic-pos (point))
-      (c-backward-syntactic-ws c-find-decl-syntactic-pos)
-
-      ;; If we hit `c-find-decl-syntactic-pos' and
-      ;; `c-find-decl-match-pos' is set then we install the cached
-      ;; values.  If we hit `c-find-decl-syntactic-pos' and
-      ;; `c-find-decl-match-pos' is nil then we know there's no decl
-      ;; prefix in the whitespace before `c-find-decl-syntactic-pos'
-      ;; and so we can continue the search from this point.  If we
-      ;; didn't hit `c-find-decl-syntactic-pos' then we're now in the
-      ;; right spot to begin searching anyway.
-      (if (and (eq (point) c-find-decl-syntactic-pos)
-              c-find-decl-match-pos)
+      (cond
+       ;; First we need to move to a syntactically relevant position.
+       ;; Begin by backing out of comment or string literals.
+       ((and
+        (when (c-got-face-at (point) c-literal-faces)
+          ;; Try to use the faces to back up to the start of the
+          ;; literal.  FIXME: What if the point is on a declaration
+          ;; inside a comment?
+          (while (and (not (bobp))
+                      (c-got-face-at (1- (point)) c-literal-faces))
+            (goto-char (previous-single-property-change
+                        (point) 'face nil (point-min))))
+
+          ;; XEmacs doesn't fontify the quotes surrounding string
+          ;; literals.
+          (and (featurep 'xemacs)
+               (eq (get-text-property (point) 'face)
+                   'font-lock-string-face)
+               (not (bobp))
+               (progn (backward-char)
+                      (not (looking-at c-string-limit-regexp)))
+               (forward-char))
+
+          ;; Don't trust the literal to contain only literal faces
+          ;; (the font lock package might not have fontified the
+          ;; start of it at all, for instance) so check that we have
+          ;; arrived at something that looks like a start or else
+          ;; resort to `c-literal-limits'.
+          (unless (looking-at c-literal-start-regexp)
+            (let ((range (c-literal-limits)))
+              (if range (goto-char (car range)))))
+
+          (setq start-in-literal (point)))
+
+        ;; The start is in a literal.  If the limit is in the same
+        ;; one we don't have to find a syntactic position etc.  We
+        ;; only check that if the limit is at or before bonl to save
+        ;; time; it covers the by far most common case when font-lock
+        ;; refontifies the current line only.
+        (<= cfd-limit (c-point 'bonl cfd-start-pos))
+        (save-excursion
+          (goto-char cfd-start-pos)
+          (while (progn
+                   (goto-char (next-single-property-change
+                               (point) 'face nil cfd-limit))
+                   (and (< (point) cfd-limit)
+                        (c-got-face-at (point) c-literal-faces))))
+          (= (point) cfd-limit)))
+
+       ;; Completely inside a literal.  Set up variables to trig the
+       ;; (< cfd-continue-pos cfd-start-pos) case below and it'll
+       ;; find a suitable start position.
+       (setq cfd-continue-pos start-in-literal))
+
+       ;; Check if the region might be completely inside a macro, to
+       ;; optimize that like the completely-inside-literal above.
+       ((save-excursion
+         (and (= (forward-line 1) 0)
+              (bolp)                   ; forward-line has funny behavior at eob.
+              (>= (point) cfd-limit)
+              (progn (backward-char)
+                     (eq (char-before) ?\\))))
+       ;; (Maybe) completely inside a macro.  Only need to trig the
+       ;; (< cfd-continue-pos cfd-start-pos) case below to make it
+       ;; set things up.
+       (setq cfd-continue-pos (1- cfd-start-pos)
+             start-in-macro t))
 
-         (progn
-           ;; The match is always outside macros and comments so we
-           ;; start at the next token.  The loop below will later go
-           ;; back using `cfd-continue-pos' to fix declarations inside
-           ;; the syntactic ws.
-           (goto-char syntactic-pos)
-           (c-forward-syntactic-ws)
+       (t
+       ;; Back out of any macro so we don't miss any declaration
+       ;; that could follow after it.
+       (when (c-beginning-of-macro)
+         (setq start-in-macro t))
+
+       ;; Now we're at a proper syntactically relevant position so we
+       ;; can use the cache.  But first clear it if it applied
+       ;; further down.
+       (c-invalidate-find-decl-cache cfd-start-pos)
+
+       (setq syntactic-pos (point))
+       (unless (eq syntactic-pos c-find-decl-syntactic-pos)
+         ;; Don't have to do this if the cache is relevant here,
+         ;; typically if the same line is refontified again.  If
+         ;; we're just some syntactic whitespace further down we can
+         ;; still use the cache to limit the skipping.
+         (c-backward-syntactic-ws c-find-decl-syntactic-pos))
+
+       ;; If we hit `c-find-decl-syntactic-pos' and
+       ;; `c-find-decl-match-pos' is set then we install the cached
+       ;; values.  If we hit `c-find-decl-syntactic-pos' and
+       ;; `c-find-decl-match-pos' is nil then we know there's no decl
+       ;; prefix in the whitespace before `c-find-decl-syntactic-pos'
+       ;; and so we can continue the search from this point.  If we
+       ;; didn't hit `c-find-decl-syntactic-pos' then we're now in
+       ;; the right spot to begin searching anyway.
+       (if (and (eq (point) c-find-decl-syntactic-pos)
+                c-find-decl-match-pos)
            (setq cfd-match-pos c-find-decl-match-pos
                  cfd-continue-pos syntactic-pos)
-           (if (< cfd-continue-pos (point))
-               (setq cfd-token-pos (point))))
-
-       (setq c-find-decl-syntactic-pos syntactic-pos)
-
-       (when (if (bobp)
-                 ;; Always consider bob a match to get the first declaration
-                 ;; in the file.  Do this separately instead of letting
-                 ;; `c-decl-prefix-re' match bob, so that it always can
-                 ;; consume at least one character to ensure that we won't
-                 ;; get stuck in an infinite loop.
-                 (setq cfd-re-match 0)
-               (backward-char)
-               (c-beginning-of-current-token)
-               (< (point) cfd-limit))
-         ;; Do an initial search now.  In the bob case above it's only done
-         ;; to search for the `c-type' property.
-         (c-find-decl-prefix-search))
-
-       ;; Advance `cfd-continue-pos' if we got a hit before the start
-       ;; position.  The earliest position that could affect after
-       ;; the start position is the char before the preceding
-       ;; comments.
-       (when (and cfd-continue-pos (< cfd-continue-pos start-pos))
-         (goto-char syntactic-pos)
+
+         (setq c-find-decl-syntactic-pos syntactic-pos)
+
+         (when (if (bobp)
+                   ;; Always consider bob a match to get the first
+                   ;; declaration in the file.  Do this separately instead of
+                   ;; letting `c-decl-prefix-or-start-re' match bob, so that
+                   ;; regexp always can consume at least one character to
+                   ;; ensure that we won't get stuck in an infinite loop.
+                   (setq cfd-re-match 0)
+                 (backward-char)
+                 (c-beginning-of-current-token)
+                 (< (point) cfd-limit))
+           ;; Do an initial search now.  In the bob case above it's
+           ;; only done to search for a `c-decl-end' spot.
+           (c-find-decl-prefix-search))
+
+         (setq c-find-decl-match-pos (and (< cfd-match-pos cfd-start-pos)
+                                          cfd-match-pos)))))
+
+      ;; Advance `cfd-continue-pos' if it's before the start position.
+      ;; The closest continue position that might have effect at or
+      ;; after the start depends on what we started in.  This also
+      ;; finds a suitable start position in the special cases when the
+      ;; region is completely within a literal or macro.
+      (when (and cfd-continue-pos (< cfd-continue-pos cfd-start-pos))
+
+       (cond
+        (start-in-macro
+         ;; If we're in a macro then it's the closest preceding token
+         ;; in the macro.  Check this before `start-in-literal',
+         ;; since if we're inside a literal in a macro, the preceding
+         ;; token is earlier than any `c-decl-end' spot inside the
+         ;; literal (comment).
+         (goto-char (or start-in-literal cfd-start-pos))
+         ;; The only syntactic ws in macros are comments.
          (c-backward-comments)
-         (unless (bobp)
-           (backward-char)
-           (c-beginning-of-current-token))
-         (setq cfd-continue-pos (max cfd-continue-pos (point))))
-
-       ;; If we got a match it's always outside macros and comments so
-       ;; advance to the next token and set `cfd-token-pos'.  The loop
-       ;; below will later go back using `cfd-continue-pos' to fix
-       ;; declarations inside the syntactic ws.
-       (when (and (< cfd-match-pos cfd-limit) (< (point) syntactic-pos))
-         (goto-char syntactic-pos)
-         (c-forward-syntactic-ws)
-         (and cfd-continue-pos
-              (< cfd-continue-pos (point))
-              (setq cfd-token-pos (point))))
+         (backward-char)
+         (c-beginning-of-current-token))
+
+        (start-in-literal
+         ;; If we're in a comment it can only be the closest
+         ;; preceding `c-decl-end' position within that comment, if
+         ;; any.  Go back to the beginning of such a property so that
+         ;; `c-find-decl-prefix-search' will find the end of it.
+         ;; (Can't stop at the end and install it directly on
+         ;; `cfd-prop-match' since that variable might be cleared
+         ;; after `cfd-fun' below.)
+         ;;
+         ;; Note that if the literal is a string then the property
+         ;; search will simply skip to the beginning of it right
+         ;; away.
+         (if (not c-type-decl-end-used)
+             (goto-char start-in-literal)
+           (goto-char cfd-start-pos)
+           (while (progn
+                    (goto-char (previous-single-property-change
+                                (point) 'c-type nil start-in-literal))
+                    (and (> (point) start-in-literal)
+                         (not (eq (c-get-char-property (point) 'c-type)
+                                  'c-decl-end))))))
+
+         (when (= (point) start-in-literal)
+           ;; Didn't find any property inside the comment, so we can
+           ;; skip it entirely.  (This won't skip past a string, but
+           ;; that'll be handled quickly by the next
+           ;; `c-find-decl-prefix-search' anyway.)
+           (c-forward-single-comment)
+           (if (> (point) cfd-limit)
+               (goto-char cfd-limit))))
 
-       (setq c-find-decl-match-pos (and (< cfd-match-pos start-pos)
-                                        cfd-match-pos))))
+        (t
+         ;; If we started in normal code, the only match that might
+         ;; apply before the start is what we already got in
+         ;; `cfd-match-pos' so we can continue at the start position.
+         ;; (Note that we don't get here if the first match is below
+         ;; it.)
+         (goto-char cfd-start-pos)))
+
+       ;; Delete found matches if they are before our new continue
+       ;; position, so that `c-find-decl-prefix-search' won't back up
+       ;; to them later on.
+       (setq cfd-continue-pos (point))
+       (when (and cfd-re-match (< cfd-re-match cfd-continue-pos))
+         (setq cfd-re-match nil))
+       (when (and cfd-prop-match (< cfd-prop-match cfd-continue-pos))
+         (setq cfd-prop-match nil)))
+
+      (if syntactic-pos
+         ;; This is the normal case and we got a proper syntactic
+         ;; position.  If there's a match then it's always outside
+         ;; macros and comments, so advance to the next token and set
+         ;; `cfd-token-pos'.  The loop below will later go back using
+         ;; `cfd-continue-pos' to fix declarations inside the
+         ;; syntactic ws.
+         (when (and cfd-match-pos (< cfd-match-pos syntactic-pos))
+           (goto-char syntactic-pos)
+           (c-forward-syntactic-ws)
+           (and cfd-continue-pos
+                (< cfd-continue-pos (point))
+                (setq cfd-token-pos (point))))
+
+       ;; Have one of the special cases when the region is completely
+       ;; within a literal or macro.  `cfd-continue-pos' is set to a
+       ;; good start position for the search, so do it.
+       (c-find-decl-prefix-search)))
 
     ;; Now loop.  We already got the first match.
 
@@ -3323,33 +3878,37 @@ This function does not do any hidden buffer changes."
 
             (< (point) cfd-limit))
 
-      (when (progn
-             ;; Narrow to the end of the macro if we got a hit inside
-             ;; one, to avoid recognizing things that start inside
-             ;; the macro and end outside it.
-             (when (> cfd-match-pos cfd-macro-end)
-               ;; Not in the same macro as in the previous round.
-               (save-excursion
-                 (goto-char cfd-match-pos)
-                 (setq cfd-macro-end
-                       (if (save-excursion (and (c-beginning-of-macro)
-                                                (< (point) cfd-match-pos)))
-                           (progn (c-end-of-macro)
-                                  (point))
-                         0))))
+      (when (and
+            (>= (point) cfd-start-pos)
 
-             (if (zerop cfd-macro-end)
-                 t
-               (if (> cfd-macro-end (point))
-                   (progn (narrow-to-region (point-min) cfd-macro-end)
-                          t)
-                 ;; The matched token was the last thing in the
-                 ;; macro, so the whole match is bogus.
-                 (setq cfd-macro-end 0)
-                 nil)))
+            (progn
+              ;; Narrow to the end of the macro if we got a hit inside
+              ;; one, to avoid recognizing things that start inside the
+              ;; macro and end outside it.
+              (when (> cfd-match-pos cfd-macro-end)
+                ;; Not in the same macro as in the previous round.
+                (save-excursion
+                  (goto-char cfd-match-pos)
+                  (setq cfd-macro-end
+                        (if (save-excursion (and (c-beginning-of-macro)
+                                                 (< (point) cfd-match-pos)))
+                            (progn (c-end-of-macro)
+                                   (point))
+                          0))))
+
+              (if (zerop cfd-macro-end)
+                  t
+                (if (> cfd-macro-end (point))
+                    (progn (narrow-to-region (point-min) cfd-macro-end)
+                           t)
+                  ;; The matched token was the last thing in the macro,
+                  ;; so the whole match is bogus.
+                  (setq cfd-macro-end 0)
+                  nil))))
 
        (c-debug-put-decl-spot-faces cfd-match-pos (point))
-       (funcall cfd-fun cfd-match-pos (/= cfd-macro-end 0))
+       (if (funcall cfd-fun cfd-match-pos (/= cfd-macro-end 0))
+           (setq cfd-prop-match nil))
 
        (when (/= cfd-macro-end 0)
          ;; Restore limits if we did macro narrowment above.
@@ -3370,14 +3929,23 @@ This function does not do any hidden buffer changes."
 ;; bother with the scoping rules of the languages, but in practice the
 ;; same name is seldom used as both a type and something else in a
 ;; file, and we only use this as a last resort in ambiguous cases (see
-;; `c-font-lock-declarations').
+;; `c-forward-decl-or-cast-1').
+;;
+;; Template types in C++ are added here too but with the template
+;; arglist replaced with "<>" in references or "<" for the one in the
+;; primary type.  E.g. the type "Foo<A,B>::Bar<C>" is stored as
+;; "Foo<>::Bar<".  This avoids storing very long strings (since C++
+;; template specs can be fairly sized programs in themselves) and
+;; improves the hit ratio (it's a type regardless of the template
+;; args; it's just not the same type, but we're only interested in
+;; recognizing types, not telling distinct types apart).  Note that
+;; template types in references are added here too; from the example
+;; above there will also be an entry "Foo<".
 (defvar c-found-types nil)
 (make-variable-buffer-local 'c-found-types)
 
 (defsubst c-clear-found-types ()
   ;; Clears `c-found-types'.
-  ;;
-  ;; This function does not do any hidden buffer changes.
   (setq c-found-types (make-vector 53 0)))
 
 (defun c-add-type (from to)
@@ -3389,23 +3957,20 @@ This function does not do any hidden buffer changes."
   ;; doesn't cover cases like when characters are removed from a type
   ;; or added in the middle.  We'd need the position of point when the
   ;; font locking is invoked to solve this well.
-  (unless (and c-recognize-<>-arglists
-              (save-excursion
-                (goto-char from)
-                (c-syntactic-re-search-forward "<" to t)))
-    ;; To avoid storing very long strings, do not add a type that
-    ;; contains '<' in languages with angle bracket arglists, since
-    ;; the type then probably contains a C++ template spec and those
-    ;; can be fairly sized programs in themselves.
-    (let ((type (c-syntactic-content from to)))
-      (unless (intern-soft type c-found-types)
-       (unintern (substring type 0 -1) c-found-types)
-       (intern type c-found-types)))))
+  ;;
+  ;; This function might do hidden buffer changes.
+  (let ((type (c-syntactic-content from to c-recognize-<>-arglists)))
+    (unless (intern-soft type c-found-types)
+      (unintern (substring type 0 -1) c-found-types)
+      (intern type c-found-types))))
 
 (defsubst c-check-type (from to)
   ;; Return non-nil if the given region contains a type in
   ;; `c-found-types'.
-  (intern-soft (c-syntactic-content from to) c-found-types))
+  ;;
+  ;; This function might do hidden buffer changes.
+  (intern-soft (c-syntactic-content from to c-recognize-<>-arglists)
+              c-found-types))
 
 (defun c-list-found-types ()
   ;; Return all the types in `c-found-types' as a sorted list of
@@ -3420,17 +3985,43 @@ This function does not do any hidden buffer changes."
 \f
 ;; Handling of small scale constructs like types and names.
 
-(defun c-remove-<>-arglist-properties (from to)
-  ;; Remove all the properties put by `c-forward-<>-arglist' in the
-  ;; specified region.  Point is clobbered.
-  (goto-char from)
-  (while (progn (skip-chars-forward "^<>," to)
-               (< (point) to))
-    (if (eq (char-after) ?,)
-       (when (eq (c-get-char-property (point) 'c-type) 'c-<>-arg-sep)
-         (c-clear-char-property (point) 'c-type))
-      (c-clear-char-property (point) 'syntax-table))
-    (forward-char)))
+(defun c-after-change-check-<>-operators (beg end)
+  ;; This is called from `after-change-functions' when
+  ;; c-recognize-<>-arglists' is set.  It ensures that no "<" or ">"
+  ;; chars with paren syntax become part of another operator like "<<"
+  ;; or ">=".
+  ;;
+  ;; This function might do hidden buffer changes.
+
+  (save-excursion
+    (goto-char beg)
+    (when (or (looking-at "[<>]")
+             (< (skip-chars-backward "<>") 0))
+
+      (goto-char beg)
+      (c-beginning-of-current-token)
+      (when (and (< (point) beg)
+                (looking-at c-<>-multichar-token-regexp)
+                (< beg (setq beg (match-end 0))))
+       (while (progn (skip-chars-forward "^<>" beg)
+                     (< (point) beg))
+         (c-clear-char-property (point) 'syntax-table)
+         (forward-char))))
+
+    (when (< beg end)
+      (goto-char end)
+      (when (or (looking-at "[<>]")
+               (< (skip-chars-backward "<>") 0))
+
+       (goto-char end)
+       (c-beginning-of-current-token)
+       (when (and (< (point) end)
+                  (looking-at c-<>-multichar-token-regexp)
+                  (< end (setq end (match-end 0))))
+         (while (progn (skip-chars-forward "^<>" end)
+                       (< (point) end))
+           (c-clear-char-property (point) 'syntax-table)
+           (forward-char)))))))
 
 ;; Dynamically bound variable that instructs `c-forward-type' to also
 ;; treat possible types (i.e. those that it normally returns 'maybe or
@@ -3439,6 +4030,20 @@ This function does not do any hidden buffer changes."
 ;; that is set, and that it adds them to `c-found-types'.
 (defvar c-promote-possible-types nil)
 
+;; Dynamically bound variable that instructs `c-forward-<>-arglist' to
+;; mark up successfully parsed arglists with paren syntax properties on
+;; the surrounding angle brackets and with `c-<>-arg-sep' in the
+;; `c-type' property of each argument separating comma.
+;;
+;; Setting this variable also makes `c-forward-<>-arglist' recurse into
+;; all arglists for side effects (i.e. recording types), otherwise it
+;; exploits any existing paren syntax properties to quickly jump to the
+;; end of already parsed arglists.
+;;
+;; Marking up the arglists is not the default since doing that correctly
+;; depends on a proper value for `c-restricted-<>-arglists'.
+(defvar c-parse-and-markup-<>-arglists nil)
+
 ;; Dynamically bound variable that instructs `c-forward-<>-arglist' to
 ;; not accept arglists that contain binary operators.
 ;;
@@ -3455,31 +4060,36 @@ This function does not do any hidden buffer changes."
 ;; "if (a < b || c > d)", it's probably not a template.
 (defvar c-restricted-<>-arglists nil)
 
-;; Dynamically bound variables that instructs `c-forward-name',
-;; `c-forward-type' and `c-forward-<>-arglist' to record the ranges of
-;; all the type and reference identifiers they encounter.  They will
-;; build lists on these variables where each element is a cons of the
-;; buffer positions surrounding each identifier.  This recording is
-;; only activated when `c-record-type-identifiers' is non-nil.
+;; Dynamically bound variables that instructs
+;; `c-forward-keyword-clause', `c-forward-<>-arglist',
+;; `c-forward-name', `c-forward-type', `c-forward-decl-or-cast-1', and
+;; `c-forward-label' to record the ranges of all the type and
+;; reference identifiers they encounter.  They will build lists on
+;; these variables where each element is a cons of the buffer
+;; positions surrounding each identifier.  This recording is only
+;; activated when `c-record-type-identifiers' is non-nil.
 ;;
 ;; All known types that can't be identifiers are recorded, and also
 ;; other possible types if `c-promote-possible-types' is set.
 ;; Recording is however disabled inside angle bracket arglists that
 ;; are encountered inside names and other angle bracket arglists.
-;; Such occurences are taken care of by `c-font-lock-<>-arglists'
+;; Such occurrences are taken care of by `c-font-lock-<>-arglists'
 ;; instead.
 ;;
 ;; Only the names in C++ template style references (e.g. "tmpl" in
 ;; "tmpl<a,b>::foo") are recorded as references, other references
 ;; aren't handled here.
+;;
+;; `c-forward-label' records the label identifier(s) on
+;; `c-record-ref-identifiers'.
 (defvar c-record-type-identifiers nil)
 (defvar c-record-ref-identifiers nil)
 
-;; If `c-record-type-identifiers' is set, this will receive a cons
-;; cell of the range of the last single identifier symbol stepped over
-;; by `c-forward-name' if it's successful.  This is the range that
-;; should be put on one of the record lists by the caller.  It's
-;; assigned nil if there's no such symbol in the name.
+;; This variable will receive a cons cell of the range of the last
+;; single identifier symbol stepped over by `c-forward-name' if it's
+;; successful.  This is the range that should be put on one of the
+;; record lists above by the caller.  It's assigned nil if there's no
+;; such symbol in the name.
 (defvar c-last-identifier-range nil)
 
 (defmacro c-record-type-id (range)
@@ -3516,45 +4126,70 @@ This function does not do any hidden buffer changes."
   ;; over.  The point is clobbered if nil is returned.  If range
   ;; recording is enabled, the identifier is recorded on as a type
   ;; if TYPE is 'type or as a reference if TYPE is 'ref.
+  ;;
+  ;; This macro might do hidden buffer changes.
   `(let (res)
      (while (if (setq res ,(if (eq type 'type)
                               `(c-forward-type)
                             `(c-forward-name)))
                nil
              (and (looking-at c-keywords-regexp)
-                  (c-forward-keyword-clause))))
+                  (c-forward-keyword-clause 1))))
      (when (memq res '(t known found prefix))
        ,(when (eq type 'ref)
          `(when c-record-type-identifiers
             (c-record-ref-id c-last-identifier-range)))
        t)))
 
-(defmacro c-forward-id-comma-list (type)
+(defmacro c-forward-id-comma-list (type update-safe-pos)
   ;; Used internally in `c-forward-keyword-clause' to move forward
   ;; over a comma separated list of types or names using
   ;; `c-forward-keyword-prefixed-id'.
+  ;;
+  ;; This macro might do hidden buffer changes.
   `(while (and (progn
-                (setq safe-pos (point))
+                ,(when update-safe-pos
+                   `(setq safe-pos (point)))
                 (eq (char-after) ?,))
               (progn
                 (forward-char)
                 (c-forward-syntactic-ws)
                 (c-forward-keyword-prefixed-id ,type)))))
 
-(defun c-forward-keyword-clause ()
-  ;; The first submatch in the current match data is assumed to
-  ;; surround a token.  If it's a keyword, move over it and any
-  ;; following clauses associated with it, stopping at the next
-  ;; following token.  t is returned in that case, otherwise the point
+(defun c-forward-keyword-clause (match)
+  ;; Submatch MATCH in the current match data is assumed to surround a
+  ;; token.  If it's a keyword, move over it and any immediately
+  ;; following clauses associated with it, stopping at the start of
+  ;; the next token.  t is returned in that case, otherwise the point
   ;; stays and nil is returned.  The kind of clauses that are
   ;; recognized are those specified by `c-type-list-kwds',
   ;; `c-ref-list-kwds', `c-colon-type-list-kwds',
   ;; `c-paren-nontype-kwds', `c-paren-type-kwds', `c-<>-type-kwds',
   ;; and `c-<>-arglist-kwds'.
+  ;;
+  ;; This function records identifier ranges on
+  ;; `c-record-type-identifiers' and `c-record-ref-identifiers' if
+  ;; `c-record-type-identifiers' is non-nil.
+  ;;
+  ;; Note that for `c-colon-type-list-kwds', which doesn't necessary
+  ;; apply directly after the keyword, the type list is moved over
+  ;; only when there is no unaccounted token before it (i.e. a token
+  ;; that isn't moved over due to some other keyword list).  The
+  ;; identifier ranges in the list are still recorded if that should
+  ;; be done, though.
+  ;;
+  ;; This function might do hidden buffer changes.
+
+  (let ((kwd-sym (c-keyword-sym (match-string match))) safe-pos pos
+       ;; The call to `c-forward-<>-arglist' below is made after
+       ;; `c-<>-sexp-kwds' keywords, so we're certain they actually
+       ;; are angle bracket arglists and `c-restricted-<>-arglists'
+       ;; should therefore be nil.
+       (c-parse-and-markup-<>-arglists t)
+       c-restricted-<>-arglists)
 
-  (let ((kwd-sym (c-keyword-sym (match-string 1))) safe-pos pos)
     (when kwd-sym
-      (goto-char (match-end 1))
+      (goto-char (match-end match))
       (c-forward-syntactic-ws)
       (setq safe-pos (point))
 
@@ -3562,12 +4197,12 @@ This function does not do any hidden buffer changes."
        ((and (c-keyword-member kwd-sym 'c-type-list-kwds)
             (c-forward-keyword-prefixed-id type))
        ;; There's a type directly after a keyword in `c-type-list-kwds'.
-       (c-forward-id-comma-list type))
+       (c-forward-id-comma-list type t))
 
        ((and (c-keyword-member kwd-sym 'c-ref-list-kwds)
             (c-forward-keyword-prefixed-id ref))
        ;; There's a name directly after a keyword in `c-ref-list-kwds'.
-       (c-forward-id-comma-list ref))
+       (c-forward-id-comma-list ref t))
 
        ((and (c-keyword-member kwd-sym 'c-paren-any-kwds)
             (eq (char-after) ?\())
@@ -3592,9 +4227,7 @@ This function does not do any hidden buffer changes."
 
        ((and (c-keyword-member kwd-sym 'c-<>-sexp-kwds)
             (eq (char-after) ?<)
-            (c-forward-<>-arglist (c-keyword-member kwd-sym 'c-<>-type-kwds)
-                                  (or c-record-type-identifiers
-                                      c-restricted-<>-arglists)))
+            (c-forward-<>-arglist (c-keyword-member kwd-sym 'c-<>-type-kwds)))
        (c-forward-syntactic-ws)
        (setq safe-pos (point)))
 
@@ -3604,46 +4237,56 @@ This function does not do any hidden buffer changes."
        (c-forward-syntactic-ws)
        (setq safe-pos (point))))
 
-      (when (and (c-keyword-member kwd-sym 'c-colon-type-list-kwds)
-                (progn
-                  ;; If a keyword matched both one of the types above and
-                  ;; this one, we match `c-colon-type-list-re' after the
-                  ;; clause matched above.
-                  (goto-char safe-pos)
-                  (looking-at c-colon-type-list-re))
-                (progn
-                  (goto-char (match-end 0))
-                  (c-forward-syntactic-ws)
-                  (c-forward-keyword-prefixed-id type)))
-       ;; There's a type after the `c-colon-type-list-re'
-       ;; match after a keyword in `c-colon-type-list-kwds'.
-       (c-forward-id-comma-list type))
+      (when (c-keyword-member kwd-sym 'c-colon-type-list-kwds)
+       (if (eq (char-after) ?:)
+           ;; If we are at the colon already, we move over the type
+           ;; list after it.
+           (progn
+             (forward-char)
+             (c-forward-syntactic-ws)
+             (when (c-forward-keyword-prefixed-id type)
+               (c-forward-id-comma-list type t)))
+         ;; Not at the colon, so stop here.  But the identifier
+         ;; ranges in the type list later on should still be
+         ;; recorded.
+         (and c-record-type-identifiers
+              (progn
+                ;; If a keyword matched both one of the types above and
+                ;; this one, we match `c-colon-type-list-re' after the
+                ;; clause matched above.
+                (goto-char safe-pos)
+                (looking-at c-colon-type-list-re))
+              (progn
+                (goto-char (match-end 0))
+                (c-forward-syntactic-ws)
+                (c-forward-keyword-prefixed-id type))
+              ;; There's a type after the `c-colon-type-list-re' match
+              ;; after a keyword in `c-colon-type-list-kwds'.
+              (c-forward-id-comma-list type nil))))
 
       (goto-char safe-pos)
       t)))
 
-(defun c-forward-<>-arglist (all-types reparse)
-  ;; The point is assumed to be at a '<'.  Try to treat it as the open
+(defun c-forward-<>-arglist (all-types)
+  ;; The point is assumed to be at a "<".  Try to treat it as the open
   ;; paren of an angle bracket arglist and move forward to the the
-  ;; corresponding '>'.  If successful, the point is left after the
-  ;; '>' and t is returned, otherwise the point isn't moved and nil is
+  ;; corresponding ">".  If successful, the point is left after the
+  ;; ">" and t is returned, otherwise the point isn't moved and nil is
   ;; returned.  If ALL-TYPES is t then all encountered arguments in
   ;; the arglist that might be types are treated as found types.
   ;;
-  ;; The surrounding '<' and '>' are given syntax-table properties to
-  ;; make them behave like parentheses.  Each argument separating ','
-  ;; is also set to `c-<>-arg-sep' in the `c-type' property.  These
-  ;; properties are also cleared in a relevant region forward from the
-  ;; point if they seems to be set and it turns out to not be an
-  ;; arglist.
+  ;; The variable `c-parse-and-markup-<>-arglists' controls how this
+  ;; function handles text properties on the angle brackets and argument
+  ;; separating commas.
   ;;
-  ;; If the arglist has been successfully parsed before then paren
-  ;; syntax properties will be exploited to quickly jump to the end,
-  ;; but that can be disabled by setting REPARSE to t.  That is
-  ;; necessary if the various side effects, e.g. recording of type
-  ;; ranges, are important.  Setting REPARSE to t only applies
-  ;; recursively to nested angle bracket arglists if
-  ;; `c-restricted-<>-arglists' is set.
+  ;; `c-restricted-<>-arglists' controls how lenient the template
+  ;; arglist recognition should be.
+  ;;
+  ;; This function records identifier ranges on
+  ;; `c-record-type-identifiers' and `c-record-ref-identifiers' if
+  ;; `c-record-type-identifiers' is non-nil.
+  ;;
+  ;; This function might do hidden buffer changes.
 
   (let ((start (point))
        ;; If `c-record-type-identifiers' is set then activate
@@ -3652,7 +4295,7 @@ This function does not do any hidden buffer changes."
        (c-record-found-types (if c-record-type-identifiers t)))
     (if (catch 'angle-bracket-arglist-escape
          (setq c-record-found-types
-               (c-forward-<>-arglist-recur all-types reparse)))
+               (c-forward-<>-arglist-recur all-types)))
        (progn
          (when (consp c-record-found-types)
            (setq c-record-type-identifiers
@@ -3664,8 +4307,10 @@ This function does not do any hidden buffer changes."
       (goto-char start)
       nil)))
 
-(defun c-forward-<>-arglist-recur (all-types reparse)
+(defun c-forward-<>-arglist-recur (all-types)
   ;; Recursive part of `c-forward-<>-arglist'.
+  ;;
+  ;; This function might do hidden buffer changes.
 
   (let ((start (point)) res pos tmp
        ;; Cover this so that any recorded found type ranges are
@@ -3677,61 +4322,24 @@ This function does not do any hidden buffer changes."
        ;; separating ',' in the arglist.
        arg-start-pos)
 
-    ;; If the '<' has paren open syntax then we've marked it as an
-    ;; angle bracket arglist before, so try to skip to the end and see
-    ;; that the close paren matches.
-    (if (and (c-get-char-property (point) 'syntax-table)
-            (progn
-              (forward-char)
-              (if (and (not (looking-at c-<-op-cont-regexp))
-                       (if (c-parse-sexp-lookup-properties)
-                           (c-go-up-list-forward)
-                         (catch 'at-end
-                           (let ((depth 1))
-                             (while (c-syntactic-re-search-forward
-                                     "[<>]" nil t t)
-                               (when (c-get-char-property (1- (point))
-                                                          'syntax-table)
-                                 (if (eq (char-before) ?<)
-                                     (setq depth (1+ depth))
-                                   (setq depth (1- depth))
-                                   (when (= depth 0) (throw 'at-end t)))))
-                             nil)))
-                       (not (looking-at c->-op-cont-regexp))
-                       (save-excursion
-                         (backward-char)
-                         (= (point)
-                            (progn (c-beginning-of-current-token)
-                                   (point)))))
-
-                  ;; Got an arglist that appears to be valid.
-                  (if reparse
-                      ;; Reparsing is requested, so zap the properties in the
-                      ;; region and go on to redo it.  It's done here to
-                      ;; avoid leaving it behind if we exit through
-                      ;; `angle-bracket-arglist-escape' below.
-                      (progn
-                        (c-remove-<>-arglist-properties start (point))
-                        (goto-char start)
-                        nil)
-                    t)
-
-                ;; Got unmatched paren brackets or either paren was
-                ;; actually some other token.  Recover by clearing the
-                ;; syntax properties on all the '<' and '>' in the
-                ;; range where we'll search for the arglist below.
-                (goto-char start)
-                (while (progn (skip-chars-forward "^<>,;{}")
-                              (looking-at "[<>,]"))
-                  (if (eq (char-after) ?,)
-                      (when (eq (c-get-char-property (point) 'c-type)
-                                'c-<>-arg-sep)
-                        (c-clear-char-property (point) 'c-type))
-                    (c-clear-char-property (point) 'syntax-table))
-                  (forward-char))
-                (goto-char start)
-                nil)))
-       t
+    ;; If the '<' has paren open syntax then we've marked it as an angle
+    ;; bracket arglist before, so skip to the end.
+    (if (and (not c-parse-and-markup-<>-arglists)
+            (c-get-char-property (point) 'syntax-table))
+
+       (progn
+         (forward-char)
+         (if (and (c-go-up-list-forward)
+                  (eq (char-before) ?>))
+             t
+
+           ;; Got unmatched paren angle brackets.  We don't clear the paren
+           ;; syntax properties and retry, on the basis that it's very
+           ;; unlikely that paren angle brackets become operators by code
+           ;; manipulation.  It's far more likely that it doesn't match due
+           ;; to narrowing or some temporary change.
+           (goto-char start)
+           nil))
 
       (forward-char)
       (unless (looking-at c-<-op-cont-regexp)
@@ -3793,11 +4401,6 @@ This function does not do any hidden buffer changes."
                      ;; balanced sexp.  In that case we stop just short
                      ;; of it so check if the following char is the closer.
                      (when (eq (char-after) ?>)
-                       ;; Remove its syntax so that we don't enter the
-                       ;; recovery code below.  That's not necessary
-                       ;; since there's no real reason to suspect that
-                       ;; things inside the arglist are unbalanced.
-                       (c-clear-char-property (point) 'syntax-table)
                        (forward-char)
                        t)))
 
@@ -3806,40 +4409,21 @@ This function does not do any hidden buffer changes."
                  ;; Either an operator starting with '>' or the end of
                  ;; the angle bracket arglist.
 
-                 (if (and (/= (1- (point)) pos)
-                          (c-get-char-property (1- (point)) 'syntax-table)
-                          (progn
-                            (c-clear-char-property (1- (point)) 'syntax-table)
-                            (c-parse-sexp-lookup-properties)))
-
-                     ;; We've skipped past a list that ended with '>'.  It
-                     ;; must be unbalanced since nested arglists are handled
-                     ;; in the case below.  Recover by removing all paren
-                     ;; properties on '<' and '>' in the searched region and
-                     ;; redo the search.
+                 (if (looking-at c->-op-cont-regexp)
                      (progn
-                       (c-remove-<>-arglist-properties pos (point))
-                       (goto-char pos)
-                       t)
+                       (goto-char (match-end 0))
+                       t)              ; Continue the loop.
 
-                   (if (looking-at c->-op-cont-regexp)
-                       (progn
-                         (when (text-property-not-all
-                                (1- (point)) (match-end 0) 'syntax-table nil)
-                           (c-remove-<>-arglist-properties (1- (point))
-                                                           (match-end 0)))
-                         (goto-char (match-end 0))
-                         t)
-
-                     ;; The angle bracket arglist is finished.
+                   ;; The angle bracket arglist is finished.
+                   (when c-parse-and-markup-<>-arglists
                      (while arg-start-pos
-                       (c-put-char-property (1- (car arg-start-pos))
-                                            'c-type 'c-<>-arg-sep)
+                       (c-put-c-type-property (1- (car arg-start-pos))
+                                              'c-<>-arg-sep)
                        (setq arg-start-pos (cdr arg-start-pos)))
                      (c-mark-<-as-paren start)
-                     (c-mark->-as-paren (1- (point)))
-                     (setq res t)
-                     nil)))
+                     (c-mark->-as-paren (1- (point))))
+                   (setq res t)
+                   nil))               ; Exit the loop.
 
                 ((eq (char-before) ?<)
                  ;; Either an operator starting with '<' or a nested arglist.
@@ -3854,7 +4438,7 @@ This function does not do any hidden buffer changes."
                           (and
 
                            (save-excursion
-                             ;; There's always an identifier before a angle
+                             ;; There's always an identifier before an angle
                              ;; bracket arglist, or a keyword in
                              ;; `c-<>-type-kwds' or `c-<>-arglist-kwds'.
                              (c-backward-syntactic-ws)
@@ -3872,26 +4456,11 @@ This function does not do any hidden buffer changes."
                                     (and keyword-match
                                          (c-keyword-member
                                           (c-keyword-sym (match-string 1))
-                                          'c-<>-type-kwds))
-                                    (and reparse
-                                         c-restricted-<>-arglists))))
+                                          'c-<>-type-kwds)))))
                            )))
 
                        ;; It was not an angle bracket arglist.
-                       (progn
-                         (when (text-property-not-all
-                                (1- pos) tmp 'syntax-table nil)
-                           (if (c-parse-sexp-lookup-properties)
-                               ;; Got an invalid open paren syntax on this
-                               ;; '<'.  We'll probably get an unbalanced '>'
-                               ;; further ahead if we just remove the syntax
-                               ;; here, so recover by removing all paren
-                               ;; properties up to and including the
-                               ;; balancing close paren.
-                               (parse-partial-sexp pos (point-max) -1)
-                             (goto-char tmp))
-                           (c-remove-<>-arglist-properties pos (point)))
-                         (goto-char tmp))
+                       (goto-char tmp)
 
                      ;; It was an angle bracket arglist.
                      (setq c-record-found-types subres)
@@ -3926,6 +4495,70 @@ This function does not do any hidden buffer changes."
       (if res
          (or c-record-found-types t)))))
 
+(defun c-backward-<>-arglist (all-types &optional limit)
+  ;; The point is assumed to be directly after a ">".  Try to treat it
+  ;; as the close paren of an angle bracket arglist and move back to
+  ;; the corresponding "<".  If successful, the point is left at
+  ;; the "<" and t is returned, otherwise the point isn't moved and
+  ;; nil is returned.  ALL-TYPES is passed on to
+  ;; `c-forward-<>-arglist'.
+  ;;
+  ;; If the optional LIMIT is given, it bounds the backward search.
+  ;; It's then assumed to be at a syntactically relevant position.
+  ;;
+  ;; This is a wrapper around `c-forward-<>-arglist'.  See that
+  ;; function for more details.
+
+  (let ((start (point)))
+    (backward-char)
+    (if (and (not c-parse-and-markup-<>-arglists)
+            (c-get-char-property (point) 'syntax-table))
+
+       (if (and (c-go-up-list-backward)
+                (eq (char-after) ?<))
+           t
+         ;; See corresponding note in `c-forward-<>-arglist'.
+         (goto-char start)
+         nil)
+
+      (while (and
+             (c-syntactic-skip-backward "^<;{}" limit t)
+
+             (if (eq (char-before) ?<)
+                 t
+               ;; Stopped at bob or a char that isn't allowed in an
+               ;; arglist, so we've failed.
+               (goto-char start)
+               nil)
+
+             (if (> (point)
+                    (progn (c-beginning-of-current-token)
+                           (point)))
+                 ;; If we moved then the "<" was part of some
+                 ;; multicharacter token.
+                 t
+
+               (backward-char)
+               (let ((beg-pos (point)))
+                 (if (c-forward-<>-arglist all-types)
+                     (cond ((= (point) start)
+                            ;; Matched the arglist.  Break the while.
+                            (goto-char beg-pos)
+                            nil)
+                           ((> (point) start)
+                            ;; We started from a non-paren ">" inside an
+                            ;; arglist.
+                            (goto-char start)
+                            nil)
+                           (t
+                            ;; Matched a shorter arglist.  Can be a nested
+                            ;; one so continue looking.
+                            (goto-char beg-pos)
+                            t))
+                   t)))))
+
+      (/= (point) start))))
+
 (defun c-forward-name ()
   ;; Move forward over a complete name if at the beginning of one,
   ;; stopping at the next following token.  If the point is not at
@@ -3939,8 +4572,14 @@ This function does not do any hidden buffer changes."
   ;; name is found, 'template if it's an identifier ending with an
   ;; angle bracket arglist, 'operator of it's an operator identifier,
   ;; or t if it's some other kind of name.
+  ;;
+  ;; This function records identifier ranges on
+  ;; `c-record-type-identifiers' and `c-record-ref-identifiers' if
+  ;; `c-record-type-identifiers' is non-nil.
+  ;;
+  ;; This function might do hidden buffer changes.
 
-  (let ((pos (point)) res id-start id-end
+  (let ((pos (point)) (start (point)) res id-start id-end
        ;; Turn off `c-promote-possible-types' here since we might
        ;; call `c-forward-<>-arglist' and we don't want it to promote
        ;; every suspect thing in the arglist to a type.  We're
@@ -3955,12 +4594,9 @@ This function does not do any hidden buffer changes."
         (progn
           ;; Check for keyword.  We go to the last symbol in
           ;; `c-identifier-key' first.
-          (if (eq c-identifier-key c-symbol-key)
-              (setq id-start (point)
-                    id-end (match-end 0))
-            (goto-char (setq id-end (match-end 0)))
-            (c-simple-skip-symbol-backward)
-            (setq id-start (point)))
+          (goto-char (setq id-end (match-end 0)))
+          (c-simple-skip-symbol-backward)
+          (setq id-start (point))
 
           (if (looking-at c-keywords-regexp)
               (when (and (c-major-mode-is 'c++-mode)
@@ -4018,9 +4654,8 @@ This function does not do any hidden buffer changes."
 
                       ((looking-at c-overloadable-operators-regexp)
                        ;; Got some other operator.
-                       (when c-record-type-identifiers
-                         (setq c-last-identifier-range
-                               (cons (point) (match-end 0))))
+                       (setq c-last-identifier-range
+                             (cons (point) (match-end 0)))
                        (goto-char (match-end 0))
                        (c-forward-syntactic-ws)
                        (setq pos (point)
@@ -4028,7 +4663,11 @@ This function does not do any hidden buffer changes."
 
                 nil)
 
-            (when c-record-type-identifiers
+            ;; `id-start' is equal to `id-end' if we've jumped over
+            ;; an identifier that doesn't end with a symbol token.
+            ;; That can occur e.g. for Java import directives on the
+            ;; form "foo.bar.*".
+            (when (and id-start (/= id-start id-end))
               (setq c-last-identifier-range
                     (cons id-start id-end)))
             (goto-char id-end)
@@ -4054,29 +4693,30 @@ This function does not do any hidden buffer changes."
              ((and c-recognize-<>-arglists
                    (eq (char-after) ?<))
               ;; Maybe an angle bracket arglist.
-              (when (let ((c-record-type-identifiers nil)
-                          (c-record-found-types nil))
-                      (c-forward-<>-arglist
-                       nil c-restricted-<>-arglists))
+
+              (when (let (c-record-type-identifiers
+                          c-record-found-types)
+                      (c-forward-<>-arglist nil))
+
+                (c-add-type start (1+ pos))
                 (c-forward-syntactic-ws)
-                (setq pos (point))
+                (setq pos (point)
+                      c-last-identifier-range nil)
+
                 (if (and c-opt-identifier-concat-key
                          (looking-at c-opt-identifier-concat-key))
+
                     ;; Continue if there's an identifier concatenation
                     ;; operator after the template argument.
                     (progn
-                      (when c-record-type-identifiers
-                        (c-record-ref-id (cons id-start id-end))
-                        (setq c-last-identifier-range nil))
+                      (when (and c-record-type-identifiers id-start)
+                        (c-record-ref-id (cons id-start id-end)))
                       (forward-char 2)
                       (c-forward-syntactic-ws)
                       t)
-                  ;; `c-add-type' isn't called here since we don't
-                  ;; want to add types containing angle bracket
-                  ;; arglists.
-                  (when c-record-type-identifiers
-                    (c-record-type-id (cons id-start id-end))
-                    (setq c-last-identifier-range nil))
+
+                  (when (and c-record-type-identifiers id-start)
+                    (c-record-type-id (cons id-start id-end)))
                   (setq res 'template)
                   nil)))
              )))))
@@ -4098,7 +4738,14 @@ This function does not do any hidden buffer changes."
   ;; Note that this function doesn't skip past the brace definition
   ;; that might be considered part of the type, e.g.
   ;; "enum {a, b, c} foo".
-  (let ((start (point)) pos res res2 id-start id-end id-range)
+  ;;
+  ;; This function records identifier ranges on
+  ;; `c-record-type-identifiers' and `c-record-ref-identifiers' if
+  ;; `c-record-type-identifiers' is non-nil.
+  ;;
+  ;; This function might do hidden buffer changes.
+
+  (let ((start (point)) pos res name-res id-start id-end id-range)
 
     ;; Skip leading type modifiers.  If any are found we know it's a
     ;; prefix of a type.
@@ -4115,13 +4762,14 @@ This function does not do any hidden buffer changes."
       (goto-char (match-end 1))
       (c-forward-syntactic-ws)
       (setq pos (point))
-      (if (memq (setq res2 (c-forward-name)) '(t template))
+      (if (memq (setq name-res (c-forward-name)) '(t template))
          (progn
-           (when (eq res2 t)
+           (when (eq name-res t)
              ;; In many languages the name can be used without the
              ;; prefix, so we add it to `c-found-types'.
              (c-add-type pos (point))
-             (when c-record-type-identifiers
+             (when (and c-record-type-identifiers
+                        c-last-identifier-range)
                (c-record-type-id c-last-identifier-range)))
            (setq res t))
        ;; Invalid syntax.
@@ -4133,8 +4781,8 @@ This function does not do any hidden buffer changes."
        (if (looking-at c-identifier-start)
            (save-excursion
              (setq id-start (point)
-                   res2 (c-forward-name))
-             (when res2
+                   name-res (c-forward-name))
+             (when name-res
                (setq id-end (point)
                      id-range c-last-identifier-range))))
        (and (cond ((looking-at c-primitive-type-key)
@@ -4165,7 +4813,7 @@ This function does not do any hidden buffer changes."
                 (looking-at c-opt-type-component-key)))
          ;; There might be more keywords for the type.
          (let (safe-pos)
-           (c-forward-keyword-clause)
+           (c-forward-keyword-clause 1)
            (while (progn
                     (setq safe-pos (point))
                     (looking-at c-opt-type-component-key))
@@ -4173,30 +4821,30 @@ This function does not do any hidden buffer changes."
                         (looking-at c-primitive-type-key))
                (c-record-type-id (cons (match-beginning 1)
                                        (match-end 1))))
-             (c-forward-keyword-clause))
+             (c-forward-keyword-clause 1))
            (if (looking-at c-primitive-type-key)
                (progn
                  (when c-record-type-identifiers
                    (c-record-type-id (cons (match-beginning 1)
                                            (match-end 1))))
-                 (c-forward-keyword-clause)
+                 (c-forward-keyword-clause 1)
                  (setq res t))
              (goto-char safe-pos)
              (setq res 'prefix)))
-       (unless (save-match-data (c-forward-keyword-clause))
+       (unless (save-match-data (c-forward-keyword-clause 1))
          (if pos
              (goto-char pos)
            (goto-char (match-end 1))
            (c-forward-syntactic-ws)))))
 
-     (res2
-      (cond ((eq res2 t)
+     (name-res
+      (cond ((eq name-res t)
             ;; A normal identifier.
             (goto-char id-end)
             (if (or res c-promote-possible-types)
                 (progn
                   (c-add-type id-start id-end)
-                  (when c-record-type-identifiers
+                  (when (and c-record-type-identifiers id-range)
                     (c-record-type-id id-range))
                   (unless res
                     (setq res 'found)))
@@ -4206,7 +4854,7 @@ This function does not do any hidden buffer changes."
                             'found
                           ;; It's an identifier that might be a type.
                           'maybe))))
-           ((eq res2 'template)
+           ((eq name-res 'template)
             ;; A template is a type.
             (goto-char id-end)
             (setq res t))
@@ -4234,9 +4882,11 @@ This function does not do any hidden buffer changes."
          (c-forward-syntactic-ws)))
 
       (when c-opt-type-concat-key
-       ;; Look for a trailing operator that concatenate the type with
-       ;; a following one, and if so step past that one through a
-       ;; recursive call.
+       ;; Look for a trailing operator that concatenates the type
+       ;; with a following one, and if so step past that one through
+       ;; a recursive call.  Note that we don't record concatenated
+       ;; types in `c-found-types' - it's the component types that
+       ;; are recorded when appropriate.
        (setq pos (point))
        (let* ((c-promote-possible-types (or (memq res '(t known))
                                             c-promote-possible-types))
@@ -4244,29 +4894,31 @@ This function does not do any hidden buffer changes."
               ;; we can merge in the types from the second part afterwards if
               ;; it turns out to be a known type there.
               (c-record-found-types (and c-record-type-identifiers
-                                         (not c-promote-possible-types))))
+                                         (not c-promote-possible-types)))
+              subres)
          (if (and (looking-at c-opt-type-concat-key)
 
                   (progn
                     (goto-char (match-end 1))
                     (c-forward-syntactic-ws)
-                    (setq res2 (c-forward-type))))
+                    (setq subres (c-forward-type))))
 
              (progn
                ;; If either operand certainly is a type then both are, but we
                ;; don't let the existence of the operator itself promote two
                ;; uncertain types to a certain one.
                (cond ((eq res t))
-                     ((eq res2 t)
-                      (c-add-type id-start id-end)
-                      (when c-record-type-identifiers
+                     ((eq subres t)
+                      (unless (eq name-res 'template)
+                        (c-add-type id-start id-end))
+                      (when (and c-record-type-identifiers id-range)
                         (c-record-type-id id-range))
                       (setq res t))
                      ((eq res 'known))
-                     ((eq res2 'known)
+                     ((eq subres 'known)
                       (setq res 'known))
                      ((eq res 'found))
-                     ((eq res2 'found)
+                     ((eq subres 'found)
                       (setq res 'found))
                      (t
                       (setq res 'maybe)))
@@ -4294,23 +4946,1099 @@ This function does not do any hidden buffer changes."
 \f
 ;; Handling of large scale constructs like statements and declarations.
 
+;; Macro used inside `c-forward-decl-or-cast-1'.  It ought to be a
+;; defsubst or perhaps even a defun, but it contains lots of free
+;; variables that refer to things inside `c-forward-decl-or-cast-1'.
+(defmacro c-fdoc-shift-type-backward (&optional short)
+  ;; `c-forward-decl-or-cast-1' can consume an arbitrary length list
+  ;; of types when parsing a declaration, which means that it
+  ;; sometimes consumes the identifier in the declaration as a type.
+  ;; This is used to "backtrack" and make the last type be treated as
+  ;; an identifier instead.
+  `(progn
+     ,(unless short
+       ;; These identifiers are bound only in the inner let.
+       '(setq identifier-type at-type
+              identifier-start type-start
+              got-parens nil
+              got-identifier t
+              got-suffix t
+              got-suffix-after-parens id-start
+              paren-depth 0))
+
+     (if (setq at-type (if (eq backup-at-type 'prefix)
+                          t
+                        backup-at-type))
+        (setq type-start backup-type-start
+              id-start backup-id-start)
+       (setq type-start start-pos
+            id-start start-pos))
+
+     ;; When these flags already are set we've found specifiers that
+     ;; unconditionally signal these attributes - backtracking doesn't
+     ;; change that.  So keep them set in that case.
+     (or at-type-decl
+        (setq at-type-decl backup-at-type-decl))
+     (or maybe-typeless
+        (setq maybe-typeless backup-maybe-typeless))
+
+     ,(unless short
+       ;; This identifier is bound only in the inner let.
+       '(setq start id-start))))
+
+(defun c-forward-decl-or-cast-1 (preceding-token-end context last-cast-end)
+  ;; Move forward over a declaration or a cast if at the start of one.
+  ;; The point is assumed to be at the start of some token.  Nil is
+  ;; returned if no declaration or cast is recognized, and the point
+  ;; is clobbered in that case.
+  ;;
+  ;; If a declaration is parsed:
+  ;;
+  ;;   The point is left at the first token after the first complete
+  ;;   declarator, if there is one.  The return value is a cons where
+  ;;   the car is the position of the first token in the declarator.
+  ;;   Some examples:
+  ;;
+  ;;    void foo (int a, char *b) stuff ...
+  ;;     car ^                    ^ point
+  ;;    float (*a)[], b;
+  ;;      car ^     ^ point
+  ;;    unsigned int a = c_style_initializer, b;
+  ;;             car ^ ^ point
+  ;;    unsigned int a (cplusplus_style_initializer), b;
+  ;;             car ^                              ^ point (might change)
+  ;;    class Foo : public Bar {}
+  ;;      car ^   ^ point
+  ;;    class PikeClass (int a, string b) stuff ...
+  ;;      car ^                           ^ point
+  ;;    enum bool;
+  ;;     car ^   ^ point
+  ;;    enum bool flag;
+  ;;          car ^   ^ point
+  ;;     void cplusplus_function (int x) throw (Bad);
+  ;;      car ^                                     ^ point
+  ;;     Foo::Foo (int b) : Base (b) {}
+  ;; car ^                ^ point
+  ;;
+  ;;   The cdr of the return value is non-nil iff a
+  ;;   `c-typedef-decl-kwds' specifier is found in the declaration,
+  ;;   i.e. the declared identifier(s) are types.
+  ;;
+  ;; If a cast is parsed:
+  ;;
+  ;;   The point is left at the first token after the closing paren of
+  ;;   the cast.  The return value is `cast'.  Note that the start
+  ;;   position must be at the first token inside the cast parenthesis
+  ;;   to recognize it.
+  ;;
+  ;; PRECEDING-TOKEN-END is the first position after the preceding
+  ;; token, i.e. on the other side of the syntactic ws from the point.
+  ;; Use a value less than or equal to (point-min) if the point is at
+  ;; the first token in (the visible part of) the buffer.
+  ;;
+  ;; CONTEXT is a symbol that describes the context at the point:
+  ;; 'decl     In a comma-separatded declaration context (typically
+  ;;           inside a function declaration arglist).
+  ;; '<>       In an angle bracket arglist.
+  ;; 'arglist  Some other type of arglist.
+  ;; nil       Some other context or unknown context.
+  ;;
+  ;; LAST-CAST-END is the first token after the closing paren of a
+  ;; preceding cast, or nil if none is known.  If
+  ;; `c-forward-decl-or-cast-1' is used in succession, it should be
+  ;; the position after the closest preceding call where a cast was
+  ;; matched.  In that case it's used to discover chains of casts like
+  ;; "(a) (b) c".
+  ;;
+  ;; This function records identifier ranges on
+  ;; `c-record-type-identifiers' and `c-record-ref-identifiers' if
+  ;; `c-record-type-identifiers' is non-nil.
+  ;;
+  ;; This function might do hidden buffer changes.
+
+  (let (;; `start-pos' is used below to point to the start of the
+       ;; first type, i.e. after any leading specifiers.  It might
+       ;; also point at the beginning of the preceding syntactic
+       ;; whitespace.
+       (start-pos (point))
+       ;; Set to the result of `c-forward-type'.
+       at-type
+       ;; The position of the first token in what we currently
+       ;; believe is the type in the declaration or cast, after any
+       ;; specifiers and their associated clauses.
+       type-start
+       ;; The position of the first token in what we currently
+       ;; believe is the declarator for the first identifier.  Set
+       ;; when the type is found, and moved forward over any
+       ;; `c-decl-hangon-kwds' and their associated clauses that
+       ;; occurs after the type.
+       id-start
+       ;; These store `at-type', `type-start' and `id-start' of the
+       ;; identifier before the one in those variables.  The previous
+       ;; identifier might turn out to be the real type in a
+       ;; declaration if the last one has to be the declarator in it.
+       ;; If `backup-at-type' is nil then the other variables have
+       ;; undefined values.
+       backup-at-type backup-type-start backup-id-start
+       ;; Set if we've found a specifier that makes the defined
+       ;; identifier(s) types.
+       at-type-decl
+       ;; Set if we've found a specifier that can start a declaration
+       ;; where there's no type.
+       maybe-typeless
+       ;; If a specifier is found that also can be a type prefix,
+       ;; these flags are set instead of those above.  If we need to
+       ;; back up an identifier, they are copied to the real flag
+       ;; variables.  Thus they only take effect if we fail to
+       ;; interpret it as a type.
+       backup-at-type-decl backup-maybe-typeless
+       ;; Whether we've found a declaration or a cast.  We might know
+       ;; this before we've found the type in it.  It's 'ids if we've
+       ;; found two consecutive identifiers (usually a sure sign, but
+       ;; we should allow that in labels too), and t if we've found a
+       ;; specifier keyword (a 100% sure sign).
+       at-decl-or-cast
+       ;; Set when we need to back up to parse this as a declaration
+       ;; but not as a cast.
+       backup-if-not-cast
+       ;; For casts, the return position.
+       cast-end
+       ;; Save `c-record-type-identifiers' and
+       ;; `c-record-ref-identifiers' since ranges are recorded
+       ;; speculatively and should be thrown away if it turns out
+       ;; that it isn't a declaration or cast.
+       (save-rec-type-ids c-record-type-identifiers)
+       (save-rec-ref-ids c-record-ref-identifiers))
+
+    ;; Check for a type.  Unknown symbols are treated as possible
+    ;; types, but they could also be specifiers disguised through
+    ;; macros like __INLINE__, so we recognize both types and known
+    ;; specifiers after them too.
+    (while
+       (let* ((start (point)) kwd-sym kwd-clause-end found-type)
+
+         ;; Look for a specifier keyword clause.
+         (when (looking-at c-prefix-spec-kwds-re)
+           (setq kwd-sym (c-keyword-sym (match-string 1)))
+           (save-excursion
+             (c-forward-keyword-clause 1)
+             (setq kwd-clause-end (point))))
+
+         (when (setq found-type (c-forward-type))
+           ;; Found a known or possible type or a prefix of a known type.
+
+           (when at-type
+             ;; Got two identifiers with nothing but whitespace
+             ;; between them.  That can only happen in declarations.
+             (setq at-decl-or-cast 'ids)
+
+             (when (eq at-type 'found)
+               ;; If the previous identifier is a found type we
+               ;; record it as a real one; it might be some sort of
+               ;; alias for a prefix like "unsigned".
+               (save-excursion
+                 (goto-char type-start)
+                 (let ((c-promote-possible-types t))
+                   (c-forward-type)))))
+
+           (setq backup-at-type at-type
+                 backup-type-start type-start
+                 backup-id-start id-start
+                 at-type found-type
+                 type-start start
+                 id-start (point)
+                 ;; The previous ambiguous specifier/type turned out
+                 ;; to be a type since we've parsed another one after
+                 ;; it, so clear these backup flags.
+                 backup-at-type-decl nil
+                 backup-maybe-typeless nil))
+
+         (if kwd-sym
+             (progn
+               ;; Handle known specifier keywords and
+               ;; `c-decl-hangon-kwds' which can occur after known
+               ;; types.
+
+               (if (c-keyword-member kwd-sym 'c-decl-hangon-kwds)
+                   ;; It's a hang-on keyword that can occur anywhere.
+                   (progn
+                     (setq at-decl-or-cast t)
+                     (if at-type
+                         ;; Move the identifier start position if
+                         ;; we've passed a type.
+                         (setq id-start kwd-clause-end)
+                       ;; Otherwise treat this as a specifier and
+                       ;; move the fallback position.
+                       (setq start-pos kwd-clause-end))
+                     (goto-char kwd-clause-end))
+
+                 ;; It's an ordinary specifier so we know that
+                 ;; anything before this can't be the type.
+                 (setq backup-at-type nil
+                       start-pos kwd-clause-end)
+
+                 (if found-type
+                     ;; It's ambiguous whether this keyword is a
+                     ;; specifier or a type prefix, so set the backup
+                     ;; flags.  (It's assumed that `c-forward-type'
+                     ;; moved further than `c-forward-keyword-clause'.)
+                     (progn
+                       (when (c-keyword-member kwd-sym 'c-typedef-decl-kwds)
+                         (setq backup-at-type-decl t))
+                       (when (c-keyword-member kwd-sym 'c-typeless-decl-kwds)
+                         (setq backup-maybe-typeless t)))
+
+                   (when (c-keyword-member kwd-sym 'c-typedef-decl-kwds)
+                     (setq at-type-decl t))
+                   (when (c-keyword-member kwd-sym 'c-typeless-decl-kwds)
+                     (setq maybe-typeless t))
+
+                   ;; Haven't matched a type so it's an umambiguous
+                   ;; specifier keyword and we know we're in a
+                   ;; declaration.
+                   (setq at-decl-or-cast t)
+
+                   (goto-char kwd-clause-end))))
+
+           ;; If the type isn't known we continue so that we'll jump
+           ;; over all specifiers and type identifiers.  The reason
+           ;; to do this for a known type prefix is to make things
+           ;; like "unsigned INT16" work.
+           (and found-type (not (eq found-type t))))))
+
+    (cond
+     ((eq at-type t)
+      ;; If a known type was found, we still need to skip over any
+      ;; hangon keyword clauses after it.  Otherwise it has already
+      ;; been done in the loop above.
+      (while (looking-at c-decl-hangon-key)
+       (c-forward-keyword-clause 1))
+      (setq id-start (point)))
+
+     ((eq at-type 'prefix)
+      ;; A prefix type is itself a primitive type when it's not
+      ;; followed by another type.
+      (setq at-type t))
+
+     ((not at-type)
+      ;; Got no type but set things up to continue anyway to handle
+      ;; the various cases when a declaration doesn't start with a
+      ;; type.
+      (setq id-start start-pos))
+
+     ((and (eq at-type 'maybe)
+          (c-major-mode-is 'c++-mode))
+      ;; If it's C++ then check if the last "type" ends on the form
+      ;; "foo::foo" or "foo::~foo", i.e. if it's the name of a
+      ;; (con|de)structor.
+      (save-excursion
+       (let (name end-2 end-1)
+         (goto-char id-start)
+         (c-backward-syntactic-ws)
+         (setq end-2 (point))
+         (when (and
+                (c-simple-skip-symbol-backward)
+                (progn
+                  (setq name
+                        (buffer-substring-no-properties (point) end-2))
+                  ;; Cheating in the handling of syntactic ws below.
+                  (< (skip-chars-backward ":~ \t\n\r\v\f") 0))
+                (progn
+                  (setq end-1 (point))
+                  (c-simple-skip-symbol-backward))
+                (>= (point) type-start)
+                (equal (buffer-substring-no-properties (point) end-1)
+                       name))
+           ;; It is a (con|de)structor name.  In that case the
+           ;; declaration is typeless so zap out any preceding
+           ;; identifier(s) that we might have taken as types.
+           (goto-char type-start)
+           (setq at-type nil
+                 backup-at-type nil
+                 id-start type-start))))))
+
+    ;; Check for and step over a type decl expression after the thing
+    ;; that is or might be a type.  This can't be skipped since we
+    ;; need the correct end position of the declarator for
+    ;; `max-type-decl-end-*'.
+    (let ((start (point)) (paren-depth 0) pos
+         ;; True if there's a non-open-paren match of
+         ;; `c-type-decl-prefix-key'.
+         got-prefix
+         ;; True if the declarator is surrounded by a parenthesis pair.
+         got-parens
+         ;; True if there is an identifier in the declarator.
+         got-identifier
+         ;; True if there's a non-close-paren match of
+         ;; `c-type-decl-suffix-key'.
+         got-suffix
+         ;; True if there's a prefix match outside the outermost
+         ;; paren pair that surrounds the declarator.
+         got-prefix-before-parens
+y        ;; True if there's a suffix match outside the outermost
+         ;; paren pair that surrounds the declarator.  The value is
+         ;; the position of the first suffix match.
+         got-suffix-after-parens
+         ;; True if we've parsed the type decl to a token that is
+         ;; known to end declarations in this context.
+         at-decl-end
+         ;; The earlier values of `at-type' and `type-start' if we've
+         ;; shifted the type backwards.
+         identifier-type identifier-start
+         ;; If `c-parse-and-markup-<>-arglists' is set we need to
+         ;; turn it off during the name skipping below to avoid
+         ;; getting `c-type' properties that might be bogus.  That
+         ;; can happen since we don't know if
+         ;; `c-restricted-<>-arglists' will be correct inside the
+         ;; arglist paren that gets entered.
+         c-parse-and-markup-<>-arglists)
+
+      (goto-char id-start)
+
+      ;; Skip over type decl prefix operators.  (Note similar code in
+      ;; `c-font-lock-declarators'.)
+      (while (and (looking-at c-type-decl-prefix-key)
+                 (if (and (c-major-mode-is 'c++-mode)
+                          (match-beginning 2))
+                     ;; If the second submatch matches in C++ then
+                     ;; we're looking at an identifier that's a
+                     ;; prefix only if it specifies a member pointer.
+                     (when (setq got-identifier (c-forward-name))
+                       (if (looking-at "\\(::\\)")
+                           ;; We only check for a trailing "::" and
+                           ;; let the "*" that should follow be
+                           ;; matched in the next round.
+                           (progn (setq got-identifier nil) t)
+                         ;; It turned out to be the real identifier,
+                         ;; so stop.
+                         nil))
+                   t))
+
+       (if (eq (char-after) ?\()
+           (progn
+             (setq paren-depth (1+ paren-depth))
+             (forward-char))
+         (unless got-prefix-before-parens
+           (setq got-prefix-before-parens (= paren-depth 0)))
+         (setq got-prefix t)
+         (goto-char (match-end 1)))
+       (c-forward-syntactic-ws))
+
+      (setq got-parens (> paren-depth 0))
+
+      ;; Skip over an identifier.
+      (or got-identifier
+         (and (looking-at c-identifier-start)
+              (setq got-identifier (c-forward-name))))
+
+      ;; Skip over type decl suffix operators.
+      (while (if (looking-at c-type-decl-suffix-key)
+
+                (if (eq (char-after) ?\))
+                    (when (> paren-depth 0)
+                      (setq paren-depth (1- paren-depth))
+                      (forward-char)
+                      t)
+                  (when (if (save-match-data (looking-at "\\s\("))
+                            (c-safe (c-forward-sexp 1) t)
+                          (goto-char (match-end 1))
+                          t)
+                    (when (and (not got-suffix-after-parens)
+                               (= paren-depth 0))
+                      (setq got-suffix-after-parens (match-beginning 0)))
+                    (setq got-suffix t)))
+
+              ;; No suffix matched.  We might have matched the
+              ;; identifier as a type and the open paren of a
+              ;; function arglist as a type decl prefix.  In that
+              ;; case we should "backtrack": Reinterpret the last
+              ;; type as the identifier, move out of the arglist and
+              ;; continue searching for suffix operators.
+              ;;
+              ;; Do this even if there's no preceding type, to cope
+              ;; with old style function declarations in K&R C,
+              ;; (con|de)structors in C++ and `c-typeless-decl-kwds'
+              ;; style declarations.  That isn't applicable in an
+              ;; arglist context, though.
+              (when (and (= paren-depth 1)
+                         (not got-prefix-before-parens)
+                         (not (eq at-type t))
+                         (or backup-at-type
+                             maybe-typeless
+                             backup-maybe-typeless
+                             (when c-recognize-typeless-decls
+                               (not context)))
+                         (setq pos (c-up-list-forward (point)))
+                         (eq (char-before pos) ?\)))
+                (c-fdoc-shift-type-backward)
+                (goto-char pos)
+                t))
+
+       (c-forward-syntactic-ws))
+
+      (when (and (or maybe-typeless backup-maybe-typeless)
+                (not got-identifier)
+                (not got-prefix)
+                at-type)
+       ;; Have found no identifier but `c-typeless-decl-kwds' has
+       ;; matched so we know we're inside a declaration.  The
+       ;; preceding type must be the identifier instead.
+       (c-fdoc-shift-type-backward))
+
+      (setq
+       at-decl-or-cast
+       (catch 'at-decl-or-cast
+
+       (when (> paren-depth 0)
+         ;; Encountered something inside parens that isn't matched by
+         ;; the `c-type-decl-*' regexps, so it's not a type decl
+         ;; expression.  Try to skip out to the same paren depth to
+         ;; not confuse the cast check below.
+         (c-safe (goto-char (scan-lists (point) 1 paren-depth)))
+         ;; If we've found a specifier keyword then it's a
+         ;; declaration regardless.
+         (throw 'at-decl-or-cast (eq at-decl-or-cast t)))
+
+       (setq at-decl-end
+             (looking-at (cond ((eq context '<>) "[,>]")
+                               (context "[,\)]")
+                               (t "[,;]"))))
+
+       ;; Now we've collected info about various characteristics of
+       ;; the construct we're looking at.  Below follows a decision
+       ;; tree based on that.  It's ordered to check more certain
+       ;; signs before less certain ones.
+
+       (if got-identifier
+           (progn
+
+             (when (and (or at-type maybe-typeless)
+                        (not (or got-prefix got-parens)))
+               ;; Got another identifier directly after the type, so it's a
+               ;; declaration.
+               (throw 'at-decl-or-cast t))
+
+             (when (and got-parens
+                        (not got-prefix)
+                        (not got-suffix-after-parens)
+                        (or backup-at-type
+                            maybe-typeless
+                            backup-maybe-typeless))
+               ;; Got a declaration of the form "foo bar (gnu);" where we've
+               ;; recognized "bar" as the type and "gnu" as the declarator.
+               ;; In this case it's however more likely that "bar" is the
+               ;; declarator and "gnu" a function argument or initializer (if
+               ;; `c-recognize-paren-inits' is set), since the parens around
+               ;; "gnu" would be superfluous if it's a declarator.  Shift the
+               ;; type one step backward.
+               (c-fdoc-shift-type-backward)))
+
+         ;; Found no identifier.
+
+         (if backup-at-type
+             (progn
+
+               (when (= (point) start)
+                 ;; Got a plain list of identifiers.  If a colon follows it's
+                 ;; a valid label.  Otherwise the last one probably is the
+                 ;; declared identifier and we should back up to the previous
+                 ;; type, providing it isn't a cast.
+                 (if (eq (char-after) ?:)
+                     ;; If we've found a specifier keyword then it's a
+                     ;; declaration regardless.
+                     (throw 'at-decl-or-cast (eq at-decl-or-cast t))
+                   (setq backup-if-not-cast t)
+                   (throw 'at-decl-or-cast t)))
+
+               (when (and got-suffix
+                          (not got-prefix)
+                          (not got-parens))
+                 ;; Got a plain list of identifiers followed by some suffix.
+                 ;; If this isn't a cast then the last identifier probably is
+                 ;; the declared one and we should back up to the previous
+                 ;; type.
+                 (setq backup-if-not-cast t)
+                 (throw 'at-decl-or-cast t)))
+
+           (when (eq at-type t)
+             ;; If the type is known we know that there can't be any
+             ;; identifier somewhere else, and it's only in declarations in
+             ;; e.g. function prototypes and in casts that the identifier may
+             ;; be left out.
+             (throw 'at-decl-or-cast t))
+
+           (when (= (point) start)
+             ;; Only got a single identifier (parsed as a type so far).
+             (if (and
+                  ;; Check that the identifier isn't at the start of an
+                  ;; expression.
+                  at-decl-end
+                  (cond
+                   ((eq context 'decl)
+                    ;; Inside an arglist that contains declarations.  If K&R
+                    ;; style declarations and parenthesis style initializers
+                    ;; aren't allowed then the single identifier must be a
+                    ;; type, else we require that it's known or found
+                    ;; (primitive types are handled above).
+                    (or (and (not c-recognize-knr-p)
+                             (not c-recognize-paren-inits))
+                        (memq at-type '(known found))))
+                   ((eq context '<>)
+                    ;; Inside a template arglist.  Accept known and found
+                    ;; types; other identifiers could just as well be
+                    ;; constants in C++.
+                    (memq at-type '(known found)))))
+                 (throw 'at-decl-or-cast t)
+               ;; Can't be a valid declaration or cast, but if we've found a
+               ;; specifier it can't be anything else either, so treat it as
+               ;; an invalid/unfinished declaration or cast.
+               (throw 'at-decl-or-cast at-decl-or-cast))))
+
+         (if (and got-parens
+                  (not got-prefix)
+                  (not context)
+                  (not (eq at-type t))
+                  (or backup-at-type
+                      maybe-typeless
+                      backup-maybe-typeless
+                      (when c-recognize-typeless-decls
+                        (or (not got-suffix)
+                            (not (looking-at
+                                  c-after-suffixed-type-maybe-decl-key))))))
+             ;; Got an empty paren pair and a preceding type that probably
+             ;; really is the identifier.  Shift the type backwards to make
+             ;; the last one the identifier.  This is analogous to the
+             ;; "backtracking" done inside the `c-type-decl-suffix-key' loop
+             ;; above.
+             ;;
+             ;; Exception: In addition to the conditions in that
+             ;; "backtracking" code, do not shift backward if we're not
+             ;; looking at either `c-after-suffixed-type-decl-key' or "[;,]".
+             ;; Since there's no preceding type, the shift would mean that
+             ;; the declaration is typeless.  But if the regexp doesn't match
+             ;; then we will simply fall through in the tests below and not
+             ;; recognize it at all, so it's better to try it as an abstract
+             ;; declarator instead.
+             (c-fdoc-shift-type-backward)
+
+           ;; Still no identifier.
+
+           (when (and got-prefix (or got-parens got-suffix))
+             ;; Require `got-prefix' together with either `got-parens' or
+             ;; `got-suffix' to recognize it as an abstract declarator:
+             ;; `got-parens' only is probably an empty function call.
+             ;; `got-suffix' only can build an ordinary expression together
+             ;; with the preceding identifier which we've taken as a type.
+             ;; We could actually accept on `got-prefix' only, but that can
+             ;; easily occur temporarily while writing an expression so we
+             ;; avoid that case anyway.  We could do a better job if we knew
+             ;; the point when the fontification was invoked.
+             (throw 'at-decl-or-cast t))
+
+           (when (and at-type
+                      (not got-prefix)
+                      (not got-parens)
+                      got-suffix-after-parens
+                      (eq (char-after got-suffix-after-parens) ?\())
+             ;; Got a type, no declarator but a paren suffix. I.e. it's a
+             ;; normal function call afterall (or perhaps a C++ style object
+             ;; instantiation expression).
+             (throw 'at-decl-or-cast nil))))
+
+       (when at-decl-or-cast
+         ;; By now we've located the type in the declaration that we know
+         ;; we're in.
+         (throw 'at-decl-or-cast t))
+
+       (when (and got-identifier
+                  (not context)
+                  (looking-at c-after-suffixed-type-decl-key)
+                  (if (and got-parens
+                           (not got-prefix)
+                           (not got-suffix)
+                           (not (eq at-type t)))
+                      ;; Shift the type backward in the case that there's a
+                      ;; single identifier inside parens.  That can only
+                      ;; occur in K&R style function declarations so it's
+                      ;; more likely that it really is a function call.
+                      ;; Therefore we only do this after
+                      ;; `c-after-suffixed-type-decl-key' has matched.
+                      (progn (c-fdoc-shift-type-backward) t)
+                    got-suffix-after-parens))
+         ;; A declaration according to `c-after-suffixed-type-decl-key'.
+         (throw 'at-decl-or-cast t))
+
+       (when (and (or got-prefix (not got-parens))
+                  (memq at-type '(t known)))
+         ;; It's a declaration if a known type precedes it and it can't be a
+         ;; function call.
+         (throw 'at-decl-or-cast t))
+
+       ;; If we get here we can't tell if this is a type decl or a normal
+       ;; expression by looking at it alone.  (That's under the assumption
+       ;; that normal expressions always can look like type decl expressions,
+       ;; which isn't really true but the cases where it doesn't hold are so
+       ;; uncommon (e.g. some placements of "const" in C++) it's not worth
+       ;; the effort to look for them.)
+
+       (unless (or at-decl-end (looking-at "=[^=]"))
+         ;; If this is a declaration it should end here or its initializer(*)
+         ;; should start here, so check for allowed separation tokens.  Note
+         ;; that this rule doesn't work e.g. with a K&R arglist after a
+         ;; function header.
+         ;;
+         ;; *) Don't check for C++ style initializers using parens
+         ;; since those already have been matched as suffixes.
+         ;;
+         ;; If `at-decl-or-cast' is then we've found some other sign that
+         ;; it's a declaration or cast, so then it's probably an
+         ;; invalid/unfinished one.
+         (throw 'at-decl-or-cast at-decl-or-cast))
+
+       ;; Below are tests that only should be applied when we're certain to
+       ;; not have parsed halfway through an expression.
+
+       (when (memq at-type '(t known))
+         ;; The expression starts with a known type so treat it as a
+         ;; declaration.
+         (throw 'at-decl-or-cast t))
+
+       (when (and (c-major-mode-is 'c++-mode)
+                  ;; In C++ we check if the identifier is a known type, since
+                  ;; (con|de)structors use the class name as identifier.
+                  ;; We've always shifted over the identifier as a type and
+                  ;; then backed up again in this case.
+                  identifier-type
+                  (or (memq identifier-type '(found known))
+                      (and (eq (char-after identifier-start) ?~)
+                           ;; `at-type' probably won't be 'found for
+                           ;; destructors since the "~" is then part of the
+                           ;; type name being checked against the list of
+                           ;; known types, so do a check without that
+                           ;; operator.
+                           (or (save-excursion
+                                 (goto-char (1+ identifier-start))
+                                 (c-forward-syntactic-ws)
+                                 (c-with-syntax-table
+                                     c-identifier-syntax-table
+                                   (looking-at c-known-type-key)))
+                               (save-excursion
+                                 (goto-char (1+ identifier-start))
+                                 ;; We have already parsed the type earlier,
+                                 ;; so it'd be possible to cache the end
+                                 ;; position instead of redoing it here, but
+                                 ;; then we'd need to keep track of another
+                                 ;; position everywhere.
+                                 (c-check-type (point)
+                                               (progn (c-forward-type)
+                                                      (point))))))))
+         (throw 'at-decl-or-cast t))
+
+       (if got-identifier
+           (progn
+             (when (and got-prefix-before-parens
+                        at-type
+                        (or at-decl-end (looking-at "=[^=]"))
+                        (not context)
+                        (not got-suffix))
+               ;; Got something like "foo * bar;".  Since we're not inside an
+               ;; arglist it would be a meaningless expression because the
+               ;; result isn't used.  We therefore choose to recognize it as
+               ;; a declaration.  Do not allow a suffix since it could then
+               ;; be a function call.
+               (throw 'at-decl-or-cast t))
+
+             (when (and (or got-suffix-after-parens
+                            (looking-at "=[^=]"))
+                        (eq at-type 'found)
+                        (not (eq context 'arglist)))
+               ;; Got something like "a (*b) (c);" or "a (b) = c;".  It could
+               ;; be an odd expression or it could be a declaration.  Treat
+               ;; it as a declaration if "a" has been used as a type
+               ;; somewhere else (if it's a known type we won't get here).
+               (throw 'at-decl-or-cast t)))
+
+         (when (and context
+                    (or got-prefix
+                        (and (eq context 'decl)
+                             (not c-recognize-paren-inits)
+                             (or got-parens got-suffix))))
+           ;; Got a type followed by an abstract declarator.  If `got-prefix'
+           ;; is set it's something like "a *" without anything after it.  If
+           ;; `got-parens' or `got-suffix' is set it's "a()", "a[]", "a()[]",
+           ;; or similar, which we accept only if the context rules out
+           ;; expressions.
+           (throw 'at-decl-or-cast t)))
+
+       ;; If we had a complete symbol table here (which rules out
+       ;; `c-found-types') we should return t due to the disambiguation rule
+       ;; (in at least C++) that anything that can be parsed as a declaration
+       ;; is a declaration.  Now we're being more defensive and prefer to
+       ;; highlight things like "foo (bar);" as a declaration only if we're
+       ;; inside an arglist that contains declarations.
+       (eq context 'decl))))
+
+    ;; The point is now after the type decl expression.
+
+    (cond
+     ;; Check for a cast.
+     ((save-excursion
+       (and
+        c-cast-parens
+
+        ;; Should be the first type/identifier in a cast paren.
+        (> preceding-token-end (point-min))
+        (memq (char-before preceding-token-end) c-cast-parens)
+
+        ;; The closing paren should follow.
+        (progn
+          (c-forward-syntactic-ws)
+          (looking-at "\\s\)"))
+
+        ;; There should be a primary expression after it.
+        (let (pos)
+          (forward-char)
+          (c-forward-syntactic-ws)
+          (setq cast-end (point))
+          (and (looking-at c-primary-expr-regexp)
+               (progn
+                 (setq pos (match-end 0))
+                 (or
+                  ;; Check if the expression begins with a prefix keyword.
+                  (match-beginning 2)
+                  (if (match-beginning 1)
+                      ;; Expression begins with an ambiguous operator.  Treat
+                      ;; it as a cast if it's a type decl or if we've
+                      ;; recognized the type somewhere else.
+                      (or at-decl-or-cast
+                          (memq at-type '(t known found)))
+                    ;; Unless it's a keyword, it's the beginning of a primary
+                    ;; expression.
+                    (not (looking-at c-keywords-regexp)))))
+               ;; If `c-primary-expr-regexp' matched a nonsymbol token, check
+               ;; that it matched a whole one so that we don't e.g. confuse
+               ;; the operator '-' with '->'.  It's ok if it matches further,
+               ;; though, since it e.g. can match the float '.5' while the
+               ;; operator regexp only matches '.'.
+               (or (not (looking-at c-nonsymbol-token-regexp))
+                   (<= (match-end 0) pos))))
+
+        ;; There should either be a cast before it or something that isn't an
+        ;; identifier or close paren.
+        (> preceding-token-end (point-min))
+        (progn
+          (goto-char (1- preceding-token-end))
+          (or (eq (point) last-cast-end)
+              (progn
+                (c-backward-syntactic-ws)
+                (if (< (skip-syntax-backward "w_") 0)
+                    ;; It's a symbol.  Accept it only if it's one of the
+                    ;; keywords that can precede an expression (without
+                    ;; surrounding parens).
+                    (looking-at c-simple-stmt-key)
+                  (and
+                   ;; Check that it isn't a close paren (block close is ok,
+                   ;; though).
+                   (not (memq (char-before) '(?\) ?\])))
+                   ;; Check that it isn't a nonsymbol identifier.
+                   (not (c-on-identifier)))))))))
+
+      ;; Handle the cast.
+      (when (and c-record-type-identifiers at-type (not (eq at-type t)))
+       (let ((c-promote-possible-types t))
+         (goto-char type-start)
+         (c-forward-type)))
+
+      (goto-char cast-end)
+      'cast)
+
+     (at-decl-or-cast
+      ;; We're at a declaration.  Highlight the type and the following
+      ;; declarators.
+
+      (when backup-if-not-cast
+       (c-fdoc-shift-type-backward t))
+
+      (when (and (eq context 'decl) (looking-at ","))
+       ;; Make sure to propagate the `c-decl-arg-start' property to
+       ;; the next argument if it's set in this one, to cope with
+       ;; interactive refontification.
+       (c-put-c-type-property (point) 'c-decl-arg-start))
+
+      (when (and c-record-type-identifiers at-type (not (eq at-type t)))
+       (let ((c-promote-possible-types t))
+         (save-excursion
+           (goto-char type-start)
+           (c-forward-type))))
+
+      (cons id-start at-type-decl))
+
+     (t
+      ;; False alarm.  Restore the recorded ranges.
+      (setq c-record-type-identifiers save-rec-type-ids
+           c-record-ref-identifiers save-rec-ref-ids)
+      nil))))
+
+(defun c-forward-label (&optional assume-markup preceding-token-end limit)
+  ;; Assuming the point is at the beginning of a token, check if it
+  ;; starts a label and if so move over it and return t, otherwise
+  ;; don't move and return nil.  The end of the label is taken to be
+  ;; the end of the first submatch in `c-opt-extra-label-key' if it
+  ;; matched, otherwise it's the colon.  The point is directly after
+  ;; the end on return.  The terminating char is marked with
+  ;; `c-decl-end' to improve recognition of the following declaration
+  ;; or statement.
+  ;;
+  ;; If ASSUME-MARKUP is non-nil, it's assumed that the preceding
+  ;; label, if any, has been marked up like that.
+  ;;
+  ;; If PRECEDING-TOKEN-END is given, it should be the first position
+  ;; after the preceding token, i.e. on the other side of the
+  ;; syntactic ws from the point.  Use a value less than or equal to
+  ;; (point-min) if the point is at the first token in (the visible
+  ;; part of) the buffer.
+  ;;
+  ;; The optional LIMIT limits the forward scan for the colon.
+  ;;
+  ;; This function records the ranges of the label symbols on
+  ;; `c-record-ref-identifiers' if `c-record-type-identifiers' (!) is
+  ;; non-nil.
+  ;;
+  ;; This function might do hidden buffer changes.
+
+  (let ((start (point)))
+    (cond
+     ((looking-at c-label-kwds-regexp)
+      (let ((kwd-end (match-end 1)))
+       ;; Record only the keyword itself for fontification, since in
+       ;; case labels the following is a constant expression and not
+       ;; a label.
+       (when c-record-type-identifiers
+         (c-record-ref-id (cons (match-beginning 1) kwd-end)))
+
+       ;; Find the label end.
+       (goto-char kwd-end)
+       (if (and (c-syntactic-re-search-forward
+                 ;; Stop on chars that aren't allowed in expressions,
+                 ;; and on operator chars that would be meaningless
+                 ;; there.  FIXME: This doesn't cope with ?: operators.
+                 "[;{=,@]\\|\\(\\=\\|[^:]\\):\\([^:]\\|\\'\\)"
+                 limit t t nil 1)
+                (match-beginning 2))
+
+           (progn
+             (goto-char (match-beginning 2))
+             (c-put-c-type-property (1- (point)) 'c-decl-end)
+             t)
+
+         ;; It's an unfinished label.  We consider the keyword enough
+         ;; to recognize it as a label, so that it gets fontified.
+         ;; Leave the point at the end of it, but don't put any
+         ;; `c-decl-end' marker.
+         (goto-char kwd-end)
+         t)))
+
+     ((and c-opt-extra-label-key
+          (looking-at c-opt-extra-label-key))
+      ;; For a `c-opt-extra-label-key' match, we record the whole
+      ;; thing for fontification.  That's to get the leading '@' in
+      ;; Objective-C protection labels fontified.
+      (goto-char (match-end 1))
+      (when c-record-type-identifiers
+       (c-record-ref-id (cons (match-beginning 1) (point))))
+      (c-put-c-type-property (1- (point)) 'c-decl-end)
+      t)
+
+     ((and c-recognize-colon-labels
+
+          ;; A colon label must have something before the colon.
+          (not (eq (char-after) ?:))
+
+          ;; Check that we're not after a token that can't precede a label.
+          (or
+           ;; Trivially succeeds when there's no preceding token.
+           (if preceding-token-end
+               (<= preceding-token-end (point-min))
+             (save-excursion
+               (c-backward-syntactic-ws)
+               (setq preceding-token-end (point))
+               (bobp)))
+
+           ;; Check if we're after a label, if we're after a closing
+           ;; paren that belong to statement, and with
+           ;; `c-label-prefix-re'.  It's done in different order
+           ;; depending on `assume-markup' since the checks have
+           ;; different expensiveness.
+           (if assume-markup
+               (or
+                (eq (c-get-char-property (1- preceding-token-end) 'c-type)
+                    'c-decl-end)
+
+                (save-excursion
+                  (goto-char (1- preceding-token-end))
+                  (c-beginning-of-current-token)
+                  (looking-at c-label-prefix-re))
+
+                (and (eq (char-before preceding-token-end) ?\))
+                     (c-after-conditional)))
+
+             (or
+              (save-excursion
+                (goto-char (1- preceding-token-end))
+                (c-beginning-of-current-token)
+                (looking-at c-label-prefix-re))
+
+              (cond
+               ((eq (char-before preceding-token-end) ?\))
+                (c-after-conditional))
+
+               ((eq (char-before preceding-token-end) ?:)
+                ;; Might be after another label, so check it recursively.
+                (save-excursion
+                  (goto-char (1- preceding-token-end))
+                  ;; Essentially the same as the
+                  ;; `c-syntactic-re-search-forward' regexp below.
+                  (c-syntactic-skip-backward "^-]:?;}=*/%&|,<>!@+" nil t)
+                  (let ((pte (point))
+                        ;; If the caller turned on recording for us,
+                        ;; it shouldn't apply when we check the
+                        ;; preceding label.
+                        c-record-type-identifiers)
+                    (c-forward-syntactic-ws)
+                    (c-forward-label nil pte start))))))))
+
+          ;; Check that the next nonsymbol token is ":".  Allow '('
+          ;; for the sake of macro arguments.  FIXME: Should build
+          ;; this regexp from the language constants.
+          (c-syntactic-re-search-forward
+           "[[:?;{=*/%&|,<>!@+-]" limit t t)
+          (eq (char-before) ?:)
+          (not (eq (char-after) ?:)))
+
+      (save-restriction
+       (narrow-to-region start (point))
+
+       ;; Check that `c-nonlabel-token-key' doesn't match anywhere.
+       (catch 'check-label
+         (goto-char start)
+         (while (progn
+                  (when (looking-at c-nonlabel-token-key)
+                    (goto-char start)
+                    (throw 'check-label nil))
+                  (and (c-safe (c-forward-sexp)
+                               (c-forward-syntactic-ws)
+                               t)
+                       (not (eobp)))))
+
+         ;; Record the identifiers in the label for fontification, unless
+         ;; it begins with `c-label-kwds' in which case the following
+         ;; identifiers are part of a (constant) expression that
+         ;; shouldn't be fontified.
+         (when (and c-record-type-identifiers
+                    (progn (goto-char start)
+                           (not (looking-at c-label-kwds-regexp))))
+           (while (c-syntactic-re-search-forward c-symbol-key nil t)
+             (c-record-ref-id (cons (match-beginning 0)
+                                    (match-end 0)))))
+
+         (c-put-c-type-property (1- (point-max)) 'c-decl-end)
+         (goto-char (point-max))
+         t)))
+
+     (t
+      ;; Not a label.
+      (goto-char start)
+      nil))))
+
+(defun c-forward-objc-directive ()
+  ;; Assuming the point is at the beginning of a token, try to move
+  ;; forward to the end of the Objective-C directive that starts
+  ;; there.  Return t if a directive was fully recognized, otherwise
+  ;; the point is moved as far as one could be successfully parsed and
+  ;; nil is returned.
+  ;;
+  ;; This function records identifier ranges on
+  ;; `c-record-type-identifiers' and `c-record-ref-identifiers' if
+  ;; `c-record-type-identifiers' is non-nil.
+  ;;
+  ;; This function might do hidden buffer changes.
+
+    (let ((start (point))
+         start-char
+         (c-promote-possible-types t)
+         ;; Turn off recognition of angle bracket arglists while parsing
+         ;; types here since the protocol reference list might then be
+         ;; considered part of the preceding name or superclass-name.
+         c-recognize-<>-arglists)
+
+      (if (or
+          (when (looking-at
+                 (eval-when-compile
+                   (c-make-keywords-re t
+                     (append (c-lang-const c-protection-kwds objc)
+                             '("@end"))
+                     'objc-mode)))
+            (goto-char (match-end 1))
+            t)
+
+          (and
+           (looking-at
+            (eval-when-compile
+              (c-make-keywords-re t
+                '("@interface" "@implementation" "@protocol")
+                'objc-mode)))
+
+           ;; Handle the name of the class itself.
+           (progn
+             (c-forward-token-2)
+             (c-forward-type))
+
+           (catch 'break
+             ;; Look for ": superclass-name" or "( category-name )".
+             (when (looking-at "[:\(]")
+               (setq start-char (char-after))
+               (forward-char)
+               (c-forward-syntactic-ws)
+               (unless (c-forward-type) (throw 'break nil))
+               (when (eq start-char ?\()
+                 (unless (eq (char-after) ?\)) (throw 'break nil))
+                 (forward-char)
+                 (c-forward-syntactic-ws)))
+
+             ;; Look for a protocol reference list.
+             (if (eq (char-after) ?<)
+                 (let ((c-recognize-<>-arglists t)
+                       (c-parse-and-markup-<>-arglists t)
+                       c-restricted-<>-arglists)
+                   (c-forward-<>-arglist t))
+               t))))
+
+         (progn
+           (c-backward-syntactic-ws)
+           (c-clear-c-type-property start (1- (point)) 'c-decl-end)
+           (c-put-c-type-property (1- (point)) 'c-decl-end)
+           t)
+
+       (c-clear-c-type-property start (point) 'c-decl-end)
+       nil)))
+
 (defun c-beginning-of-inheritance-list (&optional lim)
   ;; Go to the first non-whitespace after the colon that starts a
   ;; multiple inheritance introduction.  Optional LIM is the farthest
   ;; back we should search.
-  (let* ((lim (or lim (save-excursion
-                       (c-beginning-of-syntax)
-                       (point)))))
-    (c-with-syntax-table c++-template-syntax-table
-      (c-backward-token-2 0 t lim)
-      (while (and (or (looking-at c-symbol-start)
-                     (looking-at "[<,]\\|::"))
-                 (zerop (c-backward-token-2 1 t lim))))
-      (skip-chars-forward "^:"))))
+  ;;
+  ;; This function might do hidden buffer changes.
+  (c-with-syntax-table c++-template-syntax-table
+    (c-backward-token-2 0 t lim)
+    (while (and (or (looking-at c-symbol-start)
+                   (looking-at "[<,]\\|::"))
+               (zerop (c-backward-token-2 1 t lim))))))
 
 (defun c-in-method-def-p ()
   ;; Return nil if we aren't in a method definition, otherwise the
   ;; position of the initial [+-].
+  ;;
+  ;; This function might do hidden buffer changes.
   (save-excursion
     (beginning-of-line)
     (and c-opt-method-key
@@ -4327,6 +6055,8 @@ This function does not do any hidden buffer changes."
   ;; Only one level of enclosing parentheses is considered, so for
   ;; instance `nil' is returned when in a function call within an asm
   ;; operand.
+  ;;
+  ;; This function might do hidden buffer changes.
 
   (and c-opt-asm-stmt-key
        (save-excursion
@@ -4347,79 +6077,65 @@ top-level not enclosed within a class definition, t is returned.
 Otherwise, a 2-vector is returned where the zeroth element is the
 buffer position of the start of the class declaration, and the first
 element is the buffer position of the enclosing class's opening
-brace."
+brace.
+
+Note that this function might do hidden buffer changes.  See the
+comment at the start of cc-engine.el for more info."
   (let ((paren-state (c-parse-state)))
     (or (not (c-most-enclosing-brace paren-state))
        (c-search-uplist-for-classkey paren-state))))
 
 (defun c-just-after-func-arglist-p (&optional lim)
-  ;; Return non-nil if we are between a function's argument list closing
-  ;; paren and its opening brace.  Note that the list close brace
-  ;; could be followed by a "const" specifier or a member init hanging
-  ;; colon.  LIM is used as bound for some backward buffer searches;
-  ;; the search might continue past it.
+  ;; Return non-nil if the point is in the region after the argument
+  ;; list of a function and its opening brace (or semicolon in case it
+  ;; got no body).  If there are K&R style argument declarations in
+  ;; that region, the point has to be inside the first one for this
+  ;; function to recognize it.
   ;;
-  ;; Note: This test is easily fooled.  It only works reasonably well
-  ;; in the situations where `c-guess-basic-syntax' uses it.
-  (save-excursion
-    (if (c-mode-is-new-awk-p)
-        (c-awk-backward-syntactic-ws lim)
-      (c-backward-syntactic-ws lim))
-    (let ((checkpoint (point)))
-      ;; could be looking at const specifier
-      (if (and (eq (char-before) ?t)
-              (forward-word -1)
-              (looking-at "\\<const\\>[^_]"))
-         (c-backward-syntactic-ws lim)
-       ;; otherwise, we could be looking at a hanging member init
-       ;; colon
-       (goto-char checkpoint)
-       (while (and
-               (eq (char-before) ?,)
-               ;; this will catch member inits with multiple
-               ;; line arglists
-               (progn
-                 (forward-char -1)
-                 (c-backward-syntactic-ws (c-point 'bol))
-                 (c-safe (c-backward-sexp 1) t))
-               (or (not (looking-at "\\s\("))
-                   (c-safe (c-backward-sexp 1) t)))
-         (c-backward-syntactic-ws lim))
-       (if (and (eq (char-before) ?:)
-                (progn
-                  (forward-char -1)
-                  (c-backward-syntactic-ws lim)
-                  (looking-at "\\([ \t\n]\\|\\\\\n\\)*:\\([^:]+\\|$\\)")))
-           nil
-         (goto-char checkpoint))
-       )
-      (setq checkpoint (point))
-      (and (eq (char-before) ?\))
-          ;; Check that it isn't a cpp expression, e.g. the
-          ;; expression of an #if directive or the "function header"
-          ;; of a #define.
-          (or (not (c-beginning-of-macro))
-              (and (c-forward-to-cpp-define-body)
-                   (< (point) checkpoint)))
-          ;; Check if we are looking at an ObjC method def or a class
-          ;; category.
-          (not (and c-opt-method-key
-                    (progn
-                      (goto-char checkpoint)
-                      (c-safe (c-backward-sexp) t))
-                    (progn
-                      (c-backward-syntactic-ws lim)
-                      (or (memq (char-before) '(?- ?+))
-                          (and (c-safe (c-forward-sexp -2) t)
-                               (looking-at c-class-key))))))
-          ;; Pike has compound types that include parens,
-          ;; e.g. "array(string)".  Check that we aren't after one.
-          (not (and (c-major-mode-is 'pike-mode)
-                    (progn
-                      (goto-char checkpoint)
-                      (c-safe (c-backward-sexp 2) t))
-                    (looking-at c-primitive-type-key)))
-          ))))
+  ;; If successful, the point is moved to the first token after the
+  ;; function header (see `c-forward-decl-or-cast-1' for details) and
+  ;; the position of the opening paren of the function arglist is
+  ;; returned.
+  ;;
+  ;; The point is clobbered if not successful.
+  ;;
+  ;; LIM is used as bound for backward buffer searches.
+  ;;
+  ;; This function might do hidden buffer changes.
+
+  (let ((beg (point)) end id-start)
+    (and
+     (eq (c-beginning-of-statement-1 lim) 'same)
+
+     (not (or (c-major-mode-is 'objc-mode)
+             (c-forward-objc-directive)))
+
+     (setq id-start
+          (car-safe (c-forward-decl-or-cast-1 (c-point 'bosws) nil nil)))
+     (< id-start beg)
+
+     ;; There should not be a '=' or ',' between beg and the
+     ;; start of the declaration since that means we were in the
+     ;; "expression part" of the declaration.
+     (or (> (point) beg)
+        (not (looking-at "[=,]")))
+
+     (save-excursion
+       ;; Check that there's an arglist paren in the
+       ;; declaration.
+       (goto-char id-start)
+       (cond ((eq (char-after) ?\()
+             ;; The declarator is a paren expression, so skip past it
+             ;; so that we don't get stuck on that instead of the
+             ;; function arglist.
+             (c-forward-sexp))
+            ((and c-opt-op-identitier-prefix
+                  (looking-at c-opt-op-identitier-prefix))
+             ;; Don't trip up on "operator ()".
+             (c-forward-token-2 2 t)))
+       (and (< (point) beg)
+           (c-syntactic-re-search-forward "(" beg t t)
+           (1- (point)))))))
 
 (defun c-in-knr-argdecl (&optional lim)
   ;; Return the position of the first argument declaration if point is
@@ -4429,6 +6145,8 @@ brace."
   ;;
   ;; Note: A declaration level context is assumed; the test can return
   ;; false positives for statements.
+  ;;
+  ;; This function might do hidden buffer changes.
 
   (save-excursion
     (save-restriction
@@ -4488,6 +6206,8 @@ brace."
 (defun c-skip-conditional ()
   ;; skip forward over conditional at point, including any predicate
   ;; statements in parentheses. No error checking is performed.
+  ;;
+  ;; This function might do hidden buffer changes.
   (c-forward-sexp (cond
                   ;; else if()
                   ((looking-at (concat "\\<else"
@@ -4505,6 +6225,8 @@ brace."
 (defun c-after-conditional (&optional lim)
   ;; If looking at the token after a conditional then return the
   ;; position of its start, otherwise return nil.
+  ;;
+  ;; This function might do hidden buffer changes.
   (save-excursion
     (and (zerop (c-backward-token-2 1 t lim))
         (or (looking-at c-block-stmt-1-key)
@@ -4513,12 +6235,32 @@ brace."
                  (looking-at c-block-stmt-2-key)))
         (point))))
 
+(defun c-after-special-operator-id (&optional lim)
+  ;; If the point is after an operator identifier that isn't handled
+  ;; like an ordinary symbol (i.e. like "operator =" in C++) then the
+  ;; position of the start of that identifier is returned.  nil is
+  ;; returned otherwise.  The point may be anywhere in the syntactic
+  ;; whitespace after the last token of the operator identifier.
+  ;;
+  ;; This function might do hidden buffer changes.
+  (save-excursion
+    (and c-overloadable-operators-regexp
+        (zerop (c-backward-token-2 1 nil lim))
+        (looking-at c-overloadable-operators-regexp)
+        (or (not c-opt-op-identitier-prefix)
+            (and
+             (zerop (c-backward-token-2 1 nil lim))
+             (looking-at c-opt-op-identitier-prefix)))
+        (point))))
+
 (defsubst c-backward-to-block-anchor (&optional lim)
   ;; Assuming point is at a brace that opens a statement block of some
   ;; kind, move to the proper anchor point for that block.  It might
   ;; need to be adjusted further by c-add-stmt-syntax, but the
   ;; position at return is suitable as start position for that
   ;; function.
+  ;;
+  ;; This function might do hidden buffer changes.
   (unless (= (point) (c-point 'boi))
     (let ((start (c-after-conditional lim)))
       (if start
@@ -4528,6 +6270,8 @@ brace."
   ;; Assuming point is at a brace that opens the block of a top level
   ;; declaration of some kind, move to the proper anchor point for
   ;; that block.
+  ;;
+  ;; This function might do hidden buffer changes.
   (unless (= (point) (c-point 'boi))
     (c-beginning-of-statement-1 lim)))
 
@@ -4538,6 +6282,8 @@ brace."
   ;; semicolon.  I.e. search forward for the closest following
   ;; (syntactically relevant) '{', '=' or ';' token.  Point is left
   ;; _after_ the first found token, or at point-max if none is found.
+  ;;
+  ;; This function might do hidden buffer changes.
 
   (let ((base (point)))
     (if (c-major-mode-is 'c++-mode)
@@ -4552,7 +6298,7 @@ brace."
                 ;; operator token preceded by "operator".
                 (save-excursion
                   (and (c-safe (c-backward-sexp) t)
-                       (looking-at "operator\\>\\([^_]\\|$\\)")))
+                       (looking-at c-opt-op-identitier-prefix)))
                 (and (eq (char-before) ?<)
                      (c-with-syntax-table c++-template-syntax-table
                        (if (c-safe (goto-char (c-up-list-forward (point))))
@@ -4569,7 +6315,7 @@ brace."
 (defun c-beginning-of-decl-1 (&optional lim)
   ;; Go to the beginning of the current declaration, or the beginning
   ;; of the previous one if already at the start of it.  Point won't
-  ;; be moved out of any surrounding paren.  Return a cons cell on the
+  ;; be moved out of any surrounding paren.  Return a cons cell of the
   ;; form (MOVE . KNR-POS).  MOVE is like the return value from
   ;; `c-beginning-of-statement-1'.  If point skipped over some K&R
   ;; style argument declarations (and they are to be recognized) then
@@ -4580,10 +6326,12 @@ brace."
   ;; NB: Cases where the declaration continues after the block, as in
   ;; "struct foo { ... } bar;", are currently recognized as two
   ;; declarations, e.g. "struct foo { ... }" and "bar;" in this case.
+  ;;
+  ;; This function might do hidden buffer changes.
   (catch 'return
     (let* ((start (point))
           (last-stmt-start (point))
-          (move (c-beginning-of-statement-1 lim t t)))
+          (move (c-beginning-of-statement-1 lim nil t)))
 
       ;; `c-beginning-of-statement-1' stops at a block start, but we
       ;; want to continue if the block doesn't begin a top level
@@ -4604,7 +6352,7 @@ brace."
                ;; Check that we don't move from the first thing in a
                ;; macro to its header.
                (not (eq (setq tentative-move
-                              (c-beginning-of-statement-1 lim t t))
+                              (c-beginning-of-statement-1 lim nil t))
                         'macro)))
          (setq last-stmt-start beg
                beg (point)
@@ -4625,7 +6373,7 @@ brace."
                   (< knr-argdecl-start start)
                   (progn
                     (goto-char knr-argdecl-start)
-                    (not (eq (c-beginning-of-statement-1 lim t t) 'macro))))
+                    (not (eq (c-beginning-of-statement-1 lim nil t) 'macro))))
              (throw 'return
                     (cons (if (eq (char-after fallback-pos) ?{)
                               'previous
@@ -4633,17 +6381,6 @@ brace."
                           knr-argdecl-start))
            (goto-char fallback-pos))))
 
-      (when c-opt-access-key
-       ;; Might have ended up before a protection label.  This should
-       ;; perhaps be checked before `c-recognize-knr-p' to be really
-       ;; accurate, but we know that no language has both.
-       (while (looking-at c-opt-access-key)
-         (goto-char (match-end 0))
-         (c-forward-syntactic-ws)
-         (when (>= (point) start)
-           (goto-char start)
-           (throw 'return (cons 'same nil)))))
-
       ;; `c-beginning-of-statement-1' counts each brace block as a
       ;; separate statement, so the result will be 'previous if we've
       ;; moved over any.  If they were brace list initializers we might
@@ -4675,6 +6412,8 @@ brace."
   ;; point is moved as far as possible within the current sexp and nil
   ;; is returned.  This function doesn't handle macros; use
   ;; `c-end-of-macro' instead in those cases.
+  ;;
+  ;; This function might do hidden buffer changes.
   (let ((start (point))
        (decl-syntax-table (if (c-major-mode-is 'c++-mode)
                               c++-template-syntax-table
@@ -4729,178 +6468,171 @@ brace."
                 (c-syntactic-re-search-forward ";" nil 'move t))))
       nil)))
 
-(defun c-beginning-of-member-init-list (&optional limit)
-  ;; Go to the beginning of a member init list (i.e. just after the
-  ;; ':') if inside one.  Returns t in that case, nil otherwise.
-  (or limit
-      (setq limit (point-min)))
-  (skip-chars-forward " \t")
-
-  (if (eq (char-after) ?,)
-      (forward-char 1)
-    (c-backward-syntactic-ws limit))
-
-  (catch 'exit
-    (while (and (< limit (point))
-               (eq (char-before) ?,))
-
-      ;; this will catch member inits with multiple
-      ;; line arglists
-      (forward-char -1)
-      (c-backward-syntactic-ws limit)
-      (if (eq (char-before) ?\))
-         (unless (c-safe (c-backward-sexp 1))
-           (throw 'exit nil)))
-      (c-backward-syntactic-ws limit)
-
-      ;; Skip over any template arg to the class.  This way with a
-      ;; syntax table is bogus but it'll have to do for now.
-      (if (and (eq (char-before) ?>)
-              (c-major-mode-is 'c++-mode))
-         (c-with-syntax-table c++-template-syntax-table
-           (unless (c-safe (c-backward-sexp 1))
-             (throw 'exit nil))))
-      (c-safe (c-backward-sexp 1))
-      (c-backward-syntactic-ws limit)
-
-      ;; Skip backwards over a fully::qualified::name.
-      (while (and (eq (char-before) ?:)
-                 (save-excursion
-                   (forward-char -1)
-                   (eq (char-before) ?:)))
-       (backward-char 2)
-       (c-safe (c-backward-sexp 1)))
-
-      ;; If we've stepped over a number then this is a bitfield.
-      (when (and c-opt-bitfield-key
-                (looking-at "[0-9]"))
-       (throw 'exit nil))
-
-      ;; now continue checking
-      (c-backward-syntactic-ws limit))
-
-    (and (< limit (point))
-        (eq (char-before) ?:))))
+(defun c-looking-at-decl-block (containing-sexp goto-start &optional limit)
+  ;; Assuming the point is at an open brace, check if it starts a
+  ;; block that contains another declaration level, i.e. that isn't a
+  ;; statement block or a brace list, and if so return non-nil.
+  ;;
+  ;; If the check is successful, the return value is the start of the
+  ;; keyword that tells what kind of construct it is, i.e. typically
+  ;; what `c-decl-block-key' matched.  Also, if GOTO-START is set then
+  ;; the point will be at the start of the construct, before any
+  ;; leading specifiers, otherwise it's at the returned position.
+  ;;
+  ;; The point is clobbered if the check is unsuccessful.
+  ;;
+  ;; CONTAINING-SEXP is the position of the open of the surrounding
+  ;; paren, or nil if none.
+  ;;
+  ;; The optional LIMIT limits the backward search for the start of
+  ;; the construct.  It's assumed to be at a syntactically relevant
+  ;; position.
+  ;;
+  ;; If any template arglists are found in the searched region before
+  ;; the open brace, they get marked with paren syntax.
+  ;;
+  ;; This function might do hidden buffer changes.
+
+  (let ((open-brace (point)) kwd-start first-specifier-pos)
+    (c-syntactic-skip-backward c-block-prefix-charset limit t)
+
+    (when (and c-recognize-<>-arglists
+              (eq (char-before) ?>))
+      ;; Could be at the end of a template arglist.
+      (let ((c-parse-and-markup-<>-arglists t)
+           (c-disallow-comma-in-<>-arglists
+            (and containing-sexp
+                 (not (eq (char-after containing-sexp) ?{)))))
+       (while (and
+               (c-backward-<>-arglist nil limit)
+               (progn
+                 (c-syntactic-skip-backward c-block-prefix-charset limit t)
+                 (eq (char-before) ?>))))))
+
+    ;; Note: Can't get bogus hits inside template arglists below since they
+    ;; have gotten paren syntax above.
+    (when (and
+          ;; If `goto-start' is set we begin by searching for the
+          ;; first possible position of a leading specifier list.
+          ;; The `c-decl-block-key' search continues from there since
+          ;; we know it can't match earlier.
+          (if goto-start
+              (when (c-syntactic-re-search-forward c-symbol-start
+                                                   open-brace t t)
+                (goto-char (setq first-specifier-pos (match-beginning 0)))
+                t)
+            t)
+
+          (cond
+           ((c-syntactic-re-search-forward c-decl-block-key open-brace t t t)
+            (goto-char (setq kwd-start (match-beginning 0)))
+            (or
+
+             ;; Found a keyword that can't be a type?
+             (match-beginning 1)
+
+             ;; Can be a type too, in which case it's the return type of a
+             ;; function (under the assumption that no declaration level
+             ;; block construct starts with a type).
+             (not (c-forward-type))
+
+             ;; Jumped over a type, but it could be a declaration keyword
+             ;; followed by the declared identifier that we've jumped over
+             ;; instead (e.g. in "class Foo {").  If it indeed is a type
+             ;; then we should be at the declarator now, so check for a
+             ;; valid declarator start.
+             ;;
+             ;; Note: This doesn't cope with the case when a declared
+             ;; identifier is followed by e.g. '(' in a language where '('
+             ;; also might be part of a declarator expression.  Currently
+             ;; there's no such language.
+             (not (or (looking-at c-symbol-start)
+                      (looking-at c-type-decl-prefix-key)))))
+
+           ;; In Pike a list of modifiers may be followed by a brace
+           ;; to make them apply to many identifiers.  Note that the
+           ;; match data will be empty on return in this case.
+           ((and (c-major-mode-is 'pike-mode)
+                 (progn
+                   (goto-char open-brace)
+                   (= (c-backward-token-2) 0))
+                 (looking-at c-specifier-key)
+                 ;; Use this variant to avoid yet another special regexp.
+                 (c-keyword-member (c-keyword-sym (match-string 1))
+                                   'c-modifier-kwds))
+            (setq kwd-start (point))
+            t)))
+
+      ;; Got a match.
+
+      (if goto-start
+         ;; Back up over any preceding specifiers and their clauses
+         ;; by going forward from `first-specifier-pos', which is the
+         ;; earliest possible position where the specifier list can
+         ;; start.
+         (progn
+           (goto-char first-specifier-pos)
+
+           (while (< (point) kwd-start)
+             (if (looking-at c-symbol-key)
+                 ;; Accept any plain symbol token on the ground that
+                 ;; it's a specifier masked through a macro (just
+                 ;; like `c-forward-decl-or-cast-1' skip forward over
+                 ;; such tokens).
+                 ;;
+                 ;; Could be more restrictive wrt invalid keywords,
+                 ;; but that'd only occur in invalid code so there's
+                 ;; no use spending effort on it.
+                 (let ((end (match-end 0)))
+                   (unless (c-forward-keyword-clause 0)
+                     (goto-char end)
+                     (c-forward-syntactic-ws)))
+
+               ;; Can't parse a declaration preamble and is still
+               ;; before `kwd-start'.  That means `first-specifier-pos'
+               ;; was in some earlier construct.  Search again.
+               (if (c-syntactic-re-search-forward c-symbol-start
+                                                  kwd-start 'move t)
+                   (goto-char (setq first-specifier-pos (match-beginning 0)))
+                 ;; Got no preamble before the block declaration keyword.
+                 (setq first-specifier-pos kwd-start))))
+
+           (goto-char first-specifier-pos))
+       (goto-char kwd-start))
+
+      kwd-start)))
 
 (defun c-search-uplist-for-classkey (paren-state)
-  ;; search for the containing class, returning a 2 element vector if
-  ;; found. aref 0 contains the bufpos of the boi of the class key
-  ;; line, and aref 1 contains the bufpos of the open brace.
-  (if (null paren-state)
-      ;; no paren-state means we cannot be inside a class
-      nil
-    (let ((carcache (car paren-state))
-         search-start search-end)
-      (if (consp carcache)
-         ;; a cons cell in the first element means that there is some
-         ;; balanced sexp before the current bufpos. this we can
-         ;; ignore. the nth 1 and nth 2 elements define for us the
-         ;; search boundaries
-         (setq search-start (nth 2 paren-state)
-               search-end (nth 1 paren-state))
-       ;; if the car was not a cons cell then nth 0 and nth 1 define
-       ;; for us the search boundaries
-       (setq search-start (nth 1 paren-state)
-             search-end (nth 0 paren-state)))
-      ;; if search-end is nil, or if the search-end character isn't an
-      ;; open brace, we are definitely not in a class
-      (if (or (not search-end)
-             (< search-end (point-min))
-             (not (eq (char-after search-end) ?{)))
-         nil
-       ;; now, we need to look more closely at search-start.  if
-       ;; search-start is nil, then our start boundary is really
-       ;; point-min.
-       (if (not search-start)
-           (setq search-start (point-min))
-         ;; if search-start is a cons cell, then we can start
-         ;; searching from the end of the balanced sexp just ahead of
-         ;; us
-         (if (consp search-start)
-             (setq search-start (cdr search-start))
-           ;; Otherwise we start searching within the surrounding paren sexp.
-           (setq search-start (1+ search-start))))
-       ;; now we can do a quick regexp search from search-start to
-       ;; search-end and see if we can find a class key.  watch for
-       ;; class like strings in literals
-       (save-excursion
-         (save-restriction
-           (goto-char search-start)
-           (let (foundp class match-end)
-             (while (and (not foundp)
-                         (progn
-                           (c-forward-syntactic-ws search-end)
-                           (> search-end (point)))
-                         ;; Add one to the search limit, to allow
-                         ;; matching of the "{" in the regexp.
-                         (re-search-forward c-decl-block-key
-                                            (1+ search-end)
-                                            t))
-               (setq class (match-beginning 0)
-                     match-end (match-end 0))
-               (goto-char class)
-               (if (c-in-literal search-start)
-                   (goto-char match-end) ; its in a comment or string, ignore
-                 (c-skip-ws-forward)
-                 (setq foundp (vector (c-point 'boi) search-end))
-                 (cond
-                  ;; check for embedded keywords
-                  ((let ((char (char-after (1- class))))
-                     (and char
-                          (memq (char-syntax char) '(?w ?_))))
-                   (goto-char match-end)
-                   (setq foundp nil))
-                  ;; make sure we're really looking at the start of a
-                  ;; class definition, and not an ObjC method.
-                  ((and c-opt-method-key
-                        (re-search-forward c-opt-method-key search-end t)
-                        (not (c-in-literal class)))
-                   (setq foundp nil))
-                  ;; Check if this is an anonymous inner class.
-                  ((and c-opt-inexpr-class-key
-                        (looking-at c-opt-inexpr-class-key))
-                   (while (and (zerop (c-forward-token-2 1 t))
-                               (looking-at "(\\|\\w\\|\\s_\\|\\.")))
-                   (if (eq (point) search-end)
-                       ;; We're done.  Just trap this case in the cond.
-                       nil
-                     ;; False alarm; all conditions aren't satisfied.
-                     (setq foundp nil)))
-                  ;; Its impossible to define a regexp for this, and
-                  ;; nearly so to do it programmatically.
-                  ;;
-                  ;; ; picks up forward decls
-                  ;; = picks up init lists
-                  ;; ) picks up return types
-                  ;; > picks up templates, but remember that we can
-                  ;;   inherit from templates!
-                  ((let ((skipchars "^;=)"))
-                     ;; try to see if we found the `class' keyword
-                     ;; inside a template arg list
-                     (save-excursion
-                       (skip-chars-backward "^<>" search-start)
-                       (if (eq (char-before) ?<)
-                           (setq skipchars (concat skipchars ">"))))
-                     (while (progn
-                              (skip-chars-forward skipchars search-end)
-                              (c-in-literal class))
-                       (forward-char))
-                     (/= (point) search-end))
-                   (setq foundp nil))
-                  )))
-             foundp))
-         )))))
+  ;; Check if the closest containing paren sexp is a declaration
+  ;; block, returning a 2 element vector in that case.  Aref 0
+  ;; contains the bufpos at boi of the class key line, and aref 1
+  ;; contains the bufpos of the open brace.  This function is an
+  ;; obsolete wrapper for `c-looking-at-decl-block'.
+  ;;
+  ;; This function might do hidden buffer changes.
+  (let ((open-paren-pos (c-most-enclosing-brace paren-state)))
+    (when open-paren-pos
+      (save-excursion
+       (goto-char open-paren-pos)
+       (when (and (eq (char-after) ?{)
+                  (c-looking-at-decl-block
+                   (c-safe-position open-paren-pos paren-state)
+                   nil))
+         (back-to-indentation)
+         (vector (point) open-paren-pos))))))
 
 (defun c-inside-bracelist-p (containing-sexp paren-state)
   ;; return the buffer position of the beginning of the brace list
   ;; statement if we're inside a brace list, otherwise return nil.
   ;; CONTAINING-SEXP is the buffer pos of the innermost containing
-  ;; paren.  BRACE-STATE is the remainder of the state of enclosing
+  ;; paren.  PAREN-STATE is the remainder of the state of enclosing
   ;; braces
   ;;
   ;; N.B.: This algorithm can potentially get confused by cpp macros
-  ;; places in inconvenient locations.  Its a trade-off we make for
+  ;; placed in inconvenient locations.  It's a trade-off we make for
   ;; speed.
+  ;;
+  ;; This function might do hidden buffer changes.
   (or
    ;; This will pick up brace list declarations.
    (c-safe
@@ -4977,7 +6709,9 @@ brace."
                        (setq braceassignp
                              (cond
                               ;; Check for operator =
-                              ((looking-at "operator\\>[^_]") nil)
+                              ((and c-opt-op-identitier-prefix
+                                    (looking-at c-opt-op-identitier-prefix))
+                               nil)
                               ;; Check for `<opchar>= in Pike.
                               ((and (c-major-mode-is 'pike-mode)
                                     (or (eq (char-after) ?`)
@@ -5033,6 +6767,8 @@ brace."
   ;; matching closer, but assumes it's correct if no balanced paren is
   ;; found (i.e. the case `({ ... } ... )' is detected as _not_ being
   ;; a special brace list).
+  ;;
+  ;; This function might do hidden buffer changes.
   (if c-special-brace-lists
       (condition-case ()
          (save-excursion
@@ -5087,82 +6823,103 @@ brace."
 (defun c-looking-at-bos (&optional lim)
   ;; Return non-nil if between two statements or declarations, assuming
   ;; point is not inside a literal or comment.
-  (save-excursion
-    (c-backward-syntactic-ws lim)
-    (or (bobp)
-       ;; Return t if at the start inside some parenthesis expression
-       ;; too, to catch macros that have statements as arguments.
-       (memq (char-before) '(?\; ?} ?\())
-       (and (eq (char-before) ?{)
-            (not (and c-special-brace-lists
-                      (progn (backward-char)
-                             (c-looking-at-special-brace-list))))))))
-
-(defun c-looking-at-inexpr-block (lim containing-sexp)
-  ;; Returns non-nil if we're looking at the beginning of a block
+  ;;
+  ;; Obsolete - `c-at-statement-start-p' or `c-at-expression-start-p'
+  ;; are recommended instead.
+  ;;
+  ;; This function might do hidden buffer changes.
+  (c-at-statement-start-p))
+(make-obsolete 'c-looking-at-bos 'c-at-statement-start-p)
+
+(defun c-looking-at-inexpr-block (lim containing-sexp &optional check-at-end)
+  ;; Return non-nil if we're looking at the beginning of a block
   ;; inside an expression.  The value returned is actually a cons of
   ;; either 'inlambda, 'inexpr-statement or 'inexpr-class and the
-  ;; position of the beginning of the construct.  LIM limits the
-  ;; backward search.  CONTAINING-SEXP is the start position of the
-  ;; closest containing list.  If it's nil, the containing paren isn't
-  ;; used to decide whether we're inside an expression or not.  If
-  ;; both LIM and CONTAINING-SEXP is used, LIM needs to be farther
-  ;; back.
+  ;; position of the beginning of the construct.
+  ;;
+  ;; LIM limits the backward search.  CONTAINING-SEXP is the start
+  ;; position of the closest containing list.  If it's nil, the
+  ;; containing paren isn't used to decide whether we're inside an
+  ;; expression or not.  If both LIM and CONTAINING-SEXP are used, LIM
+  ;; needs to be farther back.
+  ;;
+  ;; If CHECK-AT-END is non-nil then extra checks at the end of the
+  ;; brace block might be done.  It should only be used when the
+  ;; construct can be assumed to be complete, i.e. when the original
+  ;; starting position was further down than that.
+  ;;
+  ;; This function might do hidden buffer changes.
+
   (save-excursion
-    (let ((res 'maybe) passed-bracket
+    (let ((res 'maybe) passed-paren
          (closest-lim (or containing-sexp lim (point-min)))
          ;; Look at the character after point only as a last resort
          ;; when we can't disambiguate.
          (block-follows (and (eq (char-after) ?{) (point))))
+
       (while (and (eq res 'maybe)
                  (progn (c-backward-syntactic-ws)
                         (> (point) closest-lim))
                  (not (bobp))
                  (progn (backward-char)
                         (looking-at "[\]\).]\\|\\w\\|\\s_"))
-                 (progn (forward-char)
-                        (goto-char (scan-sexps (point) -1))))
+                 (c-safe (forward-char)
+                         (goto-char (scan-sexps (point) -1))))
+
        (setq res
-             (cond
-              ((and block-follows
-                    c-opt-inexpr-class-key
-                    (looking-at c-opt-inexpr-class-key))
-               (and (not passed-bracket)
-                    (or (not (looking-at c-class-key))
-                        ;; If the class definition is at the start of
-                        ;; a statement, we don't consider it an
-                        ;; in-expression class.
-                        (let ((prev (point)))
-                          (while (and
-                                  (= (c-backward-token-2 1 nil closest-lim) 0)
-                                  (eq (char-syntax (char-after)) ?w))
-                            (setq prev (point)))
-                          (goto-char prev)
-                          (not (c-looking-at-bos)))
-                        ;; Also, in Pike we treat it as an
-                        ;; in-expression class if it's used in an
-                        ;; object clone expression.
-                        (save-excursion
-                          (and (c-major-mode-is 'pike-mode)
-                               (progn (goto-char block-follows)
-                                      (zerop (c-forward-token-2 1 t)))
-                               (eq (char-after) ?\())))
-                    (cons 'inexpr-class (point))))
-              ((and c-opt-inexpr-block-key
-                    (looking-at c-opt-inexpr-block-key))
-               (cons 'inexpr-statement (point)))
-              ((and c-opt-lambda-key
-                    (looking-at c-opt-lambda-key))
-               (cons 'inlambda (point)))
-              ((and c-opt-block-stmt-key
-                    (looking-at c-opt-block-stmt-key))
-               nil)
-              (t
-               (if (eq (char-after) ?\[)
-                   (setq passed-bracket t))
-               'maybe))))
+             (if (looking-at c-keywords-regexp)
+                 (let ((kw-sym (c-keyword-sym (match-string 1))))
+                   (cond
+                    ((and block-follows
+                          (c-keyword-member kw-sym 'c-inexpr-class-kwds))
+                     (and (not (eq passed-paren ?\[))
+                          (or (not (looking-at c-class-key))
+                              ;; If the class definition is at the start of
+                              ;; a statement, we don't consider it an
+                              ;; in-expression class.
+                              (let ((prev (point)))
+                                (while (and
+                                        (= (c-backward-token-2 1 nil closest-lim) 0)
+                                        (eq (char-syntax (char-after)) ?w))
+                                  (setq prev (point)))
+                                (goto-char prev)
+                                (not (c-at-statement-start-p)))
+                              ;; Also, in Pike we treat it as an
+                              ;; in-expression class if it's used in an
+                              ;; object clone expression.
+                              (save-excursion
+                                (and check-at-end
+                                     (c-major-mode-is 'pike-mode)
+                                     (progn (goto-char block-follows)
+                                            (zerop (c-forward-token-2 1 t)))
+                                     (eq (char-after) ?\())))
+                          (cons 'inexpr-class (point))))
+                    ((c-keyword-member kw-sym 'c-inexpr-block-kwds)
+                     (when (not passed-paren)
+                       (cons 'inexpr-statement (point))))
+                    ((c-keyword-member kw-sym 'c-lambda-kwds)
+                     (when (or (not passed-paren)
+                               (eq passed-paren ?\())
+                       (cons 'inlambda (point))))
+                    ((c-keyword-member kw-sym 'c-block-stmt-kwds)
+                     nil)
+                    (t
+                     'maybe)))
+
+               (if (looking-at "\\s(")
+                   (if passed-paren
+                       (if (and (eq passed-paren ?\[)
+                                (eq (char-after) ?\[))
+                           ;; Accept several square bracket sexps for
+                           ;; Java array initializations.
+                           'maybe)
+                     (setq passed-paren (char-after))
+                     'maybe)
+                 'maybe))))
+
       (if (eq res 'maybe)
-         (when (and block-follows
+         (when (and c-recognize-paren-inexpr-blocks
+                    block-follows
                     containing-sexp
                     (eq (char-after containing-sexp) ?\())
            (goto-char containing-sexp)
@@ -5174,12 +6931,15 @@ brace."
                         (c-looking-at-special-brace-list)))
                nil
              (cons 'inexpr-statement (point))))
+
        res))))
 
 (defun c-looking-at-inexpr-block-backward (paren-state)
   ;; Returns non-nil if we're looking at the end of an in-expression
   ;; block, otherwise the same as `c-looking-at-inexpr-block'.
   ;; PAREN-STATE is the paren state relevant at the current position.
+  ;;
+  ;; This function might do hidden buffer changes.
   (save-excursion
     ;; We currently only recognize a block.
     (let ((here (point))
@@ -5196,31 +6956,6 @@ brace."
                                                    paren-state)
                                   containing-sexp)))))
 
-(defun c-narrow-out-enclosing-class (paren-state lim)
-  ;; Narrow the buffer so that the enclosing class is hidden.  Uses
-  ;; and returns the value from c-search-uplist-for-classkey.
-  (setq paren-state (c-whack-state-after (point) paren-state))
-  (let (inclass-p)
-    (and paren-state
-        (setq inclass-p (c-search-uplist-for-classkey paren-state))
-        (narrow-to-region
-         (progn
-           (goto-char (1+ (aref inclass-p 1)))
-           (c-skip-ws-forward lim)
-           ;; if point is now left of the class opening brace, we're
-           ;; hosed, so try a different tact
-           (if (<= (point) (aref inclass-p 1))
-               (progn
-                 (goto-char (1+ (aref inclass-p 1)))
-                 (c-forward-syntactic-ws lim)))
-           (point))
-         ;; end point is the end of the current line
-         (progn
-           (goto-char lim)
-           (c-point 'eol))))
-    ;; return the class vector
-    inclass-p))
-
 \f
 ;; `c-guess-basic-syntax' and the functions that precedes it below
 ;; implements the main decision tree for determining the syntactic
@@ -5247,7 +6982,6 @@ brace."
 (defun c-add-stmt-syntax (syntax-symbol
                          syntax-extra-args
                          stop-at-boi-only
-                         at-block-start
                          containing-sexp
                          paren-state)
   ;; Do the generic processing to anchor the given syntax symbol on
@@ -5264,177 +6998,170 @@ brace."
   ;; SYNTAX-EXTRA-ARGS are a list of the extra arguments for the
   ;; syntax symbol.  They are appended after the anchor point.
   ;;
-  ;; If STOP-AT-BOI-ONLY is nil, we might stop in the middle of the
-  ;; line if another statement precedes the current one on this line.
+  ;; If STOP-AT-BOI-ONLY is nil, we can stop in the middle of the line
+  ;; if the current statement starts there.
   ;;
-  ;; If AT-BLOCK-START is non-nil, point is taken to be at the
-  ;; beginning of a block or brace list, which then might be nested
-  ;; inside an expression.  If AT-BLOCK-START is nil, this is found
-  ;; out by checking whether the character at point is "{" or not.
+  ;; Note: It's not a problem if PAREN-STATE "overshoots"
+  ;; CONTAINING-SEXP, i.e. contains info about parens further down.
+  ;;
+  ;; This function might do hidden buffer changes.
+
   (if (= (point) (c-point 'boi))
       ;; This is by far the most common case, so let's give it special
       ;; treatment.
       (apply 'c-add-syntax syntax-symbol (point) syntax-extra-args)
 
-    (let ((savepos (point))
-         (syntax-last c-syntactic-context)
+    (let ((syntax-last c-syntactic-context)
          (boi (c-point 'boi))
-         (prev-paren (if at-block-start ?{ (char-after)))
-         step-type step-tmp at-comment special-list)
-      (apply 'c-add-syntax syntax-symbol nil syntax-extra-args)
-
-      ;; Begin by skipping any labels and containing statements that
-      ;; are on the same line.
-      (while (and (/= (point) boi)
-                 (if (memq (setq step-tmp
-                                 (c-beginning-of-statement-1 boi nil t))
-                           '(up label))
-                     t
-                   (goto-char savepos)
-                   nil)
-                 (/= (point) savepos))
-       (setq savepos (point)
-             step-type step-tmp))
-
-      (catch 'done
-         ;; Loop if we have to back out of the containing block.
-         (while
-           (progn
+         ;; Set when we're on a label, so that we don't stop there.
+         ;; FIXME: To be complete we should check if we're on a label
+         ;; now at the start.
+         on-label)
 
-             ;; Loop if we have to back up another statement.
-             (while
-                 (progn
+      (apply 'c-add-syntax syntax-symbol nil syntax-extra-args)
 
-                   ;; Always start by skipping over any comments that
-                   ;; stands between the statement and boi.
-                   (while (and (/= (setq savepos (point)) boi)
-                               (c-backward-single-comment))
-                     (setq at-comment t
-                           boi (c-point 'boi)))
-                   (goto-char savepos)
-
-                   (and
-                    (or at-comment
-                        (eq step-type 'label)
-                        (/= savepos boi))
-
-                    (let ((save-step-type step-type))
-                      ;; Current position might not be good enough;
-                      ;; skip backward another statement.
-                      (setq step-type (c-beginning-of-statement-1
-                                       containing-sexp))
-
-                      (if (and (not stop-at-boi-only)
-                               (/= savepos boi)
-                               (memq step-type '(up previous)))
-                          ;; If stop-at-boi-only is nil, we shouldn't
-                          ;; back up over previous or containing
-                          ;; statements to try to reach boi, so go
-                          ;; back to the last position and exit.
+      ;; Loop while we have to back out of containing blocks.
+      (while
+         (and
+          (catch 'back-up-block
+
+            ;; Loop while we have to back up statements.
+            (while (or (/= (point) boi)
+                       on-label
+                       (looking-at c-comment-start-regexp))
+
+              ;; Skip past any comments that stands between the
+              ;; statement start and boi.
+              (let ((savepos (point)))
+                (while (and (/= savepos boi)
+                            (c-backward-single-comment))
+                  (setq savepos (point)
+                        boi (c-point 'boi)))
+                (goto-char savepos))
+
+              ;; Skip to the beginning of this statement or backward
+              ;; another one.
+              (let ((old-pos (point))
+                    (old-boi boi)
+                    (step-type (c-beginning-of-statement-1 containing-sexp)))
+                (setq boi (c-point 'boi)
+                      on-label (eq step-type 'label))
+
+                (cond ((= (point) old-pos)
+                       ;; If we didn't move we're at the start of a block and
+                       ;; have to continue outside it.
+                       (throw 'back-up-block t))
+
+                      ((and (eq step-type 'up)
+                            (>= (point) old-boi)
+                            (looking-at "else\\>[^_]")
+                            (save-excursion
+                              (goto-char old-pos)
+                              (looking-at "if\\>[^_]")))
+                       ;; Special case to avoid deeper and deeper indentation
+                       ;; of "else if" clauses.
+                       )
+
+                      ((and (not stop-at-boi-only)
+                            (/= old-pos old-boi)
+                            (memq step-type '(up previous)))
+                       ;; If stop-at-boi-only is nil, we shouldn't back up
+                       ;; over previous or containing statements to try to
+                       ;; reach boi, so go back to the last position and
+                       ;; exit.
+                       (goto-char old-pos)
+                       (throw 'back-up-block nil))
+
+                      (t
+                       (if (and (not stop-at-boi-only)
+                                (memq step-type '(up previous beginning)))
+                           ;; If we've moved into another statement then we
+                           ;; should no longer try to stop in the middle of a
+                           ;; line.
+                           (setq stop-at-boi-only t))
+
+                       ;; Record this as a substatement if we skipped up one
+                       ;; level.
+                       (when (eq step-type 'up)
+                         (c-add-syntax 'substatement nil))))
+                )))
+
+          containing-sexp)
+
+       ;; Now we have to go out of this block.
+       (goto-char containing-sexp)
+
+       ;; Don't stop in the middle of a special brace list opener
+       ;; like "({".
+       (when c-special-brace-lists
+         (let ((special-list (c-looking-at-special-brace-list)))
+           (when (and special-list
+                      (< (car (car special-list)) (point)))
+             (setq containing-sexp (car (car special-list)))
+             (goto-char containing-sexp))))
+
+       (setq paren-state (c-whack-state-after containing-sexp paren-state)
+             containing-sexp (c-most-enclosing-brace paren-state)
+             boi (c-point 'boi))
+
+       ;; Analyze the construct in front of the block we've stepped out
+       ;; from and add the right syntactic element for it.
+       (let ((paren-pos (point))
+             (paren-char (char-after))
+             step-type)
+
+         (if (eq paren-char ?\()
+             ;; Stepped out of a parenthesis block, so we're in an
+             ;; expression now.
+             (progn
+               (when (/= paren-pos boi)
+                 (if (and c-recognize-paren-inexpr-blocks
                           (progn
-                            (goto-char savepos)
-                            nil)
-                        (if (and (not stop-at-boi-only)
-                                 (memq step-type '(up previous beginning)))
-                            ;; If we've moved into another statement
-                            ;; then we should no longer try to stop
-                            ;; after boi.
-                            (setq stop-at-boi-only t))
-
-                        ;; Record this a substatement if we skipped up
-                        ;; one level, but not if we're still on the
-                        ;; same line.  This so e.g. a sequence of "else
-                        ;; if" clauses won't indent deeper and deeper.
-                        (when (and (eq step-type 'up)
-                                   (< (point) boi))
-                          (c-add-syntax 'substatement nil))
-
-                        (setq boi (c-point 'boi))
-                        (if (= (point) savepos)
-                            (progn
-                              (setq step-type save-step-type)
-                              nil)
-                          t)))))
-
-               (setq savepos (point)
-                     at-comment nil))
-             (setq at-comment nil)
-
-             (when (and containing-sexp
-                        (if (memq step-type '(nil same))
-                            (/= (point) boi)
-                          (eq step-type 'label)))
-               (goto-char containing-sexp)
-
-               ;; Don't stop in the middle of a special brace list opener
-               ;; like "({".
-               (when (and c-special-brace-lists
-                          (setq special-list
-                                (c-looking-at-special-brace-list)))
-                 (setq containing-sexp (car (car special-list)))
-                 (goto-char containing-sexp))
-
-               (setq paren-state (c-whack-state-after containing-sexp
-                                                      paren-state)
-                     containing-sexp (c-most-enclosing-brace paren-state)
-                     savepos (point)
-                     boi (c-point 'boi))
-
-               (if (eq (setq prev-paren (char-after)) ?\()
-                   (progn
-                     (c-backward-syntactic-ws containing-sexp)
-                     (when (/= savepos boi)
-                       (if (and (or (not (looking-at "\\>"))
-                                    (not (c-on-identifier)))
-                                (not special-list)
-                                (save-excursion
-                                  (c-forward-syntactic-ws)
-                                  (forward-char)
-                                  (c-forward-syntactic-ws)
-                                  (eq (char-after) ?{)))
-                           ;; We're in an in-expression statement.
-                           ;; This syntactic element won't get an anchor pos.
-                           (c-add-syntax 'inexpr-statement)
-                         (c-add-syntax 'arglist-cont-nonempty nil savepos)))
-                     (goto-char (max boi
-                                     (if containing-sexp
-                                         (1+ containing-sexp)
-                                       (point-min))))
-                     (setq step-type 'same))
-                 (setq step-type
-                       (c-beginning-of-statement-1 containing-sexp)))
-
-               (let ((at-bod (and (eq step-type 'same)
-                                  (/= savepos (point))
-                                  (eq prev-paren ?{))))
-
-                 (when (= savepos boi)
-                   ;; If the open brace was at boi, we're always
-                   ;; done.  The c-beginning-of-statement-1 call
-                   ;; above is necessary anyway, to decide the type
-                   ;; of block-intro to add.
-                   (goto-char savepos)
-                   (setq savepos nil))
-
-                 (when (eq prev-paren ?{)
-                   (c-add-syntax (if at-bod
-                                     'defun-block-intro
-                                   'statement-block-intro)
-                                 nil))
-
-                 (when (and (not at-bod) savepos)
-                   ;; Loop if the brace wasn't at boi, and we didn't
-                   ;; arrive at a defun block.
-                   (if (eq step-type 'same)
-                       ;; Avoid backing up another sexp if the point
-                       ;; we're at now is found to be good enough in
-                       ;; the loop above.
-                       (setq step-type nil))
-                   (if (and (not stop-at-boi-only)
-                            (memq step-type '(up previous beginning)))
-                       (setq stop-at-boi-only t))
-                   (setq boi (c-point 'boi)))))
-             )))
+                            (c-backward-syntactic-ws containing-sexp)
+                            (or (not (looking-at "\\>"))
+                                (not (c-on-identifier))))
+                          (save-excursion
+                            (goto-char (1+ paren-pos))
+                            (c-forward-syntactic-ws)
+                            (eq (char-after) ?{)))
+                     ;; Stepped out of an in-expression statement.  This
+                     ;; syntactic element won't get an anchor pos.
+                     (c-add-syntax 'inexpr-statement)
+
+                   ;; A parenthesis normally belongs to an arglist.
+                   (c-add-syntax 'arglist-cont-nonempty nil paren-pos)))
+
+               (goto-char (max boi
+                               (if containing-sexp
+                                   (1+ containing-sexp)
+                                 (point-min))))
+               (setq step-type 'same
+                     on-label nil))
+
+           (setq step-type (c-beginning-of-statement-1 containing-sexp)
+                 on-label (eq step-type 'label))
+
+           (if (and (eq step-type 'same)
+                    (/= paren-pos (point)))
+               (save-excursion
+                 (goto-char paren-pos)
+                 (let ((inexpr (c-looking-at-inexpr-block
+                                (c-safe-position containing-sexp
+                                                 paren-state)
+                                containing-sexp)))
+                   (if (and inexpr
+                            (not (eq (car inexpr) 'inlambda)))
+                       (c-add-syntax 'statement-block-intro nil)
+                     (c-add-syntax 'defun-block-intro nil))))
+             (c-add-syntax 'statement-block-intro nil)))
+
+         (if (= paren-pos boi)
+             ;; Always done if the open brace was at boi.  The
+             ;; c-beginning-of-statement-1 call above is necessary
+             ;; anyway, to decide the type of block-intro to add.
+             (goto-char paren-pos)
+           (setq boi (c-point 'boi)))
+         ))
 
       ;; Fill in the current point as the anchor for all the symbols
       ;; added above.
@@ -5443,30 +7170,33 @@ brace."
          (if (cdr (car p))
              (setcar (cdr (car p)) (point)))
          (setq p (cdr p))))
-
       )))
 
-(defun c-add-class-syntax (symbol classkey paren-state)
+(defun c-add-class-syntax (symbol
+                          containing-decl-open
+                          containing-decl-start
+                          containing-decl-kwd
+                          paren-state)
   ;; The inclass and class-close syntactic symbols are added in
   ;; several places and some work is needed to fix everything.
   ;; Therefore it's collected here.
-  (save-restriction
-    (widen)
-    (let (inexpr anchor containing-sexp)
-      (goto-char (aref classkey 1))
-      (if (and (eq symbol 'inclass) (= (point) (c-point 'boi)))
-         (c-add-syntax symbol (setq anchor (point)))
-       (c-add-syntax symbol (setq anchor (aref classkey 0)))
-       (if (and c-opt-inexpr-class-key
-                (setq containing-sexp (c-most-enclosing-brace paren-state
-                                                              (point))
-                      inexpr (cdr (c-looking-at-inexpr-block
-                                   (c-safe-position containing-sexp
-                                                    paren-state)
-                                   containing-sexp)))
-                (/= inexpr (c-point 'boi inexpr)))
-           (c-add-syntax 'inexpr-class)))
-      anchor)))
+  ;;
+  ;; This function might do hidden buffer changes.
+  (goto-char containing-decl-open)
+  (if (and (eq symbol 'inclass) (= (point) (c-point 'boi)))
+      (progn
+       (c-add-syntax symbol containing-decl-open)
+       containing-decl-open)
+    (goto-char containing-decl-start)
+    ;; Ought to use `c-add-stmt-syntax' instead of backing up to boi
+    ;; here, but we have to do like this for compatibility.
+    (back-to-indentation)
+    (c-add-syntax symbol (point))
+    (if (and (c-keyword-member containing-decl-kwd
+                              'c-inexpr-class-kwds)
+            (/= containing-decl-start (c-point 'boi containing-decl-start)))
+       (c-add-syntax 'inexpr-class))
+    (point)))
 
 (defun c-guess-continued-construct (indent-point
                                    char-after-ip
@@ -5476,6 +7206,8 @@ brace."
   ;; This function contains the decision tree reached through both
   ;; cases 18 and 10.  It's a continued statement or top level
   ;; construct of some kind.
+  ;;
+  ;; This function might do hidden buffer changes.
 
   (let (special-brace-list)
     (goto-char indent-point)
@@ -5492,11 +7224,9 @@ brace."
       (cond
        ;; CASE B.1: class-open
        ((save-excursion
-         (skip-chars-forward "{")
-         (let ((decl (c-search-uplist-for-classkey (c-parse-state))))
-           (and decl
-                (setq beg-of-same-or-containing-stmt (aref decl 0)))
-           ))
+         (and (eq (char-after) ?{)
+              (c-looking-at-decl-block containing-sexp t)
+              (setq beg-of-same-or-containing-stmt (point))))
        (c-add-syntax 'class-open beg-of-same-or-containing-stmt))
 
        ;; CASE B.2: brace-list-open
@@ -5518,26 +7248,23 @@ brace."
                               ;; for the auto newline feature.
                               'brace-list-open
                             'statement-cont)
-                          nil nil nil
+                          nil nil
                           containing-sexp paren-state))
 
        ;; CASE B.3: The body of a function declared inside a normal
        ;; block.  Can occur e.g. in Pike and when using gcc
        ;; extensions, but watch out for macros followed by blocks.
        ;; C.f. cases E, 16F and 17G.
-       ((and (not (c-looking-at-bos))
+       ((and (not (c-at-statement-start-p))
             (eq (c-beginning-of-statement-1 containing-sexp nil nil t)
                 'same)
             (save-excursion
-              ;; Look for a type followed by a symbol, i.e. the start of a
-              ;; function declaration.  Doesn't work for declarations like
-              ;; "int *foo() ..."; we'd need to refactor the more competent
-              ;; analysis in `c-font-lock-declarations' for that.
-              (and (c-forward-type)
-                   (progn
-                     (c-forward-syntactic-ws)
-                     (looking-at c-symbol-start)))))
-       (c-add-stmt-syntax 'defun-open nil t nil
+              (let ((c-recognize-typeless-decls nil))
+                ;; Turn off recognition of constructs that lacks a
+                ;; type in this case, since that's more likely to be
+                ;; a macro followed by a block.
+                (c-forward-decl-or-cast-1 (c-point 'bosws) nil nil))))
+       (c-add-stmt-syntax 'defun-open nil t
                           containing-sexp paren-state))
 
        ;; CASE B.4: Continued statement with block open.  The most
@@ -5547,7 +7274,7 @@ brace."
        ;; followed by a block which makes it very similar to a
        ;; statement with a substatement block.
        (t
-       (c-add-stmt-syntax 'substatement-open nil nil nil
+       (c-add-stmt-syntax 'substatement-open nil nil
                           containing-sexp paren-state))
        ))
 
@@ -5577,94 +7304,89 @@ brace."
             ;; prototype in a code block without resorting to this.
             (c-forward-syntactic-ws)
             (eq (char-after) ?{))
-          (not (c-looking-at-bos))
+          (not (c-at-statement-start-p))
           (eq (c-beginning-of-statement-1 containing-sexp nil nil t)
               'same)
           (save-excursion
-            ;; Look for a type followed by a symbol, i.e. the start of a
-            ;; function declaration.  Doesn't work for declarations like "int
-            ;; *foo() ..."; we'd need to refactor the more competent analysis
-            ;; in `c-font-lock-declarations' for that.
-            (and (c-forward-type)
-                 (progn
-                   (c-forward-syntactic-ws)
-                   (looking-at c-symbol-start)))))
-      (c-add-stmt-syntax 'func-decl-cont nil t nil
+            (let ((c-recognize-typeless-decls nil))
+              ;; Turn off recognition of constructs that lacks a
+              ;; type in this case, since that's more likely to be
+              ;; a macro followed by a block.
+              (c-forward-decl-or-cast-1 (c-point 'bosws) nil nil))))
+      (c-add-stmt-syntax 'func-decl-cont nil t
                         containing-sexp paren-state))
 
      ;; CASE D: continued statement.
      (t
       (c-beginning-of-statement-1 containing-sexp)
-      (c-add-stmt-syntax 'statement-cont nil nil nil
+      (c-add-stmt-syntax 'statement-cont nil nil
                         containing-sexp paren-state))
      )))
 
+;; The next autoload was added by RMS on 2005/8/9 - don't know why (ACM,
+;; 2005/11/29).
 ;;;###autoload
 (defun c-guess-basic-syntax ()
-  "Return the syntactic context of the current line.
-This function does not do any hidden buffer changes."
+  "Return the syntactic context of the current line."
   (save-excursion
-    (save-restriction
       (beginning-of-line)
       (c-save-buffer-state
          ((indent-point (point))
           (case-fold-search nil)
+          ;; A whole ugly bunch of various temporary variables.  Have
+          ;; to declare them here since it's not possible to declare
+          ;; a variable with only the scope of a cond test and the
+          ;; following result clauses, and most of this function is a
+          ;; single gigantic cond. :P
+          literal char-before-ip before-ws-ip char-after-ip macro-start
+          in-macro-expr c-syntactic-context placeholder c-in-literal-cache
+          step-type tmpsymbol keyword injava-inher special-brace-list tmp-pos
+          ;; The following record some positions for the containing
+          ;; declaration block if we're directly within one:
+          ;; `containing-decl-open' is the position of the open
+          ;; brace.  `containing-decl-start' is the start of the
+          ;; declaration.  `containing-decl-kwd' is the keyword
+          ;; symbol of the keyword that tells what kind of block it
+          ;; is.
+          containing-decl-open
+          containing-decl-start
+          containing-decl-kwd
+          ;; The open paren of the closest surrounding sexp or nil if
+          ;; there is none.
+          containing-sexp
+          ;; The position after the closest preceding brace sexp
+          ;; (nested sexps are ignored), or the position after
+          ;; `containing-sexp' if there is none, or (point-min) if
+          ;; `containing-sexp' is nil.
+          lim
+          ;; The paren state outside `containing-sexp', or at
+          ;; `indent-point' if `containing-sexp' is nil.
           (paren-state (c-parse-state))
-          literal containing-sexp char-before-ip char-after-ip lim
-          c-syntactic-context placeholder c-in-literal-cache step-type
-          tmpsymbol keyword injava-inher special-brace-list
-          ;; narrow out any enclosing class or extern "C" block
-          (inclass-p (c-narrow-out-enclosing-class paren-state
-                                                   indent-point))
-          ;; `c-state-cache' is shadowed here so that we don't
-          ;; throw it away due to the narrowing that might be done
-          ;; by the function above.  That means we must not do any
-          ;; changes during the execution of this function, since
-          ;; `c-invalidate-state-cache' then would change this local
-          ;; variable and leave a bogus value in the global one.
-          (c-state-cache (if inclass-p
-                             (c-whack-state-before (point-min) paren-state)
-                           paren-state))
-          (c-state-cache-start (point-min))
-          inenclosing-p macro-start in-macro-expr
           ;; There's always at most one syntactic element which got
-          ;; a relpos.  It's stored in syntactic-relpos.
+          ;; an anchor pos.  It's stored in syntactic-relpos.
           syntactic-relpos
           (c-stmt-delim-chars c-stmt-delim-chars))
-       ;; Check for meta top-level enclosing constructs such as
-       ;; extern language definitions.
-       (save-excursion
-         (save-restriction
-           (widen)
-           (when (and inclass-p
-                      (progn
-                        (goto-char (aref inclass-p 0))
-                        (looking-at c-other-decl-block-key)))
-             (setq inenclosing-p (match-string 1))
-             (if (string-equal inenclosing-p "extern")
-                 ;; Compatibility with legacy choice of name for the
-                 ;; extern-lang syntactic symbols.
-                 (setq inenclosing-p "extern-lang")))))
-
-       ;; Init some position variables:
-       ;;
-       ;; containing-sexp is the open paren of the closest
-       ;; surrounding sexp or nil if there is none that hasn't been
-       ;; narrowed out.
-       ;;
-       ;; lim is the position after the closest preceding brace sexp
-       ;; (nested sexps are ignored), or the position after
-       ;; containing-sexp if there is none, or (point-min) if
-       ;; containing-sexp is nil.
-       ;;
-       ;; c-state-cache is the state from c-parse-state at
-       ;; indent-point, without any parens outside the region
-       ;; narrowed by c-narrow-out-enclosing-class.
-       ;;
-       ;; paren-state is the state from c-parse-state outside
-       ;; containing-sexp, or at indent-point if containing-sexp is
-       ;; nil.  paren-state is not limited to the narrowed region, as
-       ;; opposed to c-state-cache.
+
+       ;; Check if we're directly inside an enclosing declaration
+       ;; level block.
+       (when (and (setq containing-sexp
+                        (c-most-enclosing-brace paren-state))
+                  (progn
+                    (goto-char containing-sexp)
+                    (eq (char-after) ?{))
+                  (setq placeholder
+                        (c-looking-at-decl-block
+                         (c-most-enclosing-brace paren-state
+                                                 containing-sexp)
+                         t)))
+         (setq containing-decl-open containing-sexp
+               containing-decl-start (point)
+               containing-sexp nil)
+         (goto-char placeholder)
+         (setq containing-decl-kwd (and (looking-at c-keywords-regexp)
+                                        (c-keyword-sym (match-string 1)))))
+
+       ;; Init some position variables.
        (if c-state-cache
            (progn
              (setq containing-sexp (car paren-state)
@@ -5697,7 +7419,8 @@ This function does not do any hidden buffer changes."
        ;; the most likely position to perform the majority of tests
        (goto-char indent-point)
        (c-backward-syntactic-ws lim)
-       (setq char-before-ip (char-before))
+       (setq before-ws-ip (point)
+             char-before-ip (char-before))
        (goto-char indent-point)
        (skip-chars-forward " \t")
        (setq char-after-ip (char-after))
@@ -5707,9 +7430,11 @@ This function does not do any hidden buffer changes."
 
        ;; now figure out syntactic qualities of the current line
        (cond
+
         ;; CASE 1: in a string.
         ((eq literal 'string)
          (c-add-syntax 'string (c-point 'bopl)))
+
         ;; CASE 2: in a C or C++ style comment.
         ((and (memq literal '(c c++))
               ;; This is a kludge for XEmacs where we use
@@ -5722,6 +7447,7 @@ This function does not do any hidden buffer changes."
               ;; we're inside a comment.
               (setq placeholder (c-literal-limits lim)))
          (c-add-syntax literal (car placeholder)))
+
         ;; CASE 3: in a cpp preprocessor macro continuation.
         ((and (save-excursion
                 (when (c-beginning-of-macro)
@@ -5747,11 +7473,13 @@ This function does not do any hidden buffer changes."
                         nil)))))
          (c-add-syntax tmpsymbol macro-start)
          (setq macro-start nil))
+
         ;; CASE 11: an else clause?
         ((looking-at "else\\>[^_]")
          (c-beginning-of-statement-1 containing-sexp)
-         (c-add-stmt-syntax 'else-clause nil t nil
+         (c-add-stmt-syntax 'else-clause nil t
                             containing-sexp paren-state))
+
         ;; CASE 12: while closure of a do/while construct?
         ((and (looking-at "while\\>[^_]")
               (save-excursion
@@ -5759,8 +7487,9 @@ This function does not do any hidden buffer changes."
                            'beginning)
                   (setq placeholder (point)))))
          (goto-char placeholder)
-         (c-add-stmt-syntax 'do-while-closure nil t nil
+         (c-add-stmt-syntax 'do-while-closure nil t
                             containing-sexp paren-state))
+
         ;; CASE 13: A catch or finally clause?  This case is simpler
         ;; than if-else and do-while, because a block is required
         ;; after every try, catch and finally.
@@ -5782,14 +7511,14 @@ This function does not do any hidden buffer changes."
                 (looking-at "\\(try\\|catch\\)\\>[^_]")
                 (setq placeholder (point))))
          (goto-char placeholder)
-         (c-add-stmt-syntax 'catch-clause nil t nil
+         (c-add-stmt-syntax 'catch-clause nil t
                             containing-sexp paren-state))
+
         ;; CASE 18: A substatement we can recognize by keyword.
         ((save-excursion
            (and c-opt-block-stmt-key
-                (if (c-mode-is-new-awk-p)
-                     (c-awk-prev-line-incomplete-p containing-sexp) ; ACM 2002/3/29
-                   (not (eq char-before-ip ?\;)))
+                (not (eq char-before-ip ?\;))
+                (not (c-at-vsemi-p before-ws-ip))
                 (not (memq char-after-ip '(?\) ?\] ?,)))
                 (or (not (eq char-before-ip ?}))
                     (c-looking-at-inexpr-block-backward c-state-cache))
@@ -5826,23 +7555,25 @@ This function does not do any hidden buffer changes."
                     (and (zerop (c-forward-token-2 1 nil))
                          (eq (char-after) ?\())
                   (looking-at c-opt-block-stmt-key))))
+
          (if (eq step-type 'up)
              ;; CASE 18A: Simple substatement.
              (progn
                (goto-char placeholder)
                (cond
                 ((eq char-after-ip ?{)
-                 (c-add-stmt-syntax 'substatement-open nil nil nil
+                 (c-add-stmt-syntax 'substatement-open nil nil
                                     containing-sexp paren-state))
                 ((save-excursion
                    (goto-char indent-point)
                    (back-to-indentation)
-                   (looking-at c-label-key))
-                 (c-add-stmt-syntax 'substatement-label nil nil nil
+                   (c-forward-label))
+                 (c-add-stmt-syntax 'substatement-label nil nil
                                     containing-sexp paren-state))
                 (t
-                 (c-add-stmt-syntax 'substatement nil nil nil
+                 (c-add-stmt-syntax 'substatement nil nil
                                     containing-sexp paren-state))))
+
            ;; CASE 18B: Some other substatement.  This is shared
            ;; with case 10.
            (c-guess-continued-construct indent-point
@@ -5850,14 +7581,66 @@ This function does not do any hidden buffer changes."
                                         placeholder
                                         lim
                                         paren-state)))
+
+        ;; CASE 14: A case or default label
+        ((looking-at c-label-kwds-regexp)
+         (if containing-sexp
+             (progn
+               (goto-char containing-sexp)
+               (setq lim (c-most-enclosing-brace c-state-cache
+                                                 containing-sexp))
+               (c-backward-to-block-anchor lim)
+               (c-add-stmt-syntax 'case-label nil t lim paren-state))
+           ;; Got a bogus label at the top level.  In lack of better
+           ;; alternatives, anchor it on (point-min).
+           (c-add-syntax 'case-label (point-min))))
+
+        ;; CASE 15: any other label
+        ((save-excursion
+           (back-to-indentation)
+           (and (not (looking-at c-syntactic-ws-start))
+                (c-forward-label)))
+         (cond (containing-decl-open
+                (setq placeholder (c-add-class-syntax 'inclass
+                                                      containing-decl-open
+                                                      containing-decl-start
+                                                      containing-decl-kwd
+                                                      paren-state))
+                ;; Append access-label with the same anchor point as
+                ;; inclass gets.
+                (c-append-syntax 'access-label placeholder))
+
+               (containing-sexp
+                (goto-char containing-sexp)
+                (setq lim (c-most-enclosing-brace c-state-cache
+                                                  containing-sexp))
+                (save-excursion
+                  (setq tmpsymbol
+                        (if (and (eq (c-beginning-of-statement-1 lim) 'up)
+                                 (looking-at "switch\\>[^_]"))
+                            ;; If the surrounding statement is a switch then
+                            ;; let's analyze all labels as switch labels, so
+                            ;; that they get lined up consistently.
+                            'case-label
+                          'label)))
+                (c-backward-to-block-anchor lim)
+                (c-add-stmt-syntax tmpsymbol nil t lim paren-state))
+
+               (t
+                ;; A label on the top level.  Treat it as a class
+                ;; context.  (point-min) is the closest we get to the
+                ;; class open brace.
+                (c-add-syntax 'access-label (point-min)))))
+
         ;; CASE 4: In-expression statement.  C.f. cases 7B, 16A and
         ;; 17E.
-        ((and (or c-opt-inexpr-class-key
-                  c-opt-inexpr-block-key
-                  c-opt-lambda-key)
-              (setq placeholder (c-looking-at-inexpr-block
-                                 (c-safe-position containing-sexp paren-state)
-                                 containing-sexp)))
+        ((setq placeholder (c-looking-at-inexpr-block
+                            (c-safe-position containing-sexp paren-state)
+                            containing-sexp
+                            ;; Have to turn on the heuristics after
+                            ;; the point even though it doesn't work
+                            ;; very well.  C.f. test case class-16.pike.
+                            t))
          (setq tmpsymbol (assq (car placeholder)
                                '((inexpr-class . class-open)
                                  (inexpr-statement . block-open))))
@@ -5872,14 +7655,16 @@ This function does not do any hidden buffer changes."
                              'lambda-intro-cont)))
          (goto-char (cdr placeholder))
          (back-to-indentation)
-         (c-add-stmt-syntax tmpsymbol nil t nil
+         (c-add-stmt-syntax tmpsymbol nil t
                             (c-most-enclosing-brace c-state-cache (point))
-                            (c-whack-state-after (point) paren-state))
+                            paren-state)
          (unless (eq (point) (cdr placeholder))
            (c-add-syntax (car placeholder))))
-        ;; CASE 5: Line is at top level.
-        ((null containing-sexp)
+
+        ;; CASE 5: Line is inside a declaration level block or at top level.
+        ((or containing-decl-open (null containing-sexp))
          (cond
+
           ;; CASE 5A: we are looking at a defun, brace list, class,
           ;; or inline-inclass method opening brace
           ((setq special-brace-list
@@ -5887,36 +7672,36 @@ This function does not do any hidden buffer changes."
                           (c-looking-at-special-brace-list))
                      (eq char-after-ip ?{)))
            (cond
+
             ;; CASE 5A.1: Non-class declaration block open.
             ((save-excursion
-               (goto-char indent-point)
-               (skip-chars-forward " \t")
-               (and (c-safe (c-backward-sexp 2) t)
-                    (looking-at c-other-decl-block-key)
-                    (setq keyword (match-string 1)
-                          placeholder (point))
-                    (if (string-equal keyword "extern")
-                        ;; Special case for extern-lang-open.  The
-                        ;; check for a following string is disabled
-                        ;; since it doesn't disambiguate anything.
-                        (and ;;(progn
-                             ;;  (c-forward-sexp 1)
-                             ;;  (c-forward-syntactic-ws)
-                             ;;  (eq (char-after) ?\"))
-                             (setq tmpsymbol 'extern-lang-open))
-                      (setq tmpsymbol (intern (concat keyword "-open"))))
-                    ))
+               (let (tmp)
+                 (and (eq char-after-ip ?{)
+                      (setq tmp (c-looking-at-decl-block containing-sexp t))
+                      (progn
+                        (setq placeholder (point))
+                        (goto-char tmp)
+                        (looking-at c-symbol-key))
+                      (c-keyword-member
+                       (c-keyword-sym (setq keyword (match-string 0)))
+                       'c-other-block-decl-kwds))))
              (goto-char placeholder)
-             (c-add-syntax tmpsymbol (c-point 'boi)))
+             (c-add-stmt-syntax
+              (if (string-equal keyword "extern")
+                  ;; Special case for extern-lang-open.
+                  'extern-lang-open
+                (intern (concat keyword "-open")))
+              nil t containing-sexp paren-state))
+
             ;; CASE 5A.2: we are looking at a class opening brace
             ((save-excursion
                (goto-char indent-point)
-               (skip-chars-forward " \t{")
-               (let ((decl (c-search-uplist-for-classkey (c-parse-state))))
-                 (and decl
-                      (setq placeholder (aref decl 0)))
-                 ))
+               (skip-chars-forward " \t")
+               (and (eq (char-after) ?{)
+                    (c-looking-at-decl-block containing-sexp t)
+                    (setq placeholder (point))))
              (c-add-syntax 'class-open placeholder))
+
             ;; CASE 5A.3: brace list open
             ((save-excursion
                (c-beginning-of-decl-1 lim)
@@ -5958,65 +7743,69 @@ This function does not do any hidden buffer changes."
                    (c-beginning-of-statement-1 lim)
                    (c-add-syntax 'topmost-intro-cont (c-point 'boi)))
                (c-add-syntax 'brace-list-open placeholder)))
+
             ;; CASE 5A.4: inline defun open
-            ((and inclass-p (not inenclosing-p))
+            ((and containing-decl-open
+                  (not (c-keyword-member containing-decl-kwd
+                                         'c-other-block-decl-kwds)))
              (c-add-syntax 'inline-open)
-             (c-add-class-syntax 'inclass inclass-p paren-state))
+             (c-add-class-syntax 'inclass
+                                 containing-decl-open
+                                 containing-decl-start
+                                 containing-decl-kwd
+                                 paren-state))
+
             ;; CASE 5A.5: ordinary defun open
             (t
              (goto-char placeholder)
-             (if (or inclass-p macro-start)
+             (if (or containing-decl-open macro-start)
                  (c-add-syntax 'defun-open (c-point 'boi))
                ;; Bogus to use bol here, but it's the legacy.
                (c-add-syntax 'defun-open (c-point 'bol)))
              )))
-          ;; CASE 5B: first K&R arg decl or member init
-          ((c-just-after-func-arglist-p lim)
+
+          ;; CASE 5B: After a function header but before the body (or
+          ;; the ending semicolon if there's no body).
+          ((save-excursion
+             (when (setq placeholder (c-just-after-func-arglist-p lim))
+               (setq tmp-pos (point))))
            (cond
-            ;; CASE 5B.1: a member init
-            ((or (eq char-before-ip ?:)
-                 (eq char-after-ip ?:))
-             ;; this line should be indented relative to the beginning
-             ;; of indentation for the topmost-intro line that contains
-             ;; the prototype's open paren
-             ;; TBD: is the following redundant?
-             (if (eq char-before-ip ?:)
-                 (forward-char -1))
-             (c-backward-syntactic-ws lim)
-             ;; TBD: is the preceding redundant?
-             (if (eq (char-before) ?:)
-                 (progn (forward-char -1)
-                        (c-backward-syntactic-ws lim)))
-             (if (eq (char-before) ?\))
-                 (c-backward-sexp 1))
-             (setq placeholder (point))
-             (save-excursion
-               (and (c-safe (c-backward-sexp 1) t)
-                    (looking-at "throw[^_]")
-                    (c-safe (c-backward-sexp 1) t)
-                    (setq placeholder (point))))
-             (goto-char placeholder)
-             (c-add-syntax 'member-init-intro (c-point 'boi))
-             ;; we don't need to add any class offset since this
-             ;; should be relative to the ctor's indentation
-             )
+
+            ;; CASE 5B.1: Member init list.
+            ((eq (char-after tmp-pos) ?:)
+             (if (or (> tmp-pos indent-point)
+                     (= (c-point 'bosws) (1+ tmp-pos)))
+                 (progn
+                   ;; There is no preceding member init clause.
+                   ;; Indent relative to the beginning of indentation
+                   ;; for the topmost-intro line that contains the
+                   ;; prototype's open paren.
+                   (goto-char placeholder)
+                   (c-add-syntax 'member-init-intro (c-point 'boi)))
+               ;; Indent relative to the first member init clause.
+               (goto-char (1+ tmp-pos))
+               (c-forward-syntactic-ws)
+               (c-add-syntax 'member-init-cont (point))))
+
             ;; CASE 5B.2: K&R arg decl intro
             ((and c-recognize-knr-p
                   (c-in-knr-argdecl lim))
              (c-beginning-of-statement-1 lim)
              (c-add-syntax 'knr-argdecl-intro (c-point 'boi))
-             (if inclass-p
-                 (c-add-class-syntax 'inclass inclass-p paren-state)))
-            ;; CASE 5B.3: Inside a member init list.
-            ((c-beginning-of-member-init-list lim)
-             (c-forward-syntactic-ws)
-             (c-add-syntax 'member-init-cont (point)))
+             (if containing-decl-open
+                 (c-add-class-syntax 'inclass
+                                     containing-decl-open
+                                     containing-decl-start
+                                     containing-decl-kwd
+                                     paren-state)))
+
             ;; CASE 5B.4: Nether region after a C++ or Java func
             ;; decl, which could include a `throws' declaration.
             (t
              (c-beginning-of-statement-1 lim)
              (c-add-syntax 'func-decl-cont (c-point 'boi))
              )))
+
           ;; CASE 5C: inheritance line. could be first inheritance
           ;; line, or continuation of a multiple inheritance
           ((or (and (c-major-mode-is 'c++-mode)
@@ -6061,6 +7850,7 @@ This function does not do any hidden buffer changes."
                                                         (point)))
                     ))
            (cond
+
             ;; CASE 5C.1: non-hanging colon on an inher intro
             ((eq char-after-ip ?:)
              (c-beginning-of-statement-1 lim)
@@ -6068,12 +7858,18 @@ This function does not do any hidden buffer changes."
              ;; don't add inclass symbol since relative point already
              ;; contains any class offset
              )
+
             ;; CASE 5C.2: hanging colon on an inher intro
             ((eq char-before-ip ?:)
              (c-beginning-of-statement-1 lim)
              (c-add-syntax 'inher-intro (c-point 'boi))
-             (if inclass-p
-                 (c-add-class-syntax 'inclass inclass-p paren-state)))
+             (if containing-decl-open
+                 (c-add-class-syntax 'inclass
+                                     containing-decl-open
+                                     containing-decl-start
+                                     containing-decl-kwd
+                                     paren-state)))
+
             ;; CASE 5C.3: in a Java implements/extends
             (injava-inher
              (let ((where (cdr injava-inher))
@@ -6089,6 +7885,7 @@ This function does not do any hidden buffer changes."
                                              (c-beginning-of-statement-1 lim)
                                              (point))))
                      )))
+
             ;; CASE 5C.4: a continued inheritance line
             (t
              (c-beginning-of-inheritance-list lim)
@@ -6096,77 +7893,67 @@ This function does not do any hidden buffer changes."
              ;; don't add inclass symbol since relative point already
              ;; contains any class offset
              )))
+
           ;; CASE 5D: this could be a top-level initialization, a
           ;; member init list continuation, or a template argument
           ;; list continuation.
-          ((c-with-syntax-table (if (c-major-mode-is 'c++-mode)
-                                    c++-template-syntax-table
-                                  (syntax-table))
-             (save-excursion
-               ;; Note: We use the fact that lim is always after any
-               ;; preceding brace sexp.
-               (while (and (zerop (c-backward-token-2 1 t lim))
-                           (or (not (looking-at "[;<,=]"))
-                               (and c-overloadable-operators-regexp
-                                    (looking-at c-overloadable-operators-regexp)
-                                    (save-excursion
-                                      (c-backward-token-2 1 nil lim)
-                                      (looking-at "operator\\>[^_]"))))))
-               (or (memq (char-after) '(?, ?=))
-                   (and (c-major-mode-is 'c++-mode)
-                        (zerop (c-backward-token-2 1 nil lim))
-                        (eq (char-after) ?<)))))
-           (goto-char indent-point)
-           (setq placeholder
-                 (c-beginning-of-member-init-list lim))
+          ((save-excursion
+             ;; Note: We use the fact that lim always is after any
+             ;; preceding brace sexp.
+             (if c-recognize-<>-arglists
+                 (while (and
+                         (progn
+                           (c-syntactic-skip-backward "^;,=<>" lim t)
+                           (> (point) lim))
+                         (or
+                          (when c-overloadable-operators-regexp
+                            (when (setq placeholder (c-after-special-operator-id lim))
+                              (goto-char placeholder)
+                              t))
+                          (cond
+                           ((eq (char-before) ?>)
+                            (or (c-backward-<>-arglist nil lim)
+                                (backward-char))
+                            t)
+                           ((eq (char-before) ?<)
+                            (backward-char)
+                            (if (save-excursion
+                                  (c-forward-<>-arglist nil))
+                                (progn (forward-char)
+                                       nil)
+                              t))
+                           (t nil)))))
+               ;; NB: No c-after-special-operator-id stuff in this
+               ;; clause - we assume only C++ needs it.
+               (c-syntactic-skip-backward "^;,=" lim t))
+             (memq (char-before) '(?, ?= ?<)))
            (cond
-            ;; CASE 5D.1: hanging member init colon, but watch out
-            ;; for bogus matches on access specifiers inside classes.
-            ((and placeholder
-                  (save-excursion
-                    (setq placeholder (point))
-                    (c-backward-token-2 1 t lim)
-                    (and (eq (char-after) ?:)
-                         (not (eq (char-before) ?:))))
-                  (save-excursion
-                    (goto-char placeholder)
-                    (back-to-indentation)
-                    (or
-                     (/= (car (save-excursion
-                                (parse-partial-sexp (point) placeholder)))
-                         0)
-                     (and
-                      (if c-opt-access-key
-                          (not (looking-at c-opt-access-key)) t)
-                      (not (looking-at c-class-key))
-                      (if c-opt-bitfield-key
-                          (not (looking-at c-opt-bitfield-key)) t))
-                     )))
-             (goto-char placeholder)
-             (c-forward-syntactic-ws)
-             (c-add-syntax 'member-init-cont (point))
-             ;; we do not need to add class offset since relative
-             ;; point is the member init above us
-             )
-            ;; CASE 5D.2: non-hanging member init colon
-            ((progn
-               (c-forward-syntactic-ws indent-point)
-               (eq (char-after) ?:))
-             (skip-chars-forward " \t:")
-             (c-add-syntax 'member-init-cont (point)))
+
             ;; CASE 5D.3: perhaps a template list continuation?
             ((and (c-major-mode-is 'c++-mode)
                   (save-excursion
                     (save-restriction
                       (c-with-syntax-table c++-template-syntax-table
                         (goto-char indent-point)
-                        (setq placeholder (c-up-list-backward (point)))
+                        (setq placeholder (c-up-list-backward))
                         (and placeholder
                              (eq (char-after placeholder) ?<))))))
-             ;; we can probably indent it just like an arglist-cont
-             (goto-char placeholder)
-             (c-beginning-of-statement-1 lim t)
-             (c-add-syntax 'template-args-cont (c-point 'boi)))
+             (c-with-syntax-table c++-template-syntax-table
+               (goto-char placeholder)
+               (c-beginning-of-statement-1 lim t)
+               (if (save-excursion
+                     (c-backward-syntactic-ws lim)
+                     (eq (char-before) ?<))
+                   ;; In a nested template arglist.
+                   (progn
+                     (goto-char placeholder)
+                     (c-syntactic-skip-backward "^,;" lim t)
+                     (c-forward-syntactic-ws))
+                 (back-to-indentation)))
+             ;; FIXME: Should use c-add-stmt-syntax, but it's not yet
+             ;; template aware.
+             (c-add-syntax 'template-args-cont (point)))
+
             ;; CASE 5D.4: perhaps a multiple inheritance line?
             ((and (c-major-mode-is 'c++-mode)
                   (save-excursion
@@ -6183,6 +7970,7 @@ This function does not do any hidden buffer changes."
                          (eq (char-after) ?:))))
              (goto-char placeholder)
              (c-add-syntax 'inher-cont (c-point 'boi)))
+
             ;; CASE 5D.5: Continuation of the "expression part" of a
             ;; top level construct.
             (t
@@ -6199,33 +7987,38 @@ This function does not do any hidden buffer changes."
                   ;; the first variable declaration.  C.f. case 5N.
                   'topmost-intro-cont
                 'statement-cont)
-              nil nil nil containing-sexp paren-state))
+              nil nil containing-sexp paren-state))
             ))
-          ;; CASE 5E: we are looking at a access specifier
-          ((and inclass-p
-                c-opt-access-key
-                (looking-at c-opt-access-key))
-           (setq placeholder (c-add-class-syntax 'inclass inclass-p
-                                                 paren-state))
-           ;; Append access-label with the same anchor point as inclass gets.
-           (c-append-syntax 'access-label placeholder))
+          
           ;; CASE 5F: Close of a non-class declaration level block.
-          ((and inenclosing-p
-                (eq char-after-ip ?}))
-           (c-add-syntax (intern (concat inenclosing-p "-close"))
-                         (aref inclass-p 0)))
+          ((and (eq char-after-ip ?})
+                (c-keyword-member containing-decl-kwd
+                                  'c-other-block-decl-kwds))
+           ;; This is inconsistent: Should use `containing-decl-open'
+           ;; here if it's at boi, like in case 5J.
+           (goto-char containing-decl-start)
+           (c-add-stmt-syntax
+             (if (string-equal (symbol-name containing-decl-kwd) "extern")
+                 ;; Special case for compatibility with the
+                 ;; extern-lang syntactic symbols.
+                 'extern-lang-close
+               (intern (concat (symbol-name containing-decl-kwd)
+                               "-close")))
+             nil t
+             (c-most-enclosing-brace paren-state (point))
+             paren-state))
+
           ;; CASE 5G: we are looking at the brace which closes the
           ;; enclosing nested class decl
-          ((and inclass-p
+          ((and containing-sexp
                 (eq char-after-ip ?})
-                (save-excursion
-                  (save-restriction
-                    (widen)
-                    (forward-char 1)
-                    (and (c-safe (c-backward-sexp 1) t)
-                         (= (point) (aref inclass-p 1))
-                         ))))
-           (c-add-class-syntax 'class-close inclass-p paren-state))
+                (eq containing-decl-open containing-sexp))
+           (c-add-class-syntax 'class-close
+                               containing-decl-open
+                               containing-decl-start
+                               containing-decl-kwd
+                               paren-state))
+
           ;; CASE 5H: we could be looking at subsequent knr-argdecls
           ((and c-recognize-knr-p
                 (not (eq char-before-ip ?}))
@@ -6241,6 +8034,7 @@ This function does not do any hidden buffer changes."
                 (< placeholder indent-point))
            (goto-char placeholder)
            (c-add-syntax 'knr-argdecl (point)))
+
           ;; CASE 5I: ObjC method definition.
           ((and c-opt-method-key
                 (looking-at c-opt-method-key))
@@ -6254,17 +8048,19 @@ This function does not do any hidden buffer changes."
                ;; directive.
                (goto-char (point-min)))
            (c-add-syntax 'objc-method-intro (c-point 'boi)))
+
            ;; CASE 5P: AWK pattern or function or continuation
            ;; thereof.
-           ((c-mode-is-new-awk-p)
+           ((c-major-mode-is 'awk-mode)
             (setq placeholder (point))
             (c-add-stmt-syntax
              (if (and (eq (c-beginning-of-statement-1) 'same)
                       (/= (point) placeholder))
                  'topmost-intro-cont
                'topmost-intro)
-             nil nil nil
+             nil nil
              containing-sexp paren-state))
+
           ;; CASE 5N: At a variable declaration that follows a class
           ;; definition or some other block declaration that doesn't
           ;; end at the closing '}'.  C.f. case 5D.5.
@@ -6273,9 +8069,9 @@ This function does not do any hidden buffer changes."
              (and (eq (char-before) ?})
                   (save-excursion
                     (let ((start (point)))
-                      (if paren-state
+                      (if c-state-cache
                           ;; Speed up the backward search a bit.
-                          (goto-char (car (car paren-state))))
+                          (goto-char (caar c-state-cache)))
                       (c-beginning-of-decl-1 containing-sexp)
                       (setq placeholder (point))
                       (if (= start (point))
@@ -6284,71 +8080,102 @@ This function does not do any hidden buffer changes."
                         (c-end-of-decl-1)
                         (>= (point) indent-point))))))
            (goto-char placeholder)
-           (c-add-stmt-syntax 'topmost-intro-cont nil nil nil
+           (c-add-stmt-syntax 'topmost-intro-cont nil nil
                               containing-sexp paren-state))
+
+          ;; NOTE: The point is at the end of the previous token here.
+
           ;; CASE 5J: we are at the topmost level, make
           ;; sure we skip back past any access specifiers
-          ((progn
-             (while (and inclass-p
-                         c-opt-access-key
-                         (not (bobp))
-                         (save-excursion
-                           (c-safe (c-backward-sexp 1) t)
-                           (looking-at c-opt-access-key)))
-               (c-backward-sexp 1)
-               (c-backward-syntactic-ws lim))
-             (or (bobp)
-                  (if (c-mode-is-new-awk-p)
-                      (not (c-awk-prev-line-incomplete-p))
-                    (memq (char-before) '(?\; ?})))
+          ((save-excursion
+             (setq placeholder (point))
+             (or (memq char-before-ip '(?\; ?{ ?} nil))
+                 (c-at-vsemi-p before-ws-ip)
+                 (when (and (eq char-before-ip ?:)
+                            (eq (c-beginning-of-statement-1 lim)
+                                'label))
+                   (c-backward-syntactic-ws lim)
+                   (setq placeholder (point)))
                  (and (c-major-mode-is 'objc-mode)
-                      (progn
+                      (catch 'not-in-directive
                         (c-beginning-of-statement-1 lim)
-                        (eq (char-after) ?@)))))
-           ;; real beginning-of-line could be narrowed out due to
-           ;; enclosure in a class block
-           (save-restriction
-             (widen)
-             (c-add-syntax 'topmost-intro (c-point 'bol))
-             ;; Using bol instead of boi above is highly bogus, and
-             ;; it makes our lives hard to remain compatible. :P
-             (if inclass-p
-                 (progn
-                   (goto-char (aref inclass-p 1))
-                   (or (= (point) (c-point 'boi))
-                       (goto-char (aref inclass-p 0)))
-                   (if inenclosing-p
-                       (c-add-syntax (intern (concat "in" inenclosing-p))
-                                     (c-point 'boi))
-                     (c-add-class-syntax 'inclass inclass-p paren-state))
-                   ))
-             (when (and c-syntactic-indentation-in-macros
-                        macro-start
-                        (/= macro-start (c-point 'boi indent-point)))
-               (c-add-syntax 'cpp-define-intro)
-               (setq macro-start nil))
-             ))
+                        (setq placeholder (point))
+                        (while (and (c-forward-objc-directive)
+                                    (< (point) indent-point))
+                          (c-forward-syntactic-ws)
+                          (if (>= (point) indent-point)
+                              (throw 'not-in-directive t))
+                          (setq placeholder (point)))
+                        nil))))
+           ;; For historic reasons we anchor at bol of the last
+           ;; line of the previous declaration.  That's clearly
+           ;; highly bogus and useless, and it makes our lives hard
+           ;; to remain compatible.  :P
+           (goto-char placeholder)
+           (c-add-syntax 'topmost-intro (c-point 'bol))
+           (if containing-decl-open
+               (if (c-keyword-member containing-decl-kwd
+                                     'c-other-block-decl-kwds)
+                   (progn
+                     (goto-char containing-decl-open)
+                     (unless (= (point) (c-point 'boi))
+                       (goto-char containing-decl-start))
+                     (c-add-stmt-syntax
+                      (if (string-equal (symbol-name containing-decl-kwd)
+                                        "extern")
+                          ;; Special case for compatibility with the
+                          ;; extern-lang syntactic symbols.
+                          'inextern-lang
+                        (intern (concat "in"
+                                        (symbol-name containing-decl-kwd))))
+                      nil t
+                      (c-most-enclosing-brace paren-state (point))
+                      paren-state))
+                 (c-add-class-syntax 'inclass
+                                     containing-decl-open
+                                     containing-decl-start
+                                     containing-decl-kwd
+                                     paren-state)))
+           (when (and c-syntactic-indentation-in-macros
+                      macro-start
+                      (/= macro-start (c-point 'boi indent-point)))
+             (c-add-syntax 'cpp-define-intro)
+             (setq macro-start nil)))
+
           ;; CASE 5K: we are at an ObjC method definition
           ;; continuation line.
           ((and c-opt-method-key
                 (save-excursion
-                  (goto-char indent-point)
                   (c-beginning-of-statement-1 lim)
                   (beginning-of-line)
                   (when (looking-at c-opt-method-key)
                     (setq placeholder (point)))))
            (c-add-syntax 'objc-method-args-cont placeholder))
+
           ;; CASE 5L: we are at the first argument of a template
           ;; arglist that begins on the previous line.
-          ((eq (char-before) ?<)
+          ((and c-recognize-<>-arglists
+                (eq (char-before) ?<)
+                (not (and c-overloadable-operators-regexp
+                          (c-after-special-operator-id lim))))
            (c-beginning-of-statement-1 (c-safe-position (point) paren-state))
            (c-add-syntax 'template-args-cont (c-point 'boi)))
+
           ;; CASE 5M: we are at a topmost continuation line
           (t
            (c-beginning-of-statement-1 (c-safe-position (point) paren-state))
+           (when (c-major-mode-is 'objc-mode)
+             (setq placeholder (point))
+             (while (and (c-forward-objc-directive)
+                         (< (point) indent-point))
+               (c-forward-syntactic-ws)
+               (setq placeholder (point)))
+             (goto-char placeholder))
            (c-add-syntax 'topmost-intro-cont (c-point 'boi)))
           ))
+
         ;; (CASE 6 has been removed.)
+
         ;; CASE 7: line is an expression, not a statement.  Most
         ;; likely we are either in a function prototype or a function
         ;; call argument list
@@ -6358,6 +8185,7 @@ This function does not do any hidden buffer changes."
                          (c-looking-at-special-brace-list)))
                   (eq (char-after containing-sexp) ?{)))
          (cond
+
           ;; CASE 7A: we are looking at the arglist closing paren.
           ;; C.f. case 7F.
           ((memq char-after-ip '(?\) ?\]))
@@ -6369,16 +8197,17 @@ This function does not do any hidden buffer changes."
                  (forward-char)
                  (skip-chars-forward " \t"))
              (goto-char placeholder))
-           (c-add-stmt-syntax 'arglist-close (list containing-sexp) t nil
+           (c-add-stmt-syntax 'arglist-close (list containing-sexp) t
                               (c-most-enclosing-brace paren-state (point))
-                              (c-whack-state-after (point) paren-state)))
+                              paren-state))
+
           ;; CASE 7B: Looking at the opening brace of an
           ;; in-expression block or brace list.  C.f. cases 4, 16A
           ;; and 17E.
           ((and (eq char-after-ip ?{)
                 (progn
                   (setq placeholder (c-inside-bracelist-p (point)
-                                                          c-state-cache))
+                                                          paren-state))
                   (if placeholder
                       (setq tmpsymbol '(brace-list-open . inexpr-class))
                     (setq tmpsymbol '(block-open . inexpr-statement)
@@ -6393,23 +8222,28 @@ This function does not do any hidden buffer changes."
                     )))
            (goto-char placeholder)
            (back-to-indentation)
-           (c-add-stmt-syntax (car tmpsymbol) nil t nil
+           (c-add-stmt-syntax (car tmpsymbol) nil t
                               (c-most-enclosing-brace paren-state (point))
-                              (c-whack-state-after (point) paren-state))
+                              paren-state)
            (if (/= (point) placeholder)
                (c-add-syntax (cdr tmpsymbol))))
+
           ;; CASE 7C: we are looking at the first argument in an empty
           ;; argument list. Use arglist-close if we're actually
           ;; looking at a close paren or bracket.
           ((memq char-before-ip '(?\( ?\[))
            (goto-char containing-sexp)
            (setq placeholder (c-point 'boi))
-           (when (and (c-safe (backward-up-list 1) t)
-                      (>= (point) placeholder))
-             (forward-char)
-             (skip-chars-forward " \t")
-             (setq placeholder (point)))
-           (c-add-syntax 'arglist-intro placeholder))
+           (if (and (c-safe (backward-up-list 1) t)
+                    (>= (point) placeholder))
+               (progn
+                 (forward-char)
+                 (skip-chars-forward " \t"))
+             (goto-char placeholder))
+           (c-add-stmt-syntax 'arglist-intro (list containing-sexp) t
+                              (c-most-enclosing-brace paren-state (point))
+                              paren-state))
+
           ;; CASE 7D: we are inside a conditional test clause. treat
           ;; these things as statements
           ((progn
@@ -6422,6 +8256,7 @@ This function does not do any hidden buffer changes."
                (c-add-syntax 'statement (point))
              (c-add-syntax 'statement-cont (point))
              ))
+
           ;; CASE 7E: maybe a continued ObjC method call. This is the
           ;; case when we are inside a [] bracketed exp, and what
           ;; precede the opening bracket is not an identifier.
@@ -6433,6 +8268,7 @@ This function does not do any hidden buffer changes."
                   (if (not (looking-at c-symbol-key))
                       (c-add-syntax 'objc-method-call-cont containing-sexp))
                   )))
+
           ;; CASE 7F: we are looking at an arglist continuation line,
           ;; but the preceding argument is on the same line as the
           ;; opening paren.  This case includes multi-line
@@ -6440,9 +8276,10 @@ This function does not do any hidden buffer changes."
           ;; for-list continuation line.  C.f. case 7A.
           ((progn
              (goto-char (1+ containing-sexp))
-             (skip-chars-forward " \t")
-             (and (not (eolp))
-                  (not (looking-at "\\\\$"))))
+             (< (save-excursion
+                  (c-forward-syntactic-ws)
+                  (point))
+                (c-point 'bonl)))
            (goto-char containing-sexp)
            (setq placeholder (c-point 'boi))
            (if (and (c-safe (backward-up-list 1) t)
@@ -6451,15 +8288,16 @@ This function does not do any hidden buffer changes."
                  (forward-char)
                  (skip-chars-forward " \t"))
              (goto-char placeholder))
-           (c-add-stmt-syntax 'arglist-cont-nonempty (list containing-sexp)
-                              t nil
+           (c-add-stmt-syntax 'arglist-cont-nonempty (list containing-sexp) t
                               (c-most-enclosing-brace c-state-cache (point))
-                              (c-whack-state-after (point) paren-state)))
+                              paren-state))
+
           ;; CASE 7G: we are looking at just a normal arglist
           ;; continuation line
           (t (c-forward-syntactic-ws indent-point)
              (c-add-syntax 'arglist-cont (c-point 'boi)))
           ))
+
         ;; CASE 8: func-local multi-inheritance line
         ((and (c-major-mode-is 'c++-mode)
               (save-excursion
@@ -6469,27 +8307,32 @@ This function does not do any hidden buffer changes."
          (goto-char indent-point)
          (skip-chars-forward " \t")
          (cond
+
           ;; CASE 8A: non-hanging colon on an inher intro
           ((eq char-after-ip ?:)
            (c-backward-syntactic-ws lim)
            (c-add-syntax 'inher-intro (c-point 'boi)))
+
           ;; CASE 8B: hanging colon on an inher intro
           ((eq char-before-ip ?:)
            (c-add-syntax 'inher-intro (c-point 'boi)))
+
           ;; CASE 8C: a continued inheritance line
           (t
            (c-beginning-of-inheritance-list lim)
            (c-add-syntax 'inher-cont (point))
            )))
+
         ;; CASE 9: we are inside a brace-list
-        ((and (not (c-mode-is-new-awk-p))  ; Maybe this isn't needed (ACM, 2002/3/29)
+        ((and (not (c-major-mode-is 'awk-mode))  ; Maybe this isn't needed (ACM, 2002/3/29)
                (setq special-brace-list
-                     (or (and c-special-brace-lists
+                     (or (and c-special-brace-lists ;;;; ALWAYS NIL FOR AWK!!
                               (save-excursion
                                 (goto-char containing-sexp)
                                 (c-looking-at-special-brace-list)))
                          (c-inside-bracelist-p containing-sexp paren-state))))
          (cond
+
           ;; CASE 9A: In the middle of a special brace list opener.
           ((and (consp special-brace-list)
                 (save-excursion
@@ -6509,6 +8352,7 @@ This function does not do any hidden buffer changes."
                (goto-char (match-end 1))
                (c-forward-syntactic-ws))
              (c-add-syntax 'brace-list-open (c-point 'boi))))
+
           ;; CASE 9B: brace-list-close brace
           ((if (consp special-brace-list)
                ;; Check special brace list closer.
@@ -6533,8 +8377,8 @@ This function does not do any hidden buffer changes."
                (c-add-syntax 'brace-list-close (point))
              (setq lim (c-most-enclosing-brace c-state-cache (point)))
              (c-beginning-of-statement-1 lim)
-             (c-add-stmt-syntax 'brace-list-close nil t t lim
-                                (c-whack-state-after (point) paren-state))))
+             (c-add-stmt-syntax 'brace-list-close nil t lim paren-state)))
+
           (t
            ;; Prepare for the rest of the cases below by going to the
            ;; token following the opening brace
@@ -6549,6 +8393,7 @@ This function does not do any hidden buffer changes."
              (goto-char (max start (c-point 'bol))))
            (c-skip-ws-forward indent-point)
            (cond
+
             ;; CASE 9C: we're looking at the first line in a brace-list
             ((= (point) indent-point)
              (if (consp special-brace-list)
@@ -6558,8 +8403,8 @@ This function does not do any hidden buffer changes."
                  (c-add-syntax 'brace-list-intro (point))
                (setq lim (c-most-enclosing-brace c-state-cache (point)))
                (c-beginning-of-statement-1 lim)
-               (c-add-stmt-syntax 'brace-list-intro nil t t lim
-                                  (c-whack-state-after (point) paren-state))))
+               (c-add-stmt-syntax 'brace-list-intro nil t lim paren-state)))
+
             ;; CASE 9D: this is just a later brace-list-entry or
             ;; brace-entry-open
             (t (if (or (eq char-after-ip ?{)
@@ -6572,12 +8417,12 @@ This function does not do any hidden buffer changes."
                  (c-add-syntax 'brace-list-entry (point))
                  ))
             ))))
+
         ;; CASE 10: A continued statement or top level construct.
-        ((and (if (c-mode-is-new-awk-p)
-                   (c-awk-prev-line-incomplete-p containing-sexp) ; ACM 2002/3/29
-                 (and (not (memq char-before-ip '(?\; ?:)))
-                      (or (not (eq char-before-ip ?}))
-                          (c-looking-at-inexpr-block-backward c-state-cache))))
+        ((and (not (memq char-before-ip '(?\; ?:)))
+              (not (c-at-vsemi-p before-ws-ip))
+              (or (not (eq char-before-ip ?}))
+                  (c-looking-at-inexpr-block-backward c-state-cache))
               (> (point)
                  (save-excursion
                    (c-beginning-of-statement-1 containing-sexp)
@@ -6589,29 +8434,7 @@ This function does not do any hidden buffer changes."
                                       placeholder
                                       containing-sexp
                                       paren-state))
-        ;; CASE 14: A case or default label
-        ((looking-at c-label-kwds-regexp)
-         (goto-char containing-sexp)
-         (setq lim (c-most-enclosing-brace c-state-cache containing-sexp))
-         (c-backward-to-block-anchor lim)
-         (c-add-stmt-syntax 'case-label nil t nil
-                            lim paren-state))
-        ;; CASE 15: any other label
-        ((looking-at c-label-key)
-         (goto-char containing-sexp)
-         (setq lim (c-most-enclosing-brace c-state-cache containing-sexp))
-         (save-excursion
-           (setq tmpsymbol
-                 (if (and (eq (c-beginning-of-statement-1 lim) 'up)
-                          (looking-at "switch\\>[^_]"))
-                     ;; If the surrounding statement is a switch then
-                     ;; let's analyze all labels as switch labels, so
-                     ;; that they get lined up consistently.
-                     'case-label
-                   'label)))
-         (c-backward-to-block-anchor lim)
-         (c-add-stmt-syntax tmpsymbol nil t nil
-                            lim paren-state))
+
         ;; CASE 16: block close brace, possibly closing the defun or
         ;; the class
         ((eq char-after-ip ?})
@@ -6619,14 +8442,15 @@ This function does not do any hidden buffer changes."
          (setq lim (c-most-enclosing-brace paren-state))
          (goto-char containing-sexp)
            (cond
+
             ;; CASE 16E: Closing a statement block?  This catches
             ;; cases where it's preceded by a statement keyword,
             ;; which works even when used in an "invalid" context,
             ;; e.g. a macro argument.
             ((c-after-conditional)
              (c-backward-to-block-anchor lim)
-             (c-add-stmt-syntax 'block-close nil t nil
-                                lim paren-state))
+             (c-add-stmt-syntax 'block-close nil t lim paren-state))
+
             ;; CASE 16A: closing a lambda defun or an in-expression
             ;; block?  C.f. cases 4, 7B and 17E.
             ((setq placeholder (c-looking-at-inexpr-block
@@ -6641,56 +8465,59 @@ This function does not do any hidden buffer changes."
                  (c-add-syntax tmpsymbol (point))
                (goto-char (cdr placeholder))
                (back-to-indentation)
-               (c-add-stmt-syntax tmpsymbol nil t nil
+               (c-add-stmt-syntax tmpsymbol nil t
                                   (c-most-enclosing-brace paren-state (point))
-                                  (c-whack-state-after (point) paren-state))
+                                  paren-state)
                (if (/= (point) (cdr placeholder))
                    (c-add-syntax (car placeholder)))))
+
             ;; CASE 16B: does this close an inline or a function in
             ;; a non-class declaration level block?
-            ((setq placeholder (c-search-uplist-for-classkey paren-state))
+            ((save-excursion
+               (and lim
+                    (progn
+                      (goto-char lim)
+                      (c-looking-at-decl-block
+                       (c-most-enclosing-brace paren-state lim)
+                       nil))
+                    (setq placeholder (point))))
              (c-backward-to-decl-anchor lim)
              (back-to-indentation)
              (if (save-excursion
-                   (goto-char (aref placeholder 0))
+                   (goto-char placeholder)
                    (looking-at c-other-decl-block-key))
                  (c-add-syntax 'defun-close (point))
                (c-add-syntax 'inline-close (point))))
+
             ;; CASE 16F: Can be a defun-close of a function declared
             ;; in a statement block, e.g. in Pike or when using gcc
             ;; extensions, but watch out for macros followed by
             ;; blocks.  Let it through to be handled below.
             ;; C.f. cases B.3 and 17G.
-            ((and (not inenclosing-p)
-                  lim
-                  (save-excursion
-                    (and (not (c-looking-at-bos))
-                         (eq (c-beginning-of-statement-1 lim nil nil t) 'same)
-                         (setq placeholder (point))
-                         ;; Look for a type or identifier followed by a
-                         ;; symbol, i.e. the start of a function declaration.
-                         ;; Doesn't work for declarations like "int *foo()
-                         ;; ..."; we'd need to refactor the more competent
-                         ;; analysis in `c-font-lock-declarations' for that.
-                         (c-forward-type)
-                         (progn
-                           (c-forward-syntactic-ws)
-                           (looking-at c-symbol-start)))))
+            ((save-excursion
+               (and (not (c-at-statement-start-p))
+                    (eq (c-beginning-of-statement-1 lim nil nil t) 'same)
+                    (setq placeholder (point))
+                    (let ((c-recognize-typeless-decls nil))
+                      ;; Turn off recognition of constructs that
+                      ;; lacks a type in this case, since that's more
+                      ;; likely to be a macro followed by a block.
+                      (c-forward-decl-or-cast-1 (c-point 'bosws) nil nil))))
              (back-to-indentation)
              (if (/= (point) containing-sexp)
                  (goto-char placeholder))
-             (c-add-stmt-syntax 'defun-close nil t nil
-                                lim paren-state))
-            ;; CASE 16C: if there an enclosing brace that hasn't
-            ;; been narrowed out by a class, then this is a
-            ;; block-close.  C.f. case 17H.
-            ((and (not inenclosing-p) lim)
+             (c-add-stmt-syntax 'defun-close nil t lim paren-state))
+
+            ;; CASE 16C: If there is an enclosing brace then this is
+            ;; a block close since defun closes inside declaration
+            ;; level blocks have been handled above.
+            (lim
              ;; If the block is preceded by a case/switch label on
              ;; the same line, we anchor at the first preceding label
-             ;; at boi.  The default handling in c-add-stmt-syntax is
+             ;; at boi.  The default handling in c-add-stmt-syntax
              ;; really fixes it better, but we do like this to keep
              ;; the indentation compatible with version 5.28 and
-             ;; earlier.
+             ;; earlier.  C.f. case 17H.
              (while (and (/= (setq placeholder (point)) (c-point 'boi))
                          (eq (c-beginning-of-statement-1 lim) 'label)))
              (goto-char placeholder)
@@ -6699,21 +8526,17 @@ This function does not do any hidden buffer changes."
                (goto-char containing-sexp)
                ;; c-backward-to-block-anchor not necessary here; those
                ;; situations are handled in case 16E above.
-               (c-add-stmt-syntax 'block-close nil t nil
-                                  lim paren-state)))
-            ;; CASE 16D: find out whether we're closing a top-level
-            ;; class or a defun
+               (c-add-stmt-syntax 'block-close nil t lim paren-state)))
+
+            ;; CASE 16D: Only top level defun close left.
             (t
-             (save-restriction
-               (narrow-to-region (point-min) indent-point)
-               (let ((decl (c-search-uplist-for-classkey (c-parse-state))))
-                 (if decl
-                     (c-add-class-syntax 'class-close decl paren-state)
-                   (goto-char containing-sexp)
-                   (c-backward-to-decl-anchor lim)
-                   (back-to-indentation)
-                   (c-add-syntax 'defun-close (point)))))
-             )))
+             (goto-char containing-sexp)
+             (c-backward-to-decl-anchor lim)
+             (c-add-stmt-syntax 'defun-close nil nil
+                                (c-most-enclosing-brace paren-state)
+                                paren-state))
+            ))
+
         ;; CASE 17: Statement or defun catchall.
         (t
          (goto-char indent-point)
@@ -6728,11 +8551,13 @@ This function does not do any hidden buffer changes."
                     (setq step-type last-step-type)
                     (/= (point) (c-point 'boi)))))
          (cond
+
           ;; CASE 17B: continued statement
           ((and (eq step-type 'same)
                 (/= (point) indent-point))
-           (c-add-stmt-syntax 'statement-cont nil nil nil
+           (c-add-stmt-syntax 'statement-cont nil nil
                               containing-sexp paren-state))
+
           ;; CASE 17A: After a case/default label?
           ((progn
              (while (and (eq step-type 'label)
@@ -6743,17 +8568,19 @@ This function does not do any hidden buffer changes."
            (c-add-stmt-syntax (if (eq char-after-ip ?{)
                                   'statement-case-open
                                 'statement-case-intro)
-                              nil t nil containing-sexp paren-state))
+                              nil t containing-sexp paren-state))
+
           ;; CASE 17D: any old statement
           ((progn
              (while (eq step-type 'label)
                (setq step-type
                      (c-beginning-of-statement-1 containing-sexp)))
              (eq step-type 'previous))
-           (c-add-stmt-syntax 'statement nil t nil
+           (c-add-stmt-syntax 'statement nil t
                               containing-sexp paren-state)
            (if (eq char-after-ip ?{)
                (c-add-syntax 'block-open)))
+
           ;; CASE 17I: Inside a substatement block.
           ((progn
              ;; The following tests are all based on containing-sexp.
@@ -6762,10 +8589,11 @@ This function does not do any hidden buffer changes."
              (setq lim (c-most-enclosing-brace paren-state containing-sexp))
              (c-after-conditional))
            (c-backward-to-block-anchor lim)
-           (c-add-stmt-syntax 'statement-block-intro nil t nil
+           (c-add-stmt-syntax 'statement-block-intro nil t
                               lim paren-state)
            (if (eq char-after-ip ?{)
                (c-add-syntax 'block-open)))
+
           ;; CASE 17E: first statement in an in-expression block.
           ;; C.f. cases 4, 7B and 16A.
           ((setq placeholder (c-looking-at-inexpr-block
@@ -6779,54 +8607,58 @@ This function does not do any hidden buffer changes."
                (c-add-syntax tmpsymbol (point))
              (goto-char (cdr placeholder))
              (back-to-indentation)
-             (c-add-stmt-syntax tmpsymbol nil t nil
+             (c-add-stmt-syntax tmpsymbol nil t
                                 (c-most-enclosing-brace c-state-cache (point))
-                                (c-whack-state-after (point) paren-state))
+                                paren-state)
              (if (/= (point) (cdr placeholder))
                  (c-add-syntax (car placeholder))))
            (if (eq char-after-ip ?{)
                (c-add-syntax 'block-open)))
+
           ;; CASE 17F: first statement in an inline, or first
           ;; statement in a top-level defun. we can tell this is it
           ;; if there are no enclosing braces that haven't been
           ;; narrowed out by a class (i.e. don't use bod here).
           ((save-excursion
-             (save-restriction
-               (widen)
-               (c-narrow-out-enclosing-class paren-state containing-sexp)
-               (not (c-most-enclosing-brace paren-state))))
+             (or (not (setq placeholder (c-most-enclosing-brace
+                                         paren-state)))
+                 (and (progn
+                        (goto-char placeholder)
+                        (eq (char-after) ?{))
+                      (c-looking-at-decl-block (c-most-enclosing-brace
+                                                paren-state (point))
+                                               nil))))
            (c-backward-to-decl-anchor lim)
            (back-to-indentation)
            (c-add-syntax 'defun-block-intro (point)))
+
           ;; CASE 17G: First statement in a function declared inside
           ;; a normal block.  This can occur in Pike and with
           ;; e.g. the gcc extensions, but watch out for macros
           ;; followed by blocks.  C.f. cases B.3 and 16F.
           ((save-excursion
-             (and (not (c-looking-at-bos))
+             (and (not (c-at-statement-start-p))
                   (eq (c-beginning-of-statement-1 lim nil nil t) 'same)
                   (setq placeholder (point))
-                  ;; Look for a type or identifier followed by a
-                  ;; symbol, i.e. the start of a function declaration.
-                  ;; Doesn't work for declarations like "int *foo()
-                  ;; ..."; we'd need to refactor the more competent
-                  ;; analysis in `c-font-lock-declarations' for that.
-                  (c-forward-type)
-                  (progn
-                    (c-forward-syntactic-ws)
-                    (looking-at c-symbol-start))))
+                  (let ((c-recognize-typeless-decls nil))
+                    ;; Turn off recognition of constructs that lacks
+                    ;; a type in this case, since that's more likely
+                    ;; to be a macro followed by a block.
+                    (c-forward-decl-or-cast-1 (c-point 'bosws) nil nil))))
            (back-to-indentation)
            (if (/= (point) containing-sexp)
                (goto-char placeholder))
-           (c-add-stmt-syntax 'defun-block-intro nil t nil
+           (c-add-stmt-syntax 'defun-block-intro nil t
                               lim paren-state))
-          ;; CASE 17H: First statement in a block.  C.f. case 16C.
+
+          ;; CASE 17H: First statement in a block.
           (t
            ;; If the block is preceded by a case/switch label on the
            ;; same line, we anchor at the first preceding label at
            ;; boi.  The default handling in c-add-stmt-syntax is
            ;; really fixes it better, but we do like this to keep the
            ;; indentation compatible with version 5.28 and earlier.
+           ;; C.f. case 16C.
            (while (and (/= (setq placeholder (point)) (c-point 'boi))
                        (eq (c-beginning-of-statement-1 lim) 'label)))
            (goto-char placeholder)
@@ -6835,19 +8667,22 @@ This function does not do any hidden buffer changes."
              (goto-char containing-sexp)
              ;; c-backward-to-block-anchor not necessary here; those
              ;; situations are handled in case 17I above.
-             (c-add-stmt-syntax 'statement-block-intro nil t nil
+             (c-add-stmt-syntax 'statement-block-intro nil t
                                 lim paren-state))
            (if (eq char-after-ip ?{)
                (c-add-syntax 'block-open)))
           ))
         )
+
        ;; now we need to look at any modifiers
        (goto-char indent-point)
        (skip-chars-forward " \t")
+
        ;; are we looking at a comment only line?
        (when (and (looking-at c-comment-start-regexp)
                   (/= (c-forward-token-2 0 nil (c-point 'eol)) 0))
          (c-append-syntax 'comment-intro))
+
        ;; we might want to give additional offset to friends (in C++).
        (when (and c-opt-friend-key
                   (looking-at c-opt-friend-key))
@@ -6856,9 +8691,9 @@ This function does not do any hidden buffer changes."
        ;; Set syntactic-relpos.
        (let ((p c-syntactic-context))
          (while (and p
-                     (if (integerp (car-safe (cdr-safe (car p))))
+                     (if (integerp (c-langelem-pos (car p)))
                          (progn
-                           (setq syntactic-relpos (car (cdr (car p))))
+                           (setq syntactic-relpos (c-langelem-pos (car p)))
                            nil)
                        t))
            (setq p (cdr p))))
@@ -6897,8 +8732,9 @@ This function does not do any hidden buffer changes."
                ;; we add cpp-define-intro to get the extra
                ;; indentation of the #define body.
                (c-add-syntax 'cpp-define-intro)))))
+
        ;; return the syntax
-       c-syntactic-context))))
+       c-syntactic-context)))
 
 \f
 ;; Indentation calculation.
@@ -6906,44 +8742,118 @@ This function does not do any hidden buffer changes."
 (defun c-evaluate-offset (offset langelem symbol)
   ;; offset can be a number, a function, a variable, a list, or one of
   ;; the symbols + or -
-  (cond
-   ((eq offset '+)         c-basic-offset)
-   ((eq offset '-)         (- c-basic-offset))
-   ((eq offset '++)        (* 2 c-basic-offset))
-   ((eq offset '--)        (* 2 (- c-basic-offset)))
-   ((eq offset '*)         (/ c-basic-offset 2))
-   ((eq offset '/)         (/ (- c-basic-offset) 2))
-   ((numberp offset)       offset)
-   ((functionp offset)     (c-evaluate-offset
-                           (funcall offset
-                                    (cons (car langelem)
-                                          (car-safe (cdr langelem))))
-                           langelem symbol))
-   ((vectorp offset)       offset)
-   ((null offset)          nil)
-   ((listp offset)
-    (if (eq (car offset) 'quote)
-       (error
-"Setting in c-offsets-alist element \"(%s . '%s)\" was mistakenly quoted"
-         symbol (cadr offset)))
-    (let (done)
-      (while (and (not done) offset)
-       (setq done (c-evaluate-offset (car offset) langelem symbol)
-             offset (cdr offset)))
-      (if (and c-strict-syntax-p (not done))
-         (c-benign-error "No offset found for syntactic symbol %s" symbol))
-      done))
-   (t (symbol-value offset))
-   ))
+  ;;
+  ;; This function might do hidden buffer changes.
+  (let ((res
+        (cond
+         ((numberp offset) offset)
+         ((vectorp offset) offset)
+         ((null offset)    nil)
+
+         ((eq offset '+)   c-basic-offset)
+         ((eq offset '-)   (- c-basic-offset))
+         ((eq offset '++)  (* 2 c-basic-offset))
+         ((eq offset '--)  (* 2 (- c-basic-offset)))
+         ((eq offset '*)   (/ c-basic-offset 2))
+         ((eq offset '/)   (/ (- c-basic-offset) 2))
+
+         ((functionp offset)
+          (c-evaluate-offset
+           (funcall offset
+                    (cons (c-langelem-sym langelem)
+                          (c-langelem-pos langelem)))
+           langelem symbol))
+
+         ((listp offset)
+          (cond
+           ((eq (car offset) 'quote)
+            (c-benign-error "The offset %S for %s was mistakenly quoted"
+                            offset symbol)
+            nil)
+
+           ((memq (car offset) '(min max))
+            (let (res val (method (car offset)))
+              (setq offset (cdr offset))
+              (while offset
+                (setq val (c-evaluate-offset (car offset) langelem symbol))
+                (cond
+                 ((not val))
+                 ((not res)
+                  (setq res val))
+                 ((integerp val)
+                  (if (vectorp res)
+                      (c-benign-error "\
+Error evaluating offset %S for %s: \
+Cannot combine absolute offset %S with relative %S in `%s' method"
+                                      (car offset) symbol res val method)
+                    (setq res (funcall method res val))))
+                 (t
+                  (if (integerp res)
+                      (c-benign-error "\
+Error evaluating offset %S for %s: \
+Cannot combine relative offset %S with absolute %S in `%s' method"
+                                      (car offset) symbol res val method)
+                    (setq res (vector (funcall method (aref res 0)
+                                               (aref val 0)))))))
+                (setq offset (cdr offset)))
+              res))
+
+           ((eq (car offset) 'add)
+            (let (res val)
+              (setq offset (cdr offset))
+              (while offset
+                (setq val (c-evaluate-offset (car offset) langelem symbol))
+                (cond
+                 ((not val))
+                 ((not res)
+                  (setq res val))
+                 ((integerp val)
+                  (if (vectorp res)
+                      (setq res (vector (+ (aref res 0) val)))
+                    (setq res (+ res val))))
+                 (t
+                  (if (vectorp res)
+                      (c-benign-error "\
+Error evaluating offset %S for %s: \
+Cannot combine absolute offsets %S and %S in `add' method"
+                                      (car offset) symbol res val)
+                    (setq res val))))  ; Override.
+                (setq offset (cdr offset)))
+              res))
+
+           (t
+            (let (res)
+              (when (eq (car offset) 'first)
+                (setq offset (cdr offset)))
+              (while (and (not res) offset)
+                (setq res (c-evaluate-offset (car offset) langelem symbol)
+                      offset (cdr offset)))
+              res))))
+
+         ((and (symbolp offset) (boundp offset))
+          (symbol-value offset))
+
+         (t
+          (c-benign-error "Unknown offset format %S for %s" offset symbol)
+          nil))))
+
+    (if (or (null res) (integerp res)
+           (and (vectorp res) (= (length res) 1) (integerp (aref res 0))))
+       res
+      (c-benign-error "Error evaluating offset %S for %s: Got invalid value %S"
+                     offset symbol res)
+      nil)))
 
 (defun c-calc-offset (langelem)
   ;; Get offset from LANGELEM which is a list beginning with the
   ;; syntactic symbol and followed by any analysis data it provides.
   ;; That data may be zero or more elements, but if at least one is
-  ;; given then the first is the relpos (or nil).  The symbol is
-  ;; matched against `c-offsets-alist' and the offset calculated from
-  ;; that is returned.
-  (let* ((symbol (car langelem))
+  ;; given then the first is the anchor position (or nil).  The symbol
+  ;; is matched against `c-offsets-alist' and the offset calculated
+  ;; from that is returned.
+  ;;
+  ;; This function might do hidden buffer changes.
+  (let* ((symbol (c-langelem-sym langelem))
         (match  (assq symbol c-offsets-alist))
         (offset (cdr-safe match)))
     (if match
@@ -6961,21 +8871,26 @@ This function does not do any hidden buffer changes."
 (defun c-get-offset (langelem)
   ;; This is a compatibility wrapper for `c-calc-offset' in case
   ;; someone is calling it directly.  It takes an old style syntactic
-  ;; element on the form (SYMBOL . RELPOS) and converts it to the new
-  ;; list form.
-  (if (cdr langelem)
-      (c-calc-offset (list (car langelem) (cdr langelem)))
+  ;; element on the form (SYMBOL . ANCHOR-POS) and converts it to the
+  ;; new list form.
+  ;;
+  ;; This function might do hidden buffer changes.
+  (if (c-langelem-pos langelem)
+      (c-calc-offset (list (c-langelem-sym langelem)
+                          (c-langelem-pos langelem)))
     (c-calc-offset langelem)))
 
 (defun c-get-syntactic-indentation (langelems)
   ;; Calculate the syntactic indentation from a syntactic description
   ;; as returned by `c-guess-syntax'.
   ;;
-  ;; Note that topmost-intro always has a relpos at bol, for
+  ;; Note that topmost-intro always has an anchor position at bol, for
   ;; historical reasons.  It's often used together with other symbols
   ;; that has more sane positions.  Since we always use the first
-  ;; found relpos, we rely on that these other symbols always precede
-  ;; topmost-intro in the LANGELEMS list.
+  ;; found anchor position, we rely on that these other symbols always
+  ;; precede topmost-intro in the LANGELEMS list.
+  ;;
+  ;; This function might do hidden buffer changes.
   (let ((indent 0) anchor)
 
     (while langelems
@@ -6997,9 +8912,7 @@ This function does not do any hidden buffer changes."
          ;; Use the anchor position from the first syntactic
          ;; element with one.
          (unless anchor
-           (let ((relpos (car-safe (cdr (car langelems)))))
-             (if relpos
-                 (setq anchor relpos)))))
+           (setq anchor (c-langelem-pos (car langelems)))))
 
        (setq langelems (cdr langelems))))
 
index 95e4e5226f0c4b5b43a3b73b67792ee9422a8507..e5dcecf459f8e39e8b84e6c68692d464784ffc29 100644 (file)
@@ -1,6 +1,6 @@
 ;;; cc-fonts.el --- font lock support for CC Mode
 
-;; Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+;; Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
 
 ;; Authors:    2003- Alan Mackenzie
 ;;             2002- Martin Stjernholm
@@ -30,8 +30,8 @@
 
 ;; Some comments on the use of faces:
 ;;
-;; o  `c-label-face-name' is either `font-lock-constant-face' (in Emacs
-;;    20 and later), or `font-lock-reference-face'.
+;; o  `c-label-face-name' is either `font-lock-constant-face' (in
+;;    Emacs), or `font-lock-reference-face'.
 ;;
 ;; o  `c-constant-face-name', `c-reference-face-name' and
 ;;    `c-doc-markup-face-name' are essentially set up like
 ;;    documentation are actually comments in these languages, as opposed
 ;;    to elisp).
 ;;
-;; o  `c-invalid-face-name' is `font-lock-warning-face' in Emacs.  In
-;;    older XEmacs there's no corresponding standard face, so there
-;;    it's mapped to a special `c-invalid-face'.
-;;
 ;; TBD: We should probably provide real faces for the above uses and
 ;; instead initialize them from the standard faces.
 
 (cc-bytecomp-defvar c-reference-face-name)
 (cc-bytecomp-defun c-fontify-recorded-types-and-refs)
 (cc-bytecomp-defun c-font-lock-declarators)
-(cc-bytecomp-defun c-font-lock-objc-iip-decl)
 (cc-bytecomp-defun c-font-lock-objc-method)
 (cc-bytecomp-defun c-font-lock-invalid-string)
 
-;; Emacs 19 doesn't have `defface'.  This "replacement" leaves a lot
-;; to be wished for but at least it avoids any errors.
-(cc-eval-when-compile
-  (or (fboundp 'defface)
-      (cc-bytecomp-defmacro defface (face spec doc &rest args)
-       `(make-face ',face))))
-
 \f
 ;; Note that font-lock in XEmacs doesn't expand face names as
 ;; variables, so we have to use the (eval . FORM) in the font lock
         ;; XEmacs has a font-lock-preprocessor-face.
         'font-lock-preprocessor-face)
        ((c-face-name-p 'font-lock-builtin-face)
-        ;; In Emacs 20 and later font-lock-builtin-face has
-        ;; traditionally been used for preprocessor directives.
+        ;; In Emacs font-lock-builtin-face has traditionally been
+        ;; used for preprocessor directives.
         'font-lock-builtin-face)
        (t
         'font-lock-reference-face)))
 (defconst c-constant-face-name
   (if (and (c-face-name-p 'font-lock-constant-face)
           (eq font-lock-constant-face 'font-lock-constant-face))
-      ;; This doesn't exist in XEmacs <= 20 and some earlier versions
-      ;; of XEmacs 21.
+      ;; This doesn't exist in some earlier versions of XEmacs 21.
       'font-lock-constant-face
     c-label-face-name))
 
 (defconst c-reference-face-name
-  (if (and (c-face-name-p 'font-lock-reference-face)
-          (eq font-lock-reference-face 'font-lock-reference-face))
-      ;; This is considered obsolete in Emacs 20 and later, but it
-      ;; still maps well to this use.  (Another reason to do this is
-      ;; to get unique faces for the test suite.)
-      'font-lock-reference-face
-    c-label-face-name))
+  (with-no-warnings
+   (if (and (c-face-name-p 'font-lock-reference-face)
+           (eq font-lock-reference-face 'font-lock-reference-face))
+       ;; This is considered obsolete in Emacs, but it still maps well
+       ;; to this use.  (Another reason to do this is to get unique
+       ;; faces for the test suite.)
+       'font-lock-reference-face
+     c-label-face-name)))
 
 ;; This should not mapped to a face that also is used to fontify things
 ;; that aren't comments or string literals.
         'font-lock-doc-markup-face
     c-label-face-name))
 
-(defconst c-invalid-face-name
-  (if (c-face-name-p 'font-lock-warning-face)
-      ;; Emacs >= 20 and XEmacs >= 21 has a font-lock-warning-face.
-      'font-lock-warning-face
-    ;; Otherwise we provide a face.
-    'c-invalid-face))
-
-(unless (c-face-name-p c-invalid-face-name)
-  (defconst c-invalid-face 'c-invalid-face) ; Necessary in Emacs 19.
-  ;; This face should be called `c-invalid' for consistency with the
-  ;; rest of emacs, but as it's only used in very old versions of Emacs,
-  ;; we leave it unchanged (the face-alias mechanism doesn't exist in
-  ;; those old versions).
-  (defface c-invalid-face
-    '((((class color) (background light)) (:foreground "red1"))
-      (((class color)) (:foreground "hotpink"))
-      (t (:inverse-video t)))
-    "Face used to highlight invalid syntax."
-    :group 'c-fonts))
-
-;; To make hard spaces visible an inverted version of
-;; `c-invalid-face-name' is used.  Since font-lock in Emacs expands
-;; all face names in `font-lock-keywords' as variables we need to have
-;; a variable for it.
-(defconst c-nonbreakable-space-face 'c-nonbreakable-space)
+(defconst c-negation-char-face-name
+  (if (c-face-name-p 'font-lock-negation-char-face)
+      ;; Emacs 22 has a special face for negation chars.
+      'font-lock-negation-char-face))
 
 (cc-bytecomp-defun face-inverse-video-p) ; Only in Emacs.
 (cc-bytecomp-defun face-property-instance) ; Only in XEmacs.
 (defun c-make-inverse-face (oldface newface)
   ;; Emacs and XEmacs have completely different face manipulation
   ;; routines. :P
-  ;;
-  ;; This function does not do any hidden buffer changes
   (copy-face oldface newface)
   (cond ((fboundp 'face-inverse-video-p)
-        ;; Emacs 20 and later.  This only looks at the inverse flag
-        ;; in the current frame.  Other display configurations might
-        ;; be different, but it can only show if the same Emacs has
-        ;; frames on e.g. a color and a monochrome display
-        ;; simultaneously.
+        ;; Emacs.  This only looks at the inverse flag in the current
+        ;; frame.  Other display configurations might be different,
+        ;; but it can only show if the same Emacs has frames on
+        ;; e.g. a color and a monochrome display simultaneously.
         (unless (face-inverse-video-p oldface)
           (invert-face newface)))
        ((fboundp 'face-property-instance)
         ;; XEmacs.  Same pitfall here.
         (unless (face-property-instance oldface 'reverse)
-          (invert-face newface)))
-       (t
-        ;; Emacs 19 has no inverse flag at all.  Just inverse the
-        ;; face and hope it wasn't inversed already.
-        (invert-face newface))))
+          (invert-face newface)))))
 
 (eval-and-compile
   ;; We need the following functions during compilation since they're
     ;; additional font-lock property, or else the font-lock package
     ;; won't recognize it as fontified and might override it
     ;; incorrectly.
+    ;;
+    ;; This function does a hidden buffer change.
     (if (fboundp 'font-lock-set-face)
        ;; Note: This function has no docstring in XEmacs so it might be
        ;; considered internal.
 
   (defmacro c-remove-font-lock-face (from to)
     ;; This is the inverse of `c-put-font-lock-face'.
+    ;;
+    ;; This function does a hidden buffer change.
     (if (fboundp 'font-lock-remove-face)
        `(font-lock-remove-face ,from ,to)
       `(remove-text-properties ,from ,to '(face nil))))
     ;; Put `font-lock-string-face' on a string.  The surrounding
     ;; quotes are included in Emacs but not in XEmacs.  The passed
     ;; region should include them.
+    ;;
+    ;; This function does a hidden buffer change.
     (if (featurep 'xemacs)
        `(c-put-font-lock-face (1+ ,from) (1- ,to) 'font-lock-string-face)
       `(c-put-font-lock-face ,from ,to 'font-lock-string-face)))
     ;; Like `let', but additionally activates `c-record-type-identifiers'
     ;; and `c-record-ref-identifiers', and fontifies the recorded ranges
     ;; accordingly on exit.
+    ;;
+    ;; This function does hidden buffer changes.
     `(let ((c-record-type-identifiers t)
           c-record-ref-identifiers
           ,@varlist)
        (prog1 (progn ,@body)
         (c-fontify-recorded-types-and-refs))))
   (put 'c-fontify-types-and-refs 'lisp-indent-function 1)
-  (eval-after-load "edebug" '(def-edebug-spec c-fontify-types-and-refs let*))
 
   (defun c-skip-comments-and-strings (limit)
     ;; If the point is within a region fontified as a comment or
     ;; string literal skip to the end of it or to LIMIT, whichever
     ;; comes first, and return t.  Otherwise return nil.  The match
     ;; data is not clobbered.
+    ;;
+    ;; This function might do hidden buffer changes.
     (when (c-got-face-at (point) c-literal-faces)
       (while (progn
               (goto-char (next-single-property-change
                    (c-got-face-at (point) c-literal-faces))))
       t))
 
+  (defun c-make-syntactic-matcher (regexp)
+    ;; Returns a byte compiled function suitable for use in place of a
+    ;; regexp string in a `font-lock-keywords' matcher, except that
+    ;; only matches outside comments and string literals count.
+    ;;
+    ;; This function does not do any hidden buffer changes, but the
+    ;; generated functions will.  (They are however used in places
+    ;; covered by the font-lock context.)
+    (byte-compile
+     `(lambda (limit)
+       (let (res)
+         (while (and (setq res (re-search-forward ,regexp limit t))
+                     (progn
+                       (goto-char (match-beginning 0))
+                       (or (c-skip-comments-and-strings limit)
+                           (progn
+                             (goto-char (match-end 0))
+                             nil)))))
+         res))))
+
   (defun c-make-font-lock-search-function (regexp &rest highlights)
     ;; This function makes a byte compiled function that works much like
     ;; a matcher element in `font-lock-keywords'.  It cuts out a little
     ;; the anchored matcher forms.
     ;;
     ;; This function does not do any hidden buffer changes, but the
-    ;; generated functions will.  They are however used in places
-    ;; covered by the font-lock context.
+    ;; generated functions will.  (They are however used in places
+    ;; covered by the font-lock context.)
 
     ;; Note: Replace `byte-compile' with `eval' to debug the generated
     ;; lambda easier.
     (byte-compile
      `(lambda (limit)
-       (let (-match-end-pos-
-             ;; The font-lock package in Emacs is known to clobber
+       (let (;; The font-lock package in Emacs is known to clobber
              ;; `parse-sexp-lookup-properties' (when it exists).
              (parse-sexp-lookup-properties
               (cc-eval-when-compile
                 (boundp 'parse-sexp-lookup-properties))))
          (while (re-search-forward ,regexp limit t)
-           (setq -match-end-pos- (point))
            (unless (progn
                      (goto-char (match-beginning 0))
                      (c-skip-comments-and-strings limit))
-             (goto-char -match-end-pos-)
+             (goto-char (match-end 0))
              ,@(mapcar
                 (lambda (highlight)
                   (if (integerp (car highlight))
                       (progn
-                        (unless (nth 2 highlight)
+                        (unless (eq (nth 2 highlight) t)
                           (error
-                           "The override flag must currently be set in %s"
+                           "The override flag must currently be t in %s"
                            highlight))
                         (when (nth 3 highlight)
                           (error
                        (save-match-data ,(car highlight))
                        ,(nth 2 highlight))))
                 highlights))))
-       nil))))
+       nil)))
+
+  (eval-after-load "edebug"
+    '(progn
+       (def-edebug-spec c-fontify-types-and-refs let*)
+       (def-edebug-spec c-make-syntactic-matcher t)
+       ;; If there are literal quoted or backquoted highlight specs in
+       ;; the call to `c-make-font-lock-search-function' then let's
+       ;; instrument the forms in them.
+       (def-edebug-spec c-make-font-lock-search-function
+        (form &rest &or ("quote" (&rest form)) ("`" (&rest form)) form)))))
 
 (defun c-fontify-recorded-types-and-refs ()
-  ;; Converts the ranges recorded on `c-record-type-identifiers' and
+  ;; Convert the ranges recorded on `c-record-type-identifiers' and
   ;; `c-record-ref-identifiers' to fontification.
+  ;;
+  ;; This function does hidden buffer changes.
   (let (elem)
     (while (consp c-record-type-identifiers)
       (setq elem (car c-record-type-identifiers)
@@ -388,108 +387,123 @@ stuff.  Used on level 1 and higher."
 
   t `(,@(when (c-lang-const c-opt-cpp-prefix)
          (let* ((noncontinued-line-end "\\(\\=\\|\\(\\=\\|[^\\]\\)[\n\r]\\)")
-                (ncle-depth (c-regexp-opt-depth noncontinued-line-end))
-                (sws-depth (c-lang-const c-syntactic-ws-depth)))
+                (ncle-depth (regexp-opt-depth noncontinued-line-end))
+                (sws-depth (c-lang-const c-syntactic-ws-depth))
+                (nsws-depth (c-lang-const c-nonempty-syntactic-ws-depth)))
+
            `(;; The stuff after #error and #warning is a message, so
              ;; fontify it as a string.
-             (,(concat noncontinued-line-end
-                       (c-lang-const c-opt-cpp-prefix)
-                       "\\(error\\|warning\\)\\>\\s *\\(.*\\)$")
-              ,(+ ncle-depth 2) font-lock-string-face)
+             ,@(when (c-lang-const c-cpp-message-directives)
+                 (let* ((re (c-make-keywords-re nil
+                              (c-lang-const c-cpp-message-directives)))
+                        (re-depth (regexp-opt-depth re)))
+                   `((,(concat noncontinued-line-end
+                               (c-lang-const c-opt-cpp-prefix)
+                               re
+                               "\\s +\\(.*\\)$")
+                      ,(+ ncle-depth re-depth 1) font-lock-string-face))))
 
              ;; Fontify filenames in #include <...> as strings.
-             (,(concat noncontinued-line-end
-                       (c-lang-const c-opt-cpp-prefix)
-                       "\\(import\\|include\\)\\>"
-                       (c-lang-const c-syntactic-ws)
-                       "\\(<[^>\n\r]*>?\\)")
-              (,(+ ncle-depth sws-depth 2)
-               font-lock-string-face)
-
-              ;; Use an anchored matcher to put paren syntax on the brackets.
-              (,(byte-compile
-                 `(lambda (limit)
-                    (let ((beg-pos
-                           (match-beginning ,(+ ncle-depth sws-depth 2)))
-                          (end-pos
-                           (1- (match-end ,(+ ncle-depth sws-depth 2)))))
-                      (if (eq (char-after end-pos) ?>)
-                          (progn
-                            (c-mark-<-as-paren beg-pos)
-                            (c-mark->-as-paren end-pos))
-                        (c-clear-char-property beg-pos 'syntax-table)))
-                    nil))))
+             ,@(when (c-lang-const c-cpp-include-directives)
+                 (let* ((re (c-make-keywords-re nil
+                              (c-lang-const c-cpp-include-directives)))
+                        (re-depth (regexp-opt-depth re)))
+                   `((,(concat noncontinued-line-end
+                               (c-lang-const c-opt-cpp-prefix)
+                               re
+                               (c-lang-const c-syntactic-ws)
+                               "\\(<[^>\n\r]*>?\\)")
+                      (,(+ ncle-depth re-depth sws-depth 1)
+                       font-lock-string-face)
+
+                      ;; Use an anchored matcher to put paren syntax
+                      ;; on the brackets.
+                      (,(byte-compile
+                         `(lambda (limit)
+                            (let ((beg (match-beginning
+                                        ,(+ ncle-depth re-depth sws-depth 1)))
+                                  (end (1- (match-end ,(+ ncle-depth re-depth
+                                                          sws-depth 1)))))
+                              (if (eq (char-after end) ?>)
+                                  (progn
+                                    (c-mark-<-as-paren beg)
+                                    (c-mark->-as-paren end))
+                                (c-clear-char-property beg 'syntax-table)))
+                            nil)))))))
 
              ;; #define.
-             (,(c-make-font-lock-search-function
-                (concat
-                 noncontinued-line-end
-                 (c-lang-const c-opt-cpp-prefix)
-                 "define\\>"
-                 (c-lang-const c-syntactic-ws)
-                 "\\(" (c-lang-const c-symbol-key) "\\)" ; 1 + ncle + sws
-                 (concat "\\("         ; 2 + ncle + sws + c-sym-key
-                         ;; Macro with arguments - a "function".
-                         "\\(\(\\)"    ; 3 + ncle + sws + c-sym-key
-                         "\\|"
-                         ;; Macro without arguments - a "variable".
-                         "\\([^\(]\\|$\\)"
-                         "\\)"))
-                `((if (match-beginning ,(+ 3 ncle-depth sws-depth
-                                           (c-lang-const c-symbol-key-depth)))
-                      ;; "Function".  Fontify the name and the arguments.
-                      (save-restriction
-                        (c-put-font-lock-face
-                         (match-beginning ,(+ 1 ncle-depth sws-depth))
-                         (match-end ,(+ 1 ncle-depth sws-depth))
-                         'font-lock-function-name-face)
-                        (goto-char (match-end
-                                    ,(+ 3 ncle-depth sws-depth
-                                        (c-lang-const c-symbol-key-depth))))
-
-                        (narrow-to-region (point-min) limit)
-                        (while (and
-                                (progn
-                                  (c-forward-syntactic-ws)
-                                  (looking-at c-symbol-key))
-                                (progn
-                                  (c-put-font-lock-face
-                                   (match-beginning 0) (match-end 0)
-                                   'font-lock-variable-name-face)
-                                  (goto-char (match-end 0))
-                                  (c-forward-syntactic-ws)
-                                  (eq (char-after) ?,)))
-                          (forward-char)))
-
-                    ;; "Variable".
-                    (c-put-font-lock-face
-                     (match-beginning ,(+ 1 ncle-depth sws-depth))
-                     (match-end ,(+ 1 ncle-depth sws-depth))
-                     'font-lock-variable-name-face)))))
+             ,@(when (c-lang-const c-opt-cpp-macro-define)
+                 `((,(c-make-font-lock-search-function
+                      (concat
+                       noncontinued-line-end
+                       (c-lang-const c-opt-cpp-prefix)
+                       (c-lang-const c-opt-cpp-macro-define)
+                       (c-lang-const c-nonempty-syntactic-ws)
+                       "\\(" (c-lang-const ; 1 + ncle + nsws
+                              c-symbol-key) "\\)"
+                       (concat "\\("   ; 2 + ncle + nsws + c-sym-key
+                               ;; Macro with arguments - a "function".
+                               "\\(\(\\)" ; 3 + ncle + nsws + c-sym-key
+                               "\\|"
+                               ;; Macro without arguments - a "variable".
+                               "\\([^\(]\\|$\\)"
+                               "\\)"))
+                      `((if (match-beginning
+                             ,(+ 3 ncle-depth nsws-depth
+                                 (c-lang-const c-symbol-key-depth)))
+
+                            ;; "Function".  Fontify the name and the arguments.
+                            (save-restriction
+                              (c-put-font-lock-face
+                               (match-beginning ,(+ 1 ncle-depth nsws-depth))
+                               (match-end ,(+ 1 ncle-depth nsws-depth))
+                               'font-lock-function-name-face)
+                              (goto-char
+                               (match-end
+                                ,(+ 3 ncle-depth nsws-depth
+                                    (c-lang-const c-symbol-key-depth))))
+
+                              (narrow-to-region (point-min) limit)
+                              (while (and
+                                      (progn
+                                        (c-forward-syntactic-ws)
+                                        (looking-at c-symbol-key))
+                                      (progn
+                                        (c-put-font-lock-face
+                                         (match-beginning 0) (match-end 0)
+                                         'font-lock-variable-name-face)
+                                        (goto-char (match-end 0))
+                                        (c-forward-syntactic-ws)
+                                        (eq (char-after) ?,)))
+                                (forward-char)))
+
+                          ;; "Variable".
+                          (c-put-font-lock-face
+                           (match-beginning ,(+ 1 ncle-depth nsws-depth))
+                           (match-end ,(+ 1 ncle-depth nsws-depth))
+                           'font-lock-variable-name-face)))))))
 
              ;; Fontify cpp function names in preprocessor
              ;; expressions in #if and #elif.
-             ,(when (c-lang-const c-cpp-defined-fns)
-                `(,(c-make-font-lock-search-function
-                    (concat noncontinued-line-end
-                            (c-lang-const c-opt-cpp-prefix)
-                            "\\(if\\|elif\\)\\>" ; 1 + ncle-depth
-                            ;; Match the whole logical line to look
-                            ;; for the functions in.
-                            "\\(\\\\\\(.\\|[\n\r]\\)\\|[^\n\r]\\)*")
-                    `((let ((limit (match-end 0)))
-                        (while (re-search-forward
-                                ,(concat "\\<\\("
-                                         (c-regexp-opt
-                                          (c-lang-const c-cpp-defined-fns)
-                                          nil)
-                                         "\\)\\>"
-                                         "\\s *\(?")
-                                limit 'move)
-                          (c-put-font-lock-face (match-beginning 1)
-                                                (match-end 1)
-                                                c-preprocessor-face-name)))
-                      (goto-char (match-end ,(1+ ncle-depth)))))))
+             ,@(when (and (c-lang-const c-cpp-expr-directives)
+                          (c-lang-const c-cpp-expr-functions))
+                 (let ((ced-re (c-make-keywords-re t
+                                 (c-lang-const c-cpp-expr-directives)))
+                       (cef-re (c-make-keywords-re t
+                                 (c-lang-const c-cpp-expr-functions))))
+                   `((,(c-make-font-lock-search-function
+                        (concat noncontinued-line-end
+                                (c-lang-const c-opt-cpp-prefix)
+                                ced-re ; 1 + ncle-depth
+                                ;; Match the whole logical line to look
+                                ;; for the functions in.
+                                "\\(\\\\\\(.\\|[\n\r]\\)\\|[^\n\r]\\)*")
+                        `((let ((limit (match-end 0)))
+                            (while (re-search-forward ,cef-re limit 'move)
+                              (c-put-font-lock-face (match-beginning 1)
+                                                    (match-end 1)
+                                                    c-preprocessor-face-name)))
+                          (goto-char (match-end ,(1+ ncle-depth)))))))))
 
              ;; Fontify the directive names.
              (,(c-make-font-lock-search-function
@@ -500,45 +514,52 @@ stuff.  Used on level 1 and higher."
                         "\\)")
                 `(,(1+ ncle-depth) c-preprocessor-face-name t)))
 
-             ;; fontify the n in ifndef
-             (,(concat noncontinued-line-end
-                       (c-lang-const c-opt-cpp-prefix)
-                       "if\\(n\\)def\\>")
-              ,(+ ncle-depth 1) font-lock-negation-char-face prepend)
+             (eval . (list ,(c-make-syntactic-matcher
+                             (concat noncontinued-line-end
+                                     (c-lang-const c-opt-cpp-prefix)
+                                     "if\\(n\\)def\\>"))
+                           ,(+ ncle-depth 1)
+                           c-negation-char-face-name
+                           'append))
              )))
 
       ,@(when (c-major-mode-is 'pike-mode)
+         ;; Recognize hashbangs in Pike.
          `((eval . (list "\\`#![^\n\r]*"
                          0 c-preprocessor-face-name))))
 
-      ;; Make hard spaces visible through an inverted `c-invalid-face-name'.
+      ;; Make hard spaces visible through an inverted `font-lock-warning-face'.
       (eval . (list
               "\240"
               0 (progn
-                  (unless (c-face-name-p c-nonbreakable-space-face)
-                    (c-make-inverse-face c-invalid-face-name
-                                         c-nonbreakable-space-face))
-                  'c-nonbreakable-space-face)))
+                  (unless (c-face-name-p 'c-nonbreakable-space-face)
+                    (c-make-inverse-face 'font-lock-warning-face
+                                         'c-nonbreakable-space-face))
+                  ''c-nonbreakable-space-face)))
       ))
 
 (defun c-font-lock-invalid-string ()
   ;; Assuming the point is after the opening character of a string,
-  ;; fontify that char with `c-invalid-face-name' if the string
+  ;; fontify that char with `font-lock-warning-face' if the string
   ;; decidedly isn't terminated properly.
+  ;;
+  ;; This function does hidden buffer changes.
   (let ((start (1- (point))))
     (save-excursion
-      (and (nth 3 (parse-partial-sexp start (c-point 'eol)))
-          (if (c-major-mode-is '(c-mode c++-mode objc-mode pike-mode))
+      (and (eq (elt (parse-partial-sexp start (c-point 'eol)) 8) start)
+          (if (integerp c-multiline-string-start-char)
+              ;; There's no multiline string start char before the
+              ;; string, so newlines aren't allowed.
+              (not (eq (char-before start) c-multiline-string-start-char))
+            ;; Multiline strings are allowed anywhere if
+            ;; c-multiline-string-start-char is t.
+            (not c-multiline-string-start-char))
+          (if c-string-escaped-newlines
               ;; There's no \ before the newline.
               (not (eq (char-before (point)) ?\\))
-            ;; Quoted newlines aren't supported.
+            ;; Escaped newlines aren't supported.
             t)
-          (if (c-major-mode-is 'pike-mode)
-              ;; There's no # before the string, so newlines
-              ;; aren't allowed.
-              (not (eq (char-before start) ?#))
-            t)
-          (c-put-font-lock-face start (1+ start) c-invalid-face-name)))))
+          (c-put-font-lock-face start (1+ start) 'font-lock-warning-face)))))
 
 (c-lang-defconst c-basic-matchers-before
   "Font lock matchers for basic keywords, labels, references and various
@@ -566,18 +587,18 @@ casts and declarations are fontified.  Used on level 2 and higher."
          (let ((re (c-make-keywords-re nil (c-lang-const c-constant-kwds))))
            (if (c-major-mode-is 'pike-mode)
                ;; No symbol is a keyword after "->" in Pike.
-               `((eval . (list ,(concat "\\(\\=\\|\\(\\=\\|[^-]\\)[^>]\\)"
+               `((eval . (list ,(concat "\\(\\=.?\\|[^>]\\|[^-]>\\)"
                                         "\\<\\(" re "\\)\\>")
-                               3 c-constant-face-name)))
+                               2 c-constant-face-name)))
              `((eval . (list ,(concat "\\<\\(" re "\\)\\>")
                              1 c-constant-face-name))))))
 
       ;; Fontify all keywords except the primitive types.
       ,(if (c-major-mode-is 'pike-mode)
           ;; No symbol is a keyword after "->" in Pike.
-          `(,(concat "\\(\\=\\|\\(\\=\\|[^-]\\)[^>]\\)"
+          `(,(concat "\\(\\=.?\\|[^>]\\|[^-]>\\)"
                      "\\<" (c-lang-const c-regular-keywords-regexp))
-            3 font-lock-keyword-face)
+            2 font-lock-keyword-face)
         `(,(concat "\\<" (c-lang-const c-regular-keywords-regexp))
           1 font-lock-keyword-face))
 
@@ -596,9 +617,10 @@ casts and declarations are fontified.  Used on level 2 and higher."
                  ;; Search for class identifiers preceded by ".".  The
                  ;; anchored matcher takes it from there.
                  (concat (c-lang-const c-opt-identifier-concat-key)
-                         "[ \t\n\r\f\v]*"
+                         (c-lang-const c-simple-ws) "*"
                          (concat "\\("
-                                 "[" c-upper "][" (c-lang-const c-symbol-chars) "]*"
+                                 "[" c-upper "]"
+                                 "[" (c-lang-const c-symbol-chars) "]*"
                                  "\\|"
                                  "\\*"
                                  "\\)"))
@@ -612,24 +634,26 @@ casts and declarations are fontified.  Used on level 2 and higher."
                                    (< (skip-chars-backward
                                        ,(c-lang-const c-symbol-chars)) 0))
                                  (not (get-text-property (point) 'face)))
-                       (c-put-font-lock-face (point) id-end c-reference-face-name)
+                       (c-put-font-lock-face (point) id-end
+                                             c-reference-face-name)
                        (c-backward-syntactic-ws)))
                    nil
                    (goto-char (match-end 0)))))
 
            `((,(byte-compile
-                ;; Must use a function here since we match longer than we
-                ;; want to move before doing a new search.  This is not
-                ;; necessary for XEmacs >= 20 since it restarts the search
-                ;; from the end of the first highlighted submatch (something
-                ;; that causes problems in other places).
+                ;; Must use a function here since we match longer than
+                ;; we want to move before doing a new search.  This is
+                ;; not necessary for XEmacs since it restarts the
+                ;; search from the end of the first highlighted
+                ;; submatch (something that causes problems in other
+                ;; places).
                 `(lambda (limit)
                    (while (re-search-forward
                            ,(concat "\\(\\<" ; 1
                                     "\\(" (c-lang-const c-symbol-key) "\\)" ; 2
-                                    "[ \t\n\r\f\v]*"
+                                    (c-lang-const c-simple-ws) "*"
                                     (c-lang-const c-opt-identifier-concat-key)
-                                    "[ \t\n\r\f\v]*"
+                                    (c-lang-const c-simple-ws) "*"
                                     "\\)"
                                     "\\("
                                     (c-lang-const c-opt-after-id-concat-key)
@@ -660,29 +684,30 @@ casts and declarations are fontified.  Used on level 2 and higher."
                  (if (> (point) limit) (goto-char limit)))))
 
            ;; The @interface/@implementation/@protocol directives.
-           (,(concat "\\<"
-                     (c-regexp-opt
+           ,(c-make-font-lock-search-function
+             (concat "\\<"
+                     (regexp-opt
                       '("@interface" "@implementation" "@protocol")
                       t)
                      "\\>")
-            (,(byte-compile
-               (lambda (limit)
-                 (let (;; The font-lock package in Emacs is known to clobber
-                       ;; `parse-sexp-lookup-properties' (when it exists).
-                       (parse-sexp-lookup-properties
-                        (cc-eval-when-compile
-                          (boundp 'parse-sexp-lookup-properties))))
-                   (save-restriction
-                     (narrow-to-region (point-min) limit)
-                     (c-font-lock-objc-iip-decl)))
-                 nil))))))
-
-      ("\\(!\\)[^=]" 1 font-lock-negation-char-face)
+             '((c-fontify-types-and-refs
+                   (;; The font-lock package in Emacs is known to clobber
+                    ;; `parse-sexp-lookup-properties' (when it exists).
+                    (parse-sexp-lookup-properties
+                     (cc-eval-when-compile
+                       (boundp 'parse-sexp-lookup-properties))))
+                 (c-forward-objc-directive)
+                 nil)
+               (goto-char (match-beginning 0))))))
+
+      (eval . (list "\\(!\\)[^=]" 1 c-negation-char-face-name))
       ))
 
 (defun c-font-lock-complex-decl-prepare (limit)
   ;; Called before any of the matchers in `c-complex-decl-matchers'.
   ;; Nil is always returned.
+  ;;
+  ;; This function does hidden buffer changes.
 
   ;;(message "c-font-lock-complex-decl-prepare %s %s" (point) limit)
 
@@ -718,17 +743,20 @@ casts and declarations are fontified.  Used on level 2 and higher."
 
 (defun c-font-lock-<>-arglists (limit)
   ;; Fontify types and references in names containing angle bracket
-  ;; arglists from the point to LIMIT.  This will also fontify cases
-  ;; like normal function calls on the form "foo (a < b, c > d)", but
-  ;; `c-font-lock-declarations' will undo that later.  Nil is always
-  ;; returned.
+  ;; arglists from the point to LIMIT.  Note that
+  ;; `c-font-lock-declarations' already has handled many of them.  Nil
+  ;; is always returned.
+  ;;
+  ;; This function might do hidden buffer changes.
 
   (let (;; The font-lock package in Emacs is known to clobber
        ;; `parse-sexp-lookup-properties' (when it exists).
        (parse-sexp-lookup-properties
         (cc-eval-when-compile
           (boundp 'parse-sexp-lookup-properties)))
-       id-start id-end pos kwd-sym)
+       (c-parse-and-markup-<>-arglists t)
+       c-restricted-<>-arglists
+       id-start id-end id-face pos kwd-sym)
 
     (while (and (< (point) limit)
                (re-search-forward c-opt-<>-arglist-start limit t))
@@ -739,28 +767,51 @@ casts and declarations are fontified.  Used on level 2 and higher."
 
       (goto-char id-start)
       (unless (c-skip-comments-and-strings limit)
-       (setq kwd-sym nil)
-       (if (or (not (eq (get-text-property id-start 'face)
-                        'font-lock-keyword-face))
-               (when (looking-at c-opt-<>-sexp-key)
-                 (setq kwd-sym (c-keyword-sym (match-string 1)))))
+       (setq kwd-sym nil
+             c-restricted-<>-arglists nil
+             id-face (get-text-property id-start 'face))
+
+       (if (cond
+            ((eq id-face 'font-lock-type-face)
+             ;; The identifier got the type face so it has already been
+             ;; handled in `c-font-lock-declarations'.
+             nil)
+
+            ((eq id-face 'font-lock-keyword-face)
+             (when (looking-at c-opt-<>-sexp-key)
+               ;; There's a special keyword before the "<" that tells
+               ;; that it's an angle bracket arglist.
+               (setq kwd-sym (c-keyword-sym (match-string 1)))))
+
+            (t
+             ;; There's a normal identifier before the "<".  If we're not in
+             ;; a declaration context then we set `c-restricted-<>-arglists'
+             ;; to avoid recognizing templates in function calls like "foo (a
+             ;; < b, c > d)".
+             (c-backward-syntactic-ws)
+             (when (and (memq (char-before) '(?\( ?,))
+                        (not (eq (get-text-property (1- (point)) 'c-type)
+                                 'c-decl-arg-start)))
+               (setq c-restricted-<>-arglists t))
+             t))
+
            (progn
              (goto-char (1- pos))
              ;; Check for comment/string both at the identifier and
              ;; at the "<".
              (unless (c-skip-comments-and-strings limit)
 
-               (when (c-forward-<>-arglist (c-keyword-member kwd-sym
-                                                             'c-<>-type-kwds)
-                                           t)
-                 (when (and c-opt-identifier-concat-key
-                            (not (get-text-property id-start 'face)))
-                   (c-forward-syntactic-ws)
-                   (if (looking-at c-opt-identifier-concat-key)
+               (c-fontify-types-and-refs ()
+                 (when (c-forward-<>-arglist (c-keyword-member
+                                              kwd-sym 'c-<>-type-kwds))
+                   (when (and c-opt-identifier-concat-key
+                              (not (get-text-property id-start 'face)))
+                     (c-forward-syntactic-ws)
+                     (if (looking-at c-opt-identifier-concat-key)
+                         (c-put-font-lock-face id-start id-end
+                                               c-reference-face-name)
                        (c-put-font-lock-face id-start id-end
-                                             c-reference-face-name)
-                     (c-put-font-lock-face id-start id-end
-                                           'font-lock-type-face))))
+                                             'font-lock-type-face)))))
 
                (goto-char pos)))
          (goto-char pos)))))
@@ -773,6 +824,8 @@ casts and declarations are fontified.  Used on level 2 and higher."
   ;; "bar" in "int foo = 17, bar;").  Stop at LIMIT.  If TYPES is
   ;; non-nil, fontify all identifiers as types.  Nil is always
   ;; returned.
+  ;;
+  ;; This function might do hidden buffer changes.
 
   ;;(message "c-font-lock-declarators from %s to %s" (point) limit)
   (c-fontify-types-and-refs
@@ -789,7 +842,7 @@ casts and declarations are fontified.  Used on level 2 and higher."
            (let (got-identifier)
              (setq paren-depth 0)
              ;; Skip over type decl prefix operators.  (Note similar
-             ;; code in `c-font-lock-declarations'.)
+             ;; code in `c-forward-decl-or-cast-1'.)
              (while (and (looking-at c-type-decl-prefix-key)
                          (if (and (c-major-mode-is 'c++-mode)
                                   (match-beginning 2))
@@ -830,6 +883,11 @@ casts and declarations are fontified.  Used on level 2 and higher."
 
            (<= (point) limit)
 
+           (progn
+             (when (looking-at c-decl-hangon-key)
+               (c-forward-keyword-clause 1))
+             (<= (point) limit))
+
            ;; Search syntactically to the end of the declarator (";",
            ;; ",", a closen paren, eob etc) or to the beginning of an
            ;; initializer or function prototype ("=" or "\\s\(").
@@ -883,6 +941,9 @@ casts and declarations are fontified.  Used on level 2 and higher."
                             (looking-at "{"))
                        (c-safe (c-forward-sexp) t)
                      t)
+                   ;; FIXME: Should look for c-decl-end markers here;
+                   ;; we might go far into the following declarations
+                   ;; in e.g. ObjC mode (see e.g. methods-4.m).
                    (c-syntactic-re-search-forward "[;,{]" limit 'move t)
                    (backward-char)))
 
@@ -905,106 +966,50 @@ casts and declarations are fontified.  Used on level 2 and higher."
        c-reference-face-name
        font-lock-keyword-face))
 
-;; Macro used inside `c-font-lock-declarations'.  It ought to be a
-;; defsubst or perhaps even a defun, but it contains lots of free
-;; variables that refer to things inside `c-font-lock-declarations'.
-(defmacro c-fl-shift-type-backward (&optional short)
-  ;; `c-font-lock-declarations' can consume an arbitrary length list
-  ;; of types when parsing a declaration, which means that it
-  ;; sometimes consumes the identifier in the declaration as a type.
-  ;; This is used to "backtrack" and make the last type be treated
-  ;; as an identifier instead.
-  `(progn
-     ,(unless short
-       ;; These identifiers are bound only in the inner let.
-       '(setq identifier-type at-type
-              identifier-start type-start
-              identifier-end type-end))
-     (if (setq at-type (if (eq prev-at-type 'prefix)
-                          t
-                        prev-at-type))
-        (setq type-start prev-type-start
-              type-end prev-type-end)
-       (setq type-start start-pos
-            type-end start-pos))
-     ,(unless short
-       ;; These identifiers are bound only in the inner let.
-       '(setq start type-end
-              got-parens nil
-              got-identifier t
-              got-suffix t
-              got-suffix-after-parens t
-              paren-depth 0))))
-
 (defun c-font-lock-declarations (limit)
-  ;; Fontify all the declarations and casts from the point to LIMIT.
-  ;; Assumes that strings and comments have been fontified already.
-  ;; Nil is always returned.
+  ;; Fontify all the declarations, casts and labels from the point to LIMIT.
+  ;; Assumes that strings and comments have been fontified already.  Nil is
+  ;; always returned.
   ;;
-  ;; This function can make hidden buffer changes, but the font-lock
-  ;; context covers that.
+  ;; This function might do hidden buffer changes.
 
   ;;(message "c-font-lock-declarations search from %s to %s" (point) limit)
 
   (save-restriction
-    (let (start-pos
-         c-restricted-<>-arglists
-         ;; Nonzero if the `c-decl-prefix-re' match is in an arglist context,
-         ;; as opposed to a statement-level context.  The major difference is
-         ;; that "," works as declaration delimiter in an arglist context,
-         ;; whereas it only separates declarators in the same declaration in
-         ;; a statement context.  If it's nonzero then the value is the
-         ;; matched char, e.g. ?\( or ?,.
-         arglist-match
-         ;; 'decl if we're in an arglist containing declarations (but if
-         ;; `c-recognize-paren-inits' is set it might also be an initializer
-         ;; arglist), '<> if the arglist is of angle bracket type, 'other if
-         ;; it's some other arglist, or nil if not in an arglist at all.
-         arglist-type
-         ;; Set to the result of `c-forward-type'.
-         at-type
-         ;; These record the start and end of the type or possible type found
-         ;; by `c-forward-type'.  `type-start' is at the start of the first
-         ;; type token, and `type-end' is at the start of the first token
-         ;; after the type (and after any specifiers).
-         type-start type-end
-         ;; These store `at-type', `type-start' and `type-end' of the
-         ;; identifier before the one in those variables.  The previous
-         ;; identifier might turn out to be the real type in a declaration if
-         ;; the last one has to be the declarator in it.  If `prev-at-type'
-         ;; is nil then the other variables have undefined values.
-         prev-at-type prev-type-start prev-type-end
-         ;; Whether we've found a declaration or a cast.  We might know this
-         ;; before we've found the type in it.
-         at-decl-or-cast
-         ;; Set when we need to back up to parse this as a declaration but
-         ;; not as a cast.
-         backup-if-not-cast
-         ;; Set if we've found a "typedef" specifier.  The identifiers in the
-         ;; declaration are then fontified as types.
-         at-typedef
-         ;; Set if we've found a specifier that can start a declaration where
-         ;; there's no type.
-         maybe-typeless
-         ;; The position of the next token after the closing paren of the
-         ;; last fontified cast.
+    (let (;; The position where `c-find-decl-spots' stopped.
+         start-pos
+         ;; 'decl if we're in an arglist containing declarations (but
+         ;; if `c-recognize-paren-inits' is set it might also be an
+         ;; initializer arglist), '<> if the arglist is of angle
+         ;; bracket type, 'arglist if it's some other arglist, or nil
+         ;; if not in an arglist at all.
+         context
+         ;; The position of the next token after the closing paren of
+         ;; the last detected cast.
          last-cast-end
-         ;; The same for the currently investigated cast.
-         cast-end
-         ;; The maximum of the end positions of all the checked type decl
-         ;; expressions in the successfully identified declarations.  The
-         ;; position might be either before or after the syntactic whitespace
-         ;; following the last token in the type decl expression.
+         ;; The result from `c-forward-decl-or-cast-1'.
+         decl-or-cast
+         ;; The maximum of the end positions of all the checked type
+         ;; decl expressions in the successfully identified
+         ;; declarations.  The position might be either before or
+         ;; after the syntactic whitespace following the last token
+         ;; in the type decl expression.
          (max-type-decl-end 0)
          ;; Same as `max-type-decl-*', but used when we're before
          ;; `token-pos'.
          (max-type-decl-end-before-token 0)
-         ;; Allow recording of identifier ranges in `c-forward-type' etc for
-         ;; later fontification.  Not using `c-fontify-types-and-refs' here
-         ;; since the ranges should be fontified selectively only when a
-         ;; declaration or cast has been successfully recognized.
-         c-record-type-identifiers
+         ;; Set according to the context to direct the heuristics for
+         ;; recognizing C++ templates.
+         c-restricted-<>-arglists
+         ;; Turn on recording of identifier ranges in
+         ;; `c-forward-decl-or-cast-1' and `c-forward-label' for
+         ;; later fontification.
+         (c-record-type-identifiers t)
          c-record-ref-identifiers
+         ;; Make `c-forward-type' calls mark up template arglists if
+         ;; it finds any.  That's necessary so that we later will
+         ;; stop inside them to fontify types there.
+         (c-parse-and-markup-<>-arglists t)
          ;; The font-lock package in Emacs is known to clobber
          ;; `parse-sexp-lookup-properties' (when it exists).
          (parse-sexp-lookup-properties
@@ -1024,737 +1029,162 @@ casts and declarations are fontified.  Used on level 2 and higher."
       ;; "some_other_variable" as an identifier, and the latter will not
       ;; correct itself until the second line is changed.  To avoid that we
       ;; narrow to the limit if the region to fontify is a single line.
-      (when (<= limit (c-point 'bonl))
-       (narrow-to-region
-        (point-min)
-        (save-excursion
-          ;; Narrow after any operator chars following the limit though, since
-          ;; those characters can be useful in recognizing a declaration (in
-          ;; particular the '{' that opens a function body after the header).
-          (goto-char limit)
-          (skip-chars-forward c-nonsymbol-chars)
-          (point))))
+      (narrow-to-region
+       (point-min)
+       (if (<= limit (c-point 'bonl))
+          (save-excursion
+            ;; Narrow after any operator chars following the limit though,
+            ;; since those characters can be useful in recognizing a
+            ;; declaration (in particular the '{' that opens a function body
+            ;; after the header).
+            (goto-char limit)
+            (skip-chars-forward c-nonsymbol-chars)
+            (point))
+        limit))
 
       (c-find-decl-spots
        limit
-       c-identifier-start
+       c-decl-start-re
        c-font-lock-maybe-decl-faces
 
        (lambda (match-pos inside-macro)
-        (catch 'false-alarm
-          ;; Don't do anything more if we're looking at a keyword
-          ;; that can't start a declaration.
-          (when (and (eq (get-text-property (point) 'face)
-                         'font-lock-keyword-face)
-                     (looking-at c-not-decl-init-keywords))
-            (throw 'false-alarm t))
-
-          ;; Set `arglist-match' and `arglist-type'.  Look for "<" for the
-          ;; sake of C++-style template arglists.
-          (setq arglist-match (char-before match-pos))
-          (if (memq arglist-match '(?\( ?, ?\[ ?<))
-
-              ;; Find out the type of the arglist.
-              (if (<= match-pos (point-min))
-                  (setq arglist-type 'other)
-                (let ((type (c-get-char-property (1- match-pos) 'c-type)))
-                  (cond ((eq type 'c-decl-arg-start)
-                         ;; Got a cached hit in a declaration arglist.
-                         (setq arglist-type 'decl))
-                        ((or (eq type 'c-<>-arg-sep)
-                             (eq arglist-match ?<))
-                         ;; Inside an angle bracket arglist.
-                         (setq arglist-type '<>))
-                        (type
-                         ;; Got a cached hit in some other type of arglist.
-                         (setq arglist-type 'other))
-                        ((if inside-macro
-                             (< match-pos max-type-decl-end-before-token)
-                           (< match-pos max-type-decl-end))
-                         ;; The point is within the range of a previously
-                         ;; encountered type decl expression, so the arglist
-                         ;; is probably one that contains declarations.
-                         ;; However, if `c-recognize-paren-inits' is set it
-                         ;; might also be an initializer arglist.
-                         (setq arglist-type 'decl)
-                         ;; The result of this check is cached with a char
-                         ;; property on the match token, so that we can look
-                         ;; it up again when refontifying single lines in a
-                         ;; multiline declaration.
-                         (c-put-char-property (1- match-pos)
-                                              'c-type 'c-decl-arg-start))
-                        (t
-                         (setq arglist-type 'other)))))
-
-            (setq arglist-match nil
-                  arglist-type nil))
-
-          (setq at-type nil
-                at-decl-or-cast nil
-                backup-if-not-cast nil
-                at-typedef nil
-                maybe-typeless nil
-                c-record-type-identifiers t
-                c-record-ref-identifiers nil
-                ;; `start-pos' is used below to point to the start of the
-                ;; first type, i.e. after any leading specifiers.  It might
-                ;; also point at the beginning of the preceding syntactic
-                ;; whitespace.
-                start-pos (point)
-                ;; If we're in a normal arglist context we don't want to
-                ;; recognize commas in nested angle bracket arglists since
-                ;; those commas could be part of our own arglist.
-                c-restricted-<>-arglists
-                (and c-recognize-<>-arglists
-                     (eq arglist-type 'other)))
-
-          (when (and c-restricted-<>-arglists
-                     (/= arglist-match ?,))
-            ;; We're standing at the start of a normal arglist so remove any
-            ;; angle bracket arglists containing commas that's been
-            ;; recognized inside it by the preceding slightly opportunistic
-            ;; scan in `c-font-lock-<>-arglists'.
-            (while (and (c-syntactic-re-search-forward
-                         c-opt-<>-arglist-start-in-paren nil t t)
-                        (match-beginning 1))
-              (backward-char)
-              (when (save-match-data
-                      (and (c-get-char-property (point) 'syntax-table)
-                           (not (c-forward-<>-arglist nil t))))
-                (c-remove-font-lock-face (match-beginning 2) (match-end 2))))
-            (goto-char start-pos))
-
-          ;; Check for a type, but be prepared to skip over leading
-          ;; specifiers like "static".  Unknown symbols are treated as
-          ;; possible types, but they could also be specifiers disguised
-          ;; through macros like __INLINE__, so we recognize both types and
-          ;; known specifiers after them too.
-          (while (let ((start (point))
-                       (res (unless (eq at-type t)
-                              ;; Don't look for a type if we already found a
-                              ;; positive one; we only loop for the
-                              ;; `c-specifier-key' check then.
-                              (c-forward-type))))
-
-                   (when res
-                     ;; Found a known or possible type or a prefix of a known
-                     ;; type.
-
-                     (when at-type
-                       ;; Got two identifiers with nothing but whitespace
-                       ;; between them.  That can only happen in
-                       ;; declarations.
-                       (setq at-decl-or-cast t)
-
-                       (when (eq at-type 'found)
-                         ;; If the previous identifier is a found type we
-                         ;; record it as a real one; it might be some sort of
-                         ;; alias for a prefix like "unsigned".
-                         (save-excursion
-                           (goto-char type-start)
-                           (let ((c-promote-possible-types t))
-                             (c-forward-type)))))
-
-                     (setq prev-at-type at-type
-                           prev-type-start type-start
-                           prev-type-end type-end
-                           at-type res
-                           type-start start
-                           type-end (point))
-
-                     ;; If the type isn't known we continue so that we'll
-                     ;; jump over all specifiers and type identifiers.  The
-                     ;; reason to do this for a known type prefix is to make
-                     ;; things like "unsigned INT16" work.
-                     (setq res (not (eq res t))))
-
-                   (if (looking-at c-specifier-key)
-                       ;; Found a known specifier keyword.  The specifier
-                       ;; keywords are restrictive, so we check for them
-                       ;; anywhere inside or around the type(s).  We thereby
-                       ;; avoid having special cases for specifiers like MSVC
-                       ;; '__declspec' which can come after the type.
-                       (progn
-                         (setq at-decl-or-cast t)
-                         (let ((kwd-sym (c-keyword-sym (match-string 1))))
-                           (when (c-keyword-member
-                                  kwd-sym 'c-typedef-decl-kwds)
-                             (setq at-typedef t))
-                           (when (c-keyword-member
-                                  kwd-sym 'c-typeless-decl-kwds)
-                             (setq maybe-typeless t)))
-                         (c-forward-keyword-clause)
-                         ;; Move type-end forward if we've passed a type,
-                         ;; otherwise move start-pos forward.
-                         (if at-type
-                             (setq type-end (point))
-                           (setq start-pos (point))))
-
-                     res)))
-
-          (cond
-           ((eq at-type 'prefix)
-            ;; A prefix type is itself a primitive type when it's not
-            ;; followed by another type.
-            (setq at-type t))
-
-           ((not at-type)
-            ;; Got no type but set things up to continue anyway to handle the
-            ;; various cases when a declaration doesn't start with a type.
-            (setq type-end start-pos))
-
-           ((and (eq at-type 'maybe)
-                 (c-major-mode-is 'c++-mode))
-            ;; If it's C++ then check if the last "type" ends on the form
-            ;; "foo::foo" or "foo::~foo", i.e. if it's the name of a
-            ;; (con|de)structor.
-            (save-excursion
-              (let (name end-2 end-1)
-                (goto-char type-end)
-                (c-backward-syntactic-ws)
-                (setq end-2 (point))
-                (when (and
-                       (c-simple-skip-symbol-backward)
-                       (progn
-                         (setq name
-                               (buffer-substring-no-properties (point) end-2))
-                         ;; Cheating in the handling of syntactic ws below.
-                         (< (skip-chars-backward ":~ \t\n\r\v\f") 0))
-                       (progn
-                         (setq end-1 (point))
-                         (c-simple-skip-symbol-backward))
-                       (>= (point) type-start)
-                       (equal (buffer-substring-no-properties (point) end-1)
-                              name))
-                  ;; It is a (con|de)structor name.  In that case the
-                  ;; declaration is typeless so zap out any preceding
-                  ;; identifier(s) that we might have taken as types.
-                  (goto-char type-start)
-                  (setq at-type nil
-                        prev-at-type nil
-                        type-end type-start))))))
-
-          ;; Check for and step over a type decl expression after the thing
-          ;; that is or might be a type.  This can't be skipped since we need
-          ;; the correct end position of the declarator for
-          ;; `max-type-decl-end-*'.
-          (let ((start (point)) (paren-depth 0) pos
-                ;; True if there's a non-open-paren match of
-                ;; `c-type-decl-prefix-key'.
-                got-prefix
-                ;; True if the declarator is surrounded by a parenthesis pair.
-                got-parens
-                ;; True if there is an identifier in the declarator.
-                got-identifier
-                ;; True if there's a non-close-paren match of
-                ;; `c-type-decl-suffix-key'.
-                got-suffix
-                ;; True if there's a prefix or suffix match outside the
-                ;; outermost paren pair that surrounds the declarator.
-                got-prefix-before-parens
-                got-suffix-after-parens
-                ;; True if we've parsed the type decl to a token that
-                ;; is known to end declarations in this context.
-                at-decl-end
-                ;; The earlier values of `at-type', `type-start' and
-                ;; `type-end' if we've shifted the type backwards.
-                identifier-type identifier-start identifier-end)
-            (goto-char type-end)
-
-            ;; Skip over type decl prefix operators.  (Note similar code in
-            ;; `c-font-lock-declarators'.)
-            (while (and (looking-at c-type-decl-prefix-key)
-                        (if (and (c-major-mode-is 'c++-mode)
-                                 (match-beginning 2))
-                            ;; If the second submatch matches in C++ then
-                            ;; we're looking at an identifier that's a prefix
-                            ;; only if it specifies a member pointer.
-                            (when (setq got-identifier (c-forward-name))
-                              (if (looking-at "\\(::\\)")
-                                  ;; We only check for a trailing "::" and
-                                  ;; let the "*" that should follow be
-                                  ;; matched in the next round.
-                                  (progn (setq got-identifier nil) t)
-                                ;; It turned out to be the real identifier,
-                                ;; so stop.
-                                nil))
-                          t))
-              (if (eq (char-after) ?\()
-                  (progn
-                    (setq paren-depth (1+ paren-depth))
-                    (forward-char))
-                (unless got-prefix-before-parens
-                  (setq got-prefix-before-parens (= paren-depth 0)))
-                (setq got-prefix t)
-                (goto-char (match-end 1)))
-              (c-forward-syntactic-ws))
-            (setq got-parens (> paren-depth 0))
-
-            ;; Skip over an identifier.
-            (or got-identifier
-                (and (looking-at c-identifier-start)
-                     (setq got-identifier (c-forward-name))))
-
-            ;; Skip over type decl suffix operators.
-            (while (if (looking-at c-type-decl-suffix-key)
-                       (if (eq (char-after) ?\))
-                           (when (> paren-depth 0)
-                             (setq paren-depth (1- paren-depth))
-                             (forward-char)
-                             t)
-                         (when (if (save-match-data (looking-at "\\s\("))
-                                   (c-safe (c-forward-sexp 1) t)
-                                 (goto-char (match-end 1))
-                                 t)
-                           (unless got-suffix-after-parens
-                             (setq got-suffix-after-parens (= paren-depth 0)))
-                           (setq got-suffix t)))
-                     ;; No suffix matched.  We might have matched the
-                     ;; identifier as a type and the open paren of a function
-                     ;; arglist as a type decl prefix.  In that case we
-                     ;; should "backtrack": Reinterpret the last type as the
-                     ;; identifier, move out of the arglist and continue
-                     ;; searching for suffix operators.
-                     ;;
-                     ;; Do this even if there's no preceding type, to cope
-                     ;; with old style function declarations in K&R C,
-                     ;; (con|de)structors in C++ and `c-typeless-decl-kwds'
-                     ;; style declarations.  That isn't applicable in an
-                     ;; arglist context, though.
-                     (when (and (= paren-depth 1)
-                                (not got-prefix-before-parens)
-                                (not (eq at-type t))
-                                (or prev-at-type
-                                    maybe-typeless
-                                    (when c-recognize-typeless-decls
-                                      (not arglist-type)))
-                                (setq pos (c-up-list-forward (point)))
-                                (eq (char-before pos) ?\)))
-                       (c-fl-shift-type-backward)
-                       (goto-char pos)
-                       t))
-              (c-forward-syntactic-ws))
-
-            (when (and maybe-typeless
-                       (not got-identifier)
-                       (not got-prefix)
-                       at-type
-                       (not (eq at-type t)))
-              ;; Have found no identifier but `c-typeless-decl-kwds' has
-              ;; matched so we know we're inside a declaration.  The
-              ;; preceding type must be the identifier instead.
-              (c-fl-shift-type-backward))
-
-            (setq
-             at-decl-or-cast
-             (catch 'at-decl-or-cast
-
-               (when (> paren-depth 0)
-                 ;; Encountered something inside parens that isn't matched by
-                 ;; the `c-type-decl-*' regexps, so it's not a type decl
-                 ;; expression.  Try to skip out to the same paren depth to
-                 ;; not confuse the cast check below.
-                 (c-safe (goto-char (scan-lists (point) 1 paren-depth)))
-                 (throw 'at-decl-or-cast nil))
-
-               (setq at-decl-end
-                     (looking-at (cond ((eq arglist-type '<>) "[,>]")
-                                       (arglist-type "[,\)]")
-                                       (t "[,;]"))))
-
-               ;; Now we've collected info about various characteristics of
-               ;; the construct we're looking at.  Below follows a decision
-               ;; tree based on that.  It's ordered to check more certain
-               ;; signs before less certain ones.
-
-               (if got-identifier
-                   (progn
-
-                     (when (and (or at-type maybe-typeless)
-                                (not (or got-prefix got-parens)))
-                       ;; Got another identifier directly after the type, so
-                       ;; it's a declaration.
-                       (throw 'at-decl-or-cast t))
-
-                     (when (and got-parens
-                                (not got-prefix)
-                                (not got-suffix-after-parens)
-                                (or prev-at-type maybe-typeless))
-                       ;; Got a declaration of the form "foo bar (gnu);"
-                       ;; where we've recognized "bar" as the type and "gnu"
-                       ;; as the declarator.  In this case it's however more
-                       ;; likely that "bar" is the declarator and "gnu" a
-                       ;; function argument or initializer (if
-                       ;; `c-recognize-paren-inits' is set), since the parens
-                       ;; around "gnu" would be superfluous if it's a
-                       ;; declarator.  Shift the type one step backward.
-                       (c-fl-shift-type-backward)))
-
-                 ;; Found no identifier.
-
-                 (if prev-at-type
-                     (when (or (= (point) start)
-                               (and got-suffix
-                                    (not got-prefix)
-                                    (not got-parens)))
-                       ;; Got two types after each other, so if this isn't a
-                       ;; cast then the latter probably is the identifier and
-                       ;; we should back up to the previous type.
-                       (setq backup-if-not-cast t)
-                       (throw 'at-decl-or-cast t))
-
-                   (when (eq at-type t)
-                     ;; If the type is known we know that there can't be any
-                     ;; identifier somewhere else, and it's only in
-                     ;; declarations in e.g. function prototypes and in casts
-                     ;; that the identifier may be left out.
-                     (throw 'at-decl-or-cast t))
-
-                   (when (= (point) start)
-                     ;; Only got a single identifier (parsed as a type so
-                     ;; far).
-                     (if (and
-                          ;; Check that the identifier isn't at the start of
-                          ;; an expression.
-                          at-decl-end
-                          (cond
-                           ((eq arglist-type 'decl)
-                            ;; Inside an arglist that contains declarations.
-                            ;; If K&R style declarations and parenthesis
-                            ;; style initializers aren't allowed then the
-                            ;; single identifier must be a type, else we
-                            ;; require that it's known or found (primitive
-                            ;; types are handled above).
-                            (or (and (not c-recognize-knr-p)
-                                     (not c-recognize-paren-inits))
-                                (memq at-type '(known found))))
-                           ((eq arglist-type '<>)
-                            ;; Inside a template arglist.  Accept known and
-                            ;; found types; other identifiers could just as
-                            ;; well be constants in C++.
-                            (memq at-type '(known found)))))
-                         (throw 'at-decl-or-cast t)
-                       (throw 'at-decl-or-cast nil))))
-
-                 (if (and
-                      got-parens
-                      (not got-prefix)
-                      (not arglist-type)
-                      (not (eq at-type t))
-                      (or
-                       prev-at-type
-                       maybe-typeless
-                       (when c-recognize-typeless-decls
-                         (or (not got-suffix)
-                             (not (looking-at
-                                   c-after-suffixed-type-maybe-decl-key))))))
-                     ;; Got an empty paren pair and a preceding type that
-                     ;; probably really is the identifier.  Shift the type
-                     ;; backwards to make the last one the identifier.  This
-                     ;; is analogous to the "backtracking" done inside the
-                     ;; `c-type-decl-suffix-key' loop above.
-                     ;;
-                     ;; Exception: In addition to the conditions in that
-                     ;; "backtracking" code, do not shift backward if we're
-                     ;; not looking at either `c-after-suffixed-type-decl-key'
-                     ;; or "[;,]".  Since there's no preceding type, the
-                     ;; shift would mean that the declaration is typeless.
-                     ;; But if the regexp doesn't match then we will simply
-                     ;; fall through in the tests below and not recognize it
-                     ;; at all, so it's better to try it as an abstract
-                     ;; declarator instead.
-                     (c-fl-shift-type-backward)
-
-                   ;; Still no identifier.
-
-                   (when (and got-prefix (or got-parens got-suffix))
-                     ;; Require `got-prefix' together with either
-                     ;; `got-parens' or `got-suffix' to recognize it as an
-                     ;; abstract declarator: `got-parens' only is probably an
-                     ;; empty function call.  `got-suffix' only can build an
-                     ;; ordinary expression together with the preceding
-                     ;; identifier which we've taken as a type.  We could
-                     ;; actually accept on `got-prefix' only, but that can
-                     ;; easily occur temporarily while writing an expression
-                     ;; so we avoid that case anyway.  We could do a better
-                     ;; job if we knew the point when the fontification was
-                     ;; invoked.
-                     (throw 'at-decl-or-cast t))))
-
-               (when at-decl-or-cast
-                 ;; By now we've located the type in the declaration that we
-                 ;; know we're in.
-                 (throw 'at-decl-or-cast t))
-
-               (when (and got-identifier
-                          (not arglist-type)
-                          (looking-at c-after-suffixed-type-decl-key)
-                          (if (and got-parens
-                                   (not got-prefix)
-                                   (not got-suffix)
-                                   (not (eq at-type t)))
-                              ;; Shift the type backward in the case that
-                              ;; there's a single identifier inside parens.
-                              ;; That can only occur in K&R style function
-                              ;; declarations so it's more likely that it
-                              ;; really is a function call.  Therefore we
-                              ;; only do this after
-                              ;; `c-after-suffixed-type-decl-key' has
-                              ;; matched.
-                              (progn (c-fl-shift-type-backward) t)
-                            got-suffix-after-parens))
-                 ;; A declaration according to
-                 ;; `c-after-suffixed-type-decl-key'.
-                 (throw 'at-decl-or-cast t))
-
-               (when (and (or got-prefix (not got-parens))
-                          (memq at-type '(t known)))
-                 ;; It's a declaration if a known type precedes it and it
-                 ;; can't be a function call.
-                 (throw 'at-decl-or-cast t))
-
-               ;; If we get here we can't tell if this is a type decl or a
-               ;; normal expression by looking at it alone.  (That's under
-               ;; the assumption that normal expressions always can look like
-               ;; type decl expressions, which isn't really true but the
-               ;; cases where it doesn't hold are so uncommon (e.g. some
-               ;; placements of "const" in C++) it's not worth the effort to
-               ;; look for them.)
-
-               (unless (or at-decl-end (looking-at "=[^=]"))
-                 ;; If this is a declaration it should end here or its
-                 ;; initializer(*) should start here, so check for allowed
-                 ;; separation tokens.  Note that this rule doesn't work
-                 ;; e.g. with a K&R arglist after a function header.
-                 ;;
-                 ;; *) Don't check for C++ style initializers using parens
-                 ;; since those already have been matched as suffixes.
-                 (throw 'at-decl-or-cast nil))
-
-               ;; Below are tests that only should be applied when we're
-               ;; certain to not have parsed halfway through an expression.
-
-               (when (memq at-type '(t known))
-                 ;; The expression starts with a known type so treat it as a
-                 ;; declaration.
-                 (throw 'at-decl-or-cast t))
-
-               (when (and (c-major-mode-is 'c++-mode)
-                          ;; In C++ we check if the identifier is a known
-                          ;; type, since (con|de)structors use the class name
-                          ;; as identifier.  We've always shifted over the
-                          ;; identifier as a type and then backed up again in
-                          ;; this case.
-                          identifier-type
-                          (or (memq identifier-type '(found known))
-                              (and (eq (char-after identifier-start) ?~)
-                                   ;; `at-type' probably won't be 'found for
-                                   ;; destructors since the "~" is then part
-                                   ;; of the type name being checked against
-                                   ;; the list of known types, so do a check
-                                   ;; without that operator.
-                                   (or (save-excursion
-                                         (goto-char (1+ identifier-start))
-                                         (c-forward-syntactic-ws)
-                                         (c-with-syntax-table
-                                             c-identifier-syntax-table
-                                           (looking-at c-known-type-key)))
-                                       (c-check-type (1+ identifier-start)
-                                                     identifier-end)))))
-                 (throw 'at-decl-or-cast t))
-
-               (if got-identifier
-                   (progn
-                     (when (and got-prefix-before-parens
-                                at-type
-                                (or at-decl-end (looking-at "=[^=]"))
-                                (not arglist-type)
-                                (not got-suffix))
-                       ;; Got something like "foo * bar;".  Since we're not
-                       ;; inside an arglist it would be a meaningless
-                       ;; expression because the result isn't used.  We
-                       ;; therefore choose to recognize it as a declaration.
-                       ;; Do not allow a suffix since it could then be a
-                       ;; function call.
-                       (throw 'at-decl-or-cast t))
-
-                     (when (and (or got-suffix-after-parens
-                                    (looking-at "=[^=]"))
-                                (eq at-type 'found)
-                                (not (eq arglist-type 'other)))
-                       ;; Got something like "a (*b) (c);" or "a (b) = c;".
-                       ;; It could be an odd expression or it could be a
-                       ;; declaration.  Treat it as a declaration if "a" has
-                       ;; been used as a type somewhere else (if it's a known
-                       ;; type we won't get here).
-                       (throw 'at-decl-or-cast t)))
-
-                 (when (and arglist-type
-                            (or got-prefix
-                                (and (eq arglist-type 'decl)
-                                     (not c-recognize-paren-inits)
-                                     (or got-parens got-suffix))))
-                   ;; Got a type followed by an abstract declarator.  If
-                   ;; `got-prefix' is set it's something like "a *" without
-                   ;; anything after it.  If `got-parens' or `got-suffix' is
-                   ;; set it's "a()", "a[]", "a()[]", or similar, which we
-                   ;; accept only if the context rules out expressions.
-                   (throw 'at-decl-or-cast t)))
-
-               ;; If we had a complete symbol table here (which rules out
-               ;; `c-found-types') we should return t due to the
-               ;; disambiguation rule (in at least C++) that anything that
-               ;; can be parsed as a declaration is a declaration.  Now we're
-               ;; being more defensive and prefer to highlight things like
-               ;; "foo (bar);" as a declaration only if we're inside an
-               ;; arglist that contains declarations.
-               (eq arglist-type 'decl))))
-
-          ;; Point is now after the type decl expression.
-
-          (cond
-           ;; Check for a cast.
-           ((save-excursion
-              (and
-               c-cast-parens
-
-               ;; Should be the first type/identifier in a cast paren.
-               (memq arglist-match c-cast-parens)
-
-               ;; The closing paren should follow.
-               (progn
-                 (c-forward-syntactic-ws)
-                 (looking-at "\\s\)"))
-
-               ;; There should be a primary expression after it.
-               (let (pos)
-                 (forward-char)
-                 (c-forward-syntactic-ws)
-                 (setq cast-end (point))
-                 (and (looking-at c-primary-expr-regexp)
-                      (progn
-                        (setq pos (match-end 0))
-                        (or
-                         ;; Check if the expression begins with a prefix
-                         ;; keyword.
-                         (match-beginning 2)
-                         (if (match-beginning 1)
-                             ;; Expression begins with an ambiguous operator.
-                             ;; Treat it as a cast if it's a type decl or if
-                             ;; we've recognized the type somewhere else.
-                             (or at-decl-or-cast
-                                 (memq at-type '(t known found)))
-                           ;; Unless it's a keyword, it's the beginning of a
-                           ;; primary expression.
-                           (not (looking-at c-keywords-regexp)))))
-                      ;; If `c-primary-expr-regexp' matched a nonsymbol
-                      ;; token, check that it matched a whole one so that we
-                      ;; don't e.g. confuse the operator '-' with '->'.  It's
-                      ;; ok if it matches further, though, since it e.g. can
-                      ;; match the float '.5' while the operator regexp only
-                      ;; matches '.'.
-                      (or (not (looking-at c-nonsymbol-token-regexp))
-                          (<= (match-end 0) pos))))
-
-               ;; There should either be a cast before it or something that
-               ;; isn't an identifier or close paren.
-               (/= match-pos 0)
-               (progn
-                 (goto-char (1- match-pos))
-                 (or (eq (point) last-cast-end)
-                     (progn
-                       (c-backward-syntactic-ws)
-                       (if (< (skip-syntax-backward "w_") 0)
-                           ;; It's a symbol.  Accept it only if it's one of
-                           ;; the keywords that can precede an expression
-                           ;; (without surrounding parens).
-                           (looking-at c-simple-stmt-key)
-                         (and
-                          ;; Check that it isn't a close paren (block close
-                          ;; is ok, though).
-                          (not (memq (char-before) '(?\) ?\])))
-                          ;; Check that it isn't a nonsymbol identifier.
-                          (not (c-on-identifier)))))))))
-
-            ;; Handle the cast.
-            (setq last-cast-end cast-end)
-            (when (and at-type (not (eq at-type t)))
-              (let ((c-promote-possible-types t))
-                (goto-char type-start)
-                (c-forward-type))))
-
-           (at-decl-or-cast
-            ;; We're at a declaration.  Highlight the type and the following
-            ;; declarators.
-
-            (when backup-if-not-cast
-              (c-fl-shift-type-backward t))
-
-            (when (and (eq arglist-type 'decl) (looking-at ","))
-              ;; Make sure to propagate the `c-decl-arg-start' property to
-              ;; the next argument if it's set in this one, to cope with
-              ;; interactive refontification.
-              (c-put-char-property (point) 'c-type 'c-decl-arg-start))
-
-            ;; Set `max-type-decl-end' or `max-type-decl-end-before-token'
-            ;; under the assumption that we're after the first type decl
-            ;; expression in the declaration now.  That's not really true; we
-            ;; could also be after a parenthesized initializer expression in
-            ;; C++, but this is only used as a last resort to slant ambiguous
-            ;; expression/declarations, and overall it's worth the risk to
-            ;; occasionally fontify an expression as a declaration in an
-            ;; initializer expression compared to getting ambiguous things in
-            ;; normal function prototypes fontified as expressions.
-            (if inside-macro
-                (when (> (point) max-type-decl-end-before-token)
-                  (setq max-type-decl-end-before-token (point)))
-              (when (> (point) max-type-decl-end)
-                (setq max-type-decl-end (point))))
-
-            (when (and at-type (not (eq at-type t)))
-              (let ((c-promote-possible-types t))
-                (goto-char type-start)
-                (c-forward-type)))
-
-            (goto-char type-end)
-
-            (let ((decl-list
-                   (if arglist-type
-                       ;; Should normally not fontify a list of declarators
-                       ;; inside an arglist, but the first argument in the
-                       ;; ';' separated list of a "for" statement is an
-                       ;; exception.
-                       (when (and (eq arglist-match ?\() (/= match-pos 0))
-                         (save-excursion
-                           (goto-char (1- match-pos))
-                           (c-backward-syntactic-ws)
-                           (and (c-simple-skip-symbol-backward)
-                                (looking-at c-paren-stmt-key))))
-                     t)))
-
-              ;; Fix the `c-decl-id-start' or `c-decl-type-start' property
-              ;; before the first declarator if it's a list.
-              ;; `c-font-lock-declarators' handles the rest.
-              (when decl-list
-                (save-excursion
-                  (c-backward-syntactic-ws)
-                  (unless (bobp)
-                    (c-put-char-property (1- (point)) 'c-type
-                                         (if at-typedef
-                                             'c-decl-type-start
-                                           'c-decl-id-start)))))
-
-              (c-font-lock-declarators (point-max) decl-list at-typedef)))
-
-           (t
-            ;; False alarm.  Skip the fontification done below.
-            (throw 'false-alarm t)))
-
-          ;; A cast or declaration has been successfully identified, so do
-          ;; all the fontification of types and refs that's been recorded by
-          ;; the calls to `c-forward-type' and `c-forward-name' above.
-          (c-fontify-recorded-types-and-refs)
-          nil)))
+        (setq start-pos (point))
+        (when
+         ;; The result of the form below is true when we don't recognize a
+         ;; declaration or cast.
+         (if (and (eq (get-text-property (point) 'face)
+                      'font-lock-keyword-face)
+                  (looking-at c-not-decl-init-keywords))
+             ;; Don't do anything more if we're looking at a keyword that
+             ;; can't start a declaration.
+             t
+
+           ;; Set `context'.  Look for "<" for the sake of C++-style template
+           ;; arglists.
+           (if (memq (char-before match-pos) '(?\( ?, ?\[ ?<))
+
+               ;; Find out the type of the arglist.
+               (if (<= match-pos (point-min))
+                   (setq context 'arglist)
+                 (let ((type (c-get-char-property (1- match-pos) 'c-type)))
+                   (cond ((eq type 'c-decl-arg-start)
+                          ;; Got a cached hit in a declaration arglist.
+                          (setq context 'decl))
+                         ((or (eq type 'c-<>-arg-sep)
+                              (eq (char-before match-pos) ?<))
+                          ;; Inside an angle bracket arglist.
+                          (setq context '<>))
+                         (type
+                          ;; Got a cached hit in some other type of arglist.
+                          (setq context 'arglist))
+                         ((if inside-macro
+                              (< match-pos max-type-decl-end-before-token)
+                            (< match-pos max-type-decl-end))
+                          ;; The point is within the range of a previously
+                          ;; encountered type decl expression, so the arglist
+                          ;; is probably one that contains declarations.
+                          ;; However, if `c-recognize-paren-inits' is set it
+                          ;; might also be an initializer arglist.
+                          (setq context 'decl)
+                          ;; The result of this check is cached with a char
+                          ;; property on the match token, so that we can look
+                          ;; it up again when refontifying single lines in a
+                          ;; multiline declaration.
+                          (c-put-char-property (1- match-pos)
+                                               'c-type 'c-decl-arg-start))
+                         (t
+                          (setq context 'arglist)))))
+
+             (setq context nil))
+
+           ;; If we're in a normal arglist context we don't want to
+           ;; recognize commas in nested angle bracket arglists since
+           ;; those commas could be part of our own arglist.
+           (setq c-restricted-<>-arglists (and c-recognize-<>-arglists
+                                               (eq context 'arglist))
+
+                 ;; Now analyze the construct.
+                 decl-or-cast (c-forward-decl-or-cast-1
+                               match-pos context last-cast-end))
+
+           (if (not decl-or-cast)
+               ;; False alarm.  Return t to go on to the next check.
+               t
+
+             (if (eq decl-or-cast 'cast)
+                 ;; Save the position after the previous cast so we can feed
+                 ;; it to `c-forward-decl-or-cast-1' in the next round.  That
+                 ;; helps it discover cast chains like "(a) (b) c".
+                 (setq last-cast-end (point))
+
+               ;; Set `max-type-decl-end' or `max-type-decl-end-before-token'
+               ;; under the assumption that we're after the first type decl
+               ;; expression in the declaration now.  That's not really true;
+               ;; we could also be after a parenthesized initializer
+               ;; expression in C++, but this is only used as a last resort
+               ;; to slant ambiguous expression/declarations, and overall
+               ;; it's worth the risk to occasionally fontify an expression
+               ;; as a declaration in an initializer expression compared to
+               ;; getting ambiguous things in normal function prototypes
+               ;; fontified as expressions.
+               (if inside-macro
+                   (when (> (point) max-type-decl-end-before-token)
+                     (setq max-type-decl-end-before-token (point)))
+                 (when (> (point) max-type-decl-end)
+                   (setq max-type-decl-end (point))))
+
+               ;; Back up to the type to fontify the declarator(s).
+               (goto-char (car decl-or-cast))
+
+               (let ((decl-list
+                      (if context
+                          ;; Should normally not fontify a list of
+                          ;; declarators inside an arglist, but the first
+                          ;; argument in the ';' separated list of a "for"
+                          ;; statement is an exception.
+                          (when (eq (char-before match-pos) ?\()
+                            (save-excursion
+                              (goto-char (1- match-pos))
+                              (c-backward-syntactic-ws)
+                              (and (c-simple-skip-symbol-backward)
+                                   (looking-at c-paren-stmt-key))))
+                        t)))
+
+                 ;; Fix the `c-decl-id-start' or `c-decl-type-start' property
+                 ;; before the first declarator if it's a list.
+                 ;; `c-font-lock-declarators' handles the rest.
+                 (when decl-list
+                   (save-excursion
+                     (c-backward-syntactic-ws)
+                     (unless (bobp)
+                       (c-put-char-property (1- (point)) 'c-type
+                                            (if (cdr decl-or-cast)
+                                                'c-decl-type-start
+                                              'c-decl-id-start)))))
+
+                 (c-font-lock-declarators
+                  (point-max) decl-list (cdr decl-or-cast))))
+
+             ;; A cast or declaration has been successfully identified, so do
+             ;; all the fontification of types and refs that's been recorded.
+             (c-fontify-recorded-types-and-refs)
+             nil))
+
+         ;; It was a false alarm.  Check if we're in a label instead.
+         (goto-char start-pos)
+         (when (c-forward-label t match-pos nil)
+           ;; Can't use `c-fontify-types-and-refs' here since we
+           ;; should use the label face.
+           (let (elem)
+             (while c-record-ref-identifiers
+               (setq elem (car c-record-ref-identifiers)
+                     c-record-ref-identifiers (cdr c-record-ref-identifiers))
+               (c-put-font-lock-face (car elem) (cdr elem)
+                                     c-label-face-name)))
+           ;; `c-forward-label' probably has added a `c-decl-end'
+           ;; marker, so return t to `c-find-decl-spots' to signal
+           ;; that.
+           t))))
 
       nil)))
 
@@ -1794,32 +1224,40 @@ on level 2 only and so aren't combined with `c-complex-decl-matchers'."
       ;; Fontify types preceded by `c-type-prefix-kwds' and the
       ;; identifiers in the declarations they might start.
       ,@(when (c-lang-const c-type-prefix-kwds)
-         (let ((prefix-re (c-make-keywords-re nil
-                            (c-lang-const c-type-prefix-kwds))))
+         (let* ((prefix-re (c-make-keywords-re nil
+                             (c-lang-const c-type-prefix-kwds)))
+                (type-match (+ 2
+                               (regexp-opt-depth prefix-re)
+                               (c-lang-const c-simple-ws-depth))))
            `((,(c-make-font-lock-search-function
-                (concat "\\<\\(" prefix-re "\\)"
-                        "[ \t\n\r\f\v]+"
-                        "\\(" (c-lang-const c-symbol-key) "\\)")
-                `(,(+ (c-regexp-opt-depth prefix-re) 2)
+                (concat "\\<\\(" prefix-re "\\)" ; 1
+                        (c-lang-const c-simple-ws) "+"
+                        (concat "\\("  ; 2 + prefix-re + c-simple-ws
+                                (c-lang-const c-symbol-key)
+                                "\\)"))
+                `(,type-match
                   'font-lock-type-face t)
-                '((c-font-lock-declarators limit t nil)
+                `((c-font-lock-declarators limit t nil)
                   (save-match-data
-                    (goto-char (match-end 2))
+                    (goto-char (match-end ,type-match))
                     (c-forward-syntactic-ws))
-                  (goto-char (match-end 2))))))))
+                  (goto-char (match-end ,type-match))))))))
 
       ;; Fontify special declarations that lacks a type.
       ,@(when (c-lang-const c-typeless-decl-kwds)
          `((,(c-make-font-lock-search-function
               (concat "\\<\\("
-                      (c-regexp-opt (c-lang-const c-typeless-decl-kwds))
+                      (regexp-opt (c-lang-const c-typeless-decl-kwds))
                       "\\)\\>")
               '((c-font-lock-declarators limit t nil)
                 (save-match-data
                   (goto-char (match-end 1))
                   (c-forward-syntactic-ws))
                 (goto-char (match-end 1)))))))
-      ))
+
+      ;; Fontify generic colon labels in languages that support them.
+      ,@(when (c-lang-const c-recognize-colon-labels)
+         `(c-font-lock-labels))))
 
 (c-lang-defconst c-complex-decl-matchers
   "Complex font lock matchers for types and declarations.  Used on level
@@ -1828,10 +1266,6 @@ on level 2 only and so aren't combined with `c-complex-decl-matchers'."
   t `(;; Initialize some things before the search functions below.
       c-font-lock-complex-decl-prepare
 
-      ;; Fontify angle bracket arglists like templates in C++.
-      ,@(when (c-lang-const c-recognize-<>-arglists)
-         `(c-font-lock-<>-arglists))
-
       ,@(if (c-major-mode-is 'objc-mode)
            ;; Fontify method declarations in Objective-C, but first
            ;; we have to put the `c-decl-end' `c-type' property on
@@ -1847,18 +1281,15 @@ on level 2 only and so aren't combined with `c-complex-decl-matchers'."
                                  nil)))
                '((c-put-char-property (1- (match-end 1))
                                       'c-type 'c-decl-end)))
+             c-font-lock-objc-methods))
 
-             c-font-lock-objc-methods)
-
-         (when (c-lang-const c-opt-access-key)
-           `(,(c-make-font-lock-search-function
-               (c-lang-const c-opt-access-key)
-               '((c-put-char-property (1- (match-end 0))
-                                      'c-type 'c-decl-end))))))
-
-      ;; Fontify all declarations and casts.
+      ;; Fontify all declarations, casts and normal labels.
       c-font-lock-declarations
 
+      ;; Fontify angle bracket arglists like templates in C++.
+      ,@(when (c-lang-const c-recognize-<>-arglists)
+         `(c-font-lock-<>-arglists))
+
       ;; The first two rules here mostly find occurences that
       ;; `c-font-lock-declarations' has found already, but not
       ;; declarations containing blocks in the type (see note below).
@@ -1870,9 +1301,9 @@ on level 2 only and so aren't combined with `c-complex-decl-matchers'."
                   (c-lang-const c-primitive-type-kwds))))
         (if (c-major-mode-is 'pike-mode)
             ;; No symbol is a keyword after "->" in Pike.
-            `(,(concat "\\(\\=\\|\\(\\=\\|[^-]\\)[^>]\\)"
+            `(,(concat "\\(\\=.?\\|[^>]\\|[^-]>\\)"
                        "\\<\\(" re "\\)\\>")
-              3 font-lock-type-face)
+              2 font-lock-type-face)
           `(,(concat "\\<\\(" re "\\)\\>")
             1 'font-lock-type-face)))
 
@@ -1900,8 +1331,8 @@ on level 2 only and so aren't combined with `c-complex-decl-matchers'."
                        (unless (c-skip-comments-and-strings limit)
                          (c-forward-syntactic-ws)
                          ;; Handle prefix declaration specifiers.
-                         (when (looking-at c-specifier-key)
-                           (c-forward-keyword-clause))
+                         (when (looking-at c-prefix-spec-kwds-re)
+                           (c-forward-keyword-clause 1))
                          ,(if (c-major-mode-is 'c++-mode)
                               `(when (and (c-forward-type)
                                           (eq (char-after) ?=))
@@ -1949,12 +1380,15 @@ on level 2 only and so aren't combined with `c-complex-decl-matchers'."
       ))
 
 (defun c-font-lock-labels (limit)
-  ;; Fontify all the declarations from the point to LIMIT.  Assumes
+  ;; Fontify all statement labels from the point to LIMIT.  Assumes
   ;; that strings and comments have been fontified already.  Nil is
   ;; always returned.
   ;;
-  ;; This function can make hidden buffer changes, but the font-lock
-  ;; context covers that.
+  ;; Note: This function is only used on decoration level 2; this is
+  ;; taken care of directly by the gargantuan
+  ;; `c-font-lock-declarations' on higher levels.
+  ;;
+  ;; This function might do hidden buffer changes.
 
   (let (continue-pos id-start
        ;; The font-lock package in Emacs is known to clobber
@@ -2027,11 +1461,9 @@ higher."
                   (c-forward-syntactic-ws))
                 (goto-char (match-end 0)))))))
 
-      ;; Fontify labels in languages that supports them.
-      ,@(when (c-lang-const c-label-key)
-
-         `(;; Fontify labels after goto etc.
-           ;; (Got three different interpretation levels here,
+       ;; Fontify labels after goto etc.
+       ,@(when (c-lang-const c-before-label-kwds)
+         `(;; (Got three different interpretation levels here,
            ;; which makes it a bit complicated: 1) The backquote
            ;; stuff is expanded when compiled or loaded, 2) the
            ;; eval form is evaluated at font-lock setup (to
@@ -2048,11 +1480,8 @@ higher."
                             "\\("      ; identifier-offset
                             (c-lang-const c-symbol-key)
                             "\\)")
-                   (list ,(+ (c-regexp-opt-depth c-before-label-re) 2)
-                         c-label-face-name nil t))))
-
-           ;; Fontify normal labels.
-           c-font-lock-labels))
+                   (list ,(+ (regexp-opt-depth c-before-label-re) 2)
+                         c-label-face-name nil t))))))
 
       ;; Fontify the clauses after various keywords.
       ,@(when (or (c-lang-const c-type-list-kwds)
@@ -2068,7 +1497,7 @@ higher."
                                 (c-lang-const c-paren-type-kwds)))
                       "\\)\\>")
               '((c-fontify-types-and-refs ((c-promote-possible-types t))
-                  (c-forward-keyword-clause)
+                  (c-forward-keyword-clause 1)
                   (if (> (point) limit) (goto-char limit))))))))
       ))
 
@@ -2135,8 +1564,6 @@ higher."
   ;; to override, but we should otoh avoid clobbering a user setting.
   ;; This heuristic for that isn't perfect, but I can't think of any
   ;; better. /mast
-  ;;
-  ;; This function does not do any hidden buffer changes.
   (when (and (boundp def-var)
             (memq (symbol-value def-var)
                   (cons nil
@@ -2193,6 +1620,8 @@ need for `c-font-lock-extra-types'.")
   ;;
   ;; As usual, C++ takes the prize in coming up with a hard to parse
   ;; syntax. :P
+  ;;
+  ;; This function might do hidden buffer changes.
 
   (unless (c-skip-comments-and-strings limit)
     (save-excursion
@@ -2338,50 +1767,13 @@ need for `c++-font-lock-extra-types'.")
 \f
 ;;; Objective-C.
 
-(defun c-font-lock-objc-iip-decl ()
-  ;; Assuming the point is after an "@interface", "@implementation",
-  ;; "@protocol" declaration, fontify all the types in the directive.
-  ;; Return t if the directive was fully recognized.  Point will then
-  ;; be at the end of it.
-
-  (c-fontify-types-and-refs
-      (start-char
-       (c-promote-possible-types t)
-       ;; Turn off recognition of angle bracket arglists while parsing
-       ;; types here since the protocol reference list might then be
-       ;; considered part of the preceding name or superclass-name.
-       c-recognize-<>-arglists)
-    (catch 'break
-
-      ;; Handle the name of the class itself.
-      (c-forward-syntactic-ws)
-      (unless (c-forward-type) (throw 'break nil))
-
-      ;; Look for ": superclass-name" or "( category-name )".
-      (when (looking-at "[:\(]")
-       (setq start-char (char-after))
-       (forward-char)
-       (c-forward-syntactic-ws)
-       (unless (c-forward-type) (throw 'break nil))
-       (when (eq start-char ?\()
-         (unless (eq (char-after) ?\)) (throw 'break nil))
-         (forward-char)
-         (c-forward-syntactic-ws)))
-
-      ;; Look for a protocol reference list.
-      (when (if (eq (char-after) ?<)
-               (progn
-                 (setq c-recognize-<>-arglists t)
-                 (c-forward-<>-arglist t t))
-             t)
-       (c-put-char-property (1- (point)) 'c-type 'c-decl-end)
-       t))))
-
 (defun c-font-lock-objc-method ()
   ;; Assuming the point is after the + or - that starts an Objective-C
   ;; method declaration, fontify it.  This must be done before normal
   ;; casts, declarations and labels are fontified since they will get
   ;; false matches in these things.
+  ;;
+  ;; This function might do hidden buffer changes.
 
   (c-fontify-types-and-refs
       ((first t)
@@ -2430,6 +1822,8 @@ need for `c++-font-lock-extra-types'.")
 (defun c-font-lock-objc-methods (limit)
   ;; Fontify method declarations in Objective-C.  Nil is always
   ;; returned.
+  ;;
+  ;; This function might do hidden buffer changes.
 
   (let (;; The font-lock package in Emacs is known to clobber
        ;; `parse-sexp-lookup-properties' (when it exists).
@@ -2605,6 +1999,8 @@ need for `pike-font-lock-extra-types'.")
   ;; Note that faces added through KEYWORDS should never replace the
   ;; existing `c-doc-face-name' face since the existence of that face
   ;; is used as a flag in other code to skip comments.
+  ;;
+  ;; This function might do hidden buffer changes.
 
   (let (comment-beg region-beg)
     (if (eq (get-text-property (point) 'face)
@@ -2686,6 +2082,8 @@ need for `pike-font-lock-extra-types'.")
   ;; between the point and LIMIT that only is fontified with
   ;; `c-doc-face-name'.  If a match is found then submatch 0 surrounds
   ;; the first char and t is returned, otherwise nil is returned.
+  ;;
+  ;; This function might do hidden buffer changes.
   (let (start)
     (while (if (re-search-forward regexp limit t)
               (not (eq (get-text-property
@@ -2697,11 +2095,40 @@ need for `pike-font-lock-extra-types'.")
                              (copy-marker (1+ start))))
       t)))
 
+;; GtkDoc patterns contributed by Masatake YAMATO <jet@gyve.org>.
+
+(defconst gtkdoc-font-lock-doc-comments
+  (let ((symbol "[a-zA-Z0-9_]+")
+       (header "^ \\* "))
+    `((,(concat header "\\("     symbol "\\):[ \t]*$") 
+       1 ,c-doc-markup-face-name prepend nil)
+      (,(concat                  symbol     "()")
+       0 ,c-doc-markup-face-name prepend nil)
+      (,(concat header "\\(" "@" symbol "\\):")
+       1 ,c-doc-markup-face-name prepend nil)
+      (,(concat "[#%]" symbol)
+       0 ,c-doc-markup-face-name prepend nil))
+    ))
+
+(defconst gtkdoc-font-lock-doc-protection
+  `(("< \\(public\\|private\\|protected\\) >"
+     1 ,c-doc-markup-face-name prepend nil)))
+
+(defconst gtkdoc-font-lock-keywords
+  `((,(lambda (limit)
+       (c-font-lock-doc-comments "/\\*\\*$" limit
+         gtkdoc-font-lock-doc-comments)
+       (c-font-lock-doc-comments "/\\*< " limit
+         gtkdoc-font-lock-doc-protection)
+       ))))
+
+;; Javadoc.
+
 (defconst javadoc-font-lock-doc-comments
   `(("{@[a-z]+[^}\n\r]*}"              ; "{@foo ...}" markup.
      0 ,c-doc-markup-face-name prepend nil)
-    ("^\\(/\\*\\)?[ \t*]*\\(@[a-z]+\\)" ; "@foo ..." markup.
-     2 ,c-doc-markup-face-name prepend nil)
+    ("^\\(/\\*\\)?\\(\\s \\|\\*\\)*\\(@[a-z]+\\)" ; "@foo ..." markup.
+     3 ,c-doc-markup-face-name prepend nil)
     (,(concat "</?\\sw"                        ; HTML tags.
              "\\("
              (concat "\\sw\\|\\s \\|[=\n\r*.:]\\|"
@@ -2715,13 +2142,15 @@ need for `pike-font-lock-extra-types'.")
     ;; allowed in non-markup use.
     (,(lambda (limit)
        (c-find-invalid-doc-markup "[<>&]\\|{@" limit))
-     0 ,c-invalid-face-name prepend nil)))
+     0 'font-lock-warning-face prepend nil)))
 
 (defconst javadoc-font-lock-keywords
   `((,(lambda (limit)
        (c-font-lock-doc-comments "/\\*\\*" limit
          javadoc-font-lock-doc-comments)))))
 
+;; Pike autodoc.
+
 (defconst autodoc-decl-keywords
   ;; Adorned regexp matching the keywords that introduce declarations
   ;; in Pike Autodoc.
@@ -2736,6 +2165,8 @@ need for `pike-font-lock-extra-types'.")
 (defun autodoc-font-lock-line-markup (limit)
   ;; Fontify all line oriented keywords between the point and LIMIT.
   ;; Nil is always returned.
+  ;;
+  ;; This function might do hidden buffer changes.
 
   (let ((line-re (concat "^\\(\\(/\\*!\\|\\s *\\("
                         c-current-comment-prefix
@@ -2765,7 +2196,7 @@ need for `pike-font-lock-extra-types'.")
                     (and (eq (char-before) ?@)
                          (not (eobp))
                          (progn (forward-char)
-                                (skip-chars-forward " \t")
+                                (skip-syntax-forward " ")
                                 (looking-at c-current-comment-prefix))))
              (goto-char (match-end 0))
              (c-remove-font-lock-face pos (1- end))
@@ -2804,7 +2235,7 @@ need for `pike-font-lock-extra-types'.")
                 (and (eq (char-before) ?@)
                      (not (eobp))
                      (progn (forward-char)
-                            (skip-chars-forward " \t")
+                            (skip-syntax-forward " ")
                             (looking-at c-current-comment-prefix))))
          (goto-char (match-end 0))))))
 
@@ -2818,12 +2249,14 @@ need for `pike-font-lock-extra-types'.")
     ;; Fontify remaining markup characters as invalid.
     (,(lambda (limit)
        (c-find-invalid-doc-markup "@" limit))
-     0 ,c-invalid-face-name prepend nil)
+     0 'font-lock-warning-face prepend nil)
     ))
 
 (defun autodoc-font-lock-keywords ()
   ;; Note that we depend on that `c-current-comment-prefix' has got
   ;; its proper value here.
+  ;;
+  ;; This function might do hidden buffer changes.
 
   ;; The `c-type' text property with `c-decl-end' is used to mark the
   ;; end of the `autodoc-decl-keywords' occurrences to fontify the
@@ -2846,13 +2279,13 @@ need for `pike-font-lock-extra-types'.")
      ',(eval-when-compile               ; Evaluate while compiling cc-fonts
         (list
          ;; Function names.
-         '("^[ \t]*\\(func\\(tion\\)?\\)\\>[ \t]*\\(\\sw+\\)?"
+         '("^\\s *\\(func\\(tion\\)?\\)\\>\\s *\\(\\sw+\\)?"
            (1 font-lock-keyword-face) (3 font-lock-function-name-face nil t))
          ;;
          ;; Variable names.
          (cons
           (concat "\\<"
-                  (c-regexp-opt
+                  (regexp-opt
                    '("ARGC" "ARGIND" "ARGV" "BINMODE" "CONVFMT" "ENVIRON"
                      "ERRNO" "FIELDWIDTHS" "FILENAME" "FNR" "FS" "IGNORECASE"
                      "LINT" "NF" "NR" "OFMT" "OFS" "ORS" "PROCINFO" "RLENGTH"
@@ -2861,7 +2294,7 @@ need for `pike-font-lock-extra-types'.")
 
          ;; Special file names.  (acm, 2002/7/22)
          ;; The following regexp was created by first evaluating this in GNU Emacs 21.1:
-         ;; (c-regexp-opt '("/dev/stdin" "/dev/stdout" "/dev/stderr" "/dev/fd/n" "/dev/pid"
+         ;; (regexp-opt '("/dev/stdin" "/dev/stdout" "/dev/stderr" "/dev/fd/n" "/dev/pid"
          ;;                 "/dev/ppid" "/dev/pgrpid" "/dev/user") 'words)
          ;; , removing the "?:" from each "\\(?:" (for backward compatibility with older Emacsen)
          ;; , replacing the "n" in "dev/fd/n" with "[0-9]+"
@@ -2875,7 +2308,7 @@ std\\(err\\|in\\|out\\)\\|user\\)\\)\\>\
            (1 font-lock-variable-name-face t)
            (8 font-lock-variable-name-face t t))
          ;; Do the same (almost) with
-         ;; (c-regexp-opt '("/inet/tcp/lport/rhost/rport" "/inet/udp/lport/rhost/rport"
+         ;; (regexp-opt '("/inet/tcp/lport/rhost/rport" "/inet/udp/lport/rhost/rport"
          ;;                 "/inet/raw/lport/rhost/rport") 'words)
          ;; This cannot be combined with the above pattern, because the match number
          ;; for the (optional) closing \" would then exceed 9.
@@ -2886,7 +2319,7 @@ std\\(err\\|in\\|out\\)\\|user\\)\\)\\>\
 
          ;; Keywords.
          (concat "\\<"
-                 (c-regexp-opt
+                 (regexp-opt
                   '("BEGIN" "END" "break" "continue" "delete" "do" "else"
                     "exit" "for" "getline" "if" "in" "next" "nextfile"
                     "return" "while")
@@ -2896,7 +2329,7 @@ std\\(err\\|in\\|out\\)\\|user\\)\\)\\>\
          `(eval . (list
                    ,(concat
                      "\\<"
-                     (c-regexp-opt
+                     (regexp-opt
                       '("adump" "and" "asort" "atan2" "bindtextdomain" "close"
                         "compl" "cos" "dcgettext" "exp" "extension" "fflush"
                         "gensub" "gsub" "index" "int" "length" "log" "lshift"
@@ -2909,17 +2342,17 @@ std\\(err\\|in\\|out\\)\\|user\\)\\)\\>\
 
          ;; gawk debugging keywords.  (acm, 2002/7/21)
          ;; (Removed, 2003/6/6.  These functions are now fontified as built-ins)
-;;     (list (concat "\\<" (c-regexp-opt '("adump" "stopme") t) "\\>")
+;;     (list (concat "\\<" (regexp-opt '("adump" "stopme") t) "\\>")
 ;;        0 'font-lock-warning-face)
 
          ;; User defined functions with an apparent spurious space before the
          ;; opening parenthesis.  acm, 2002/5/30.
-         `(,(concat "\\(\\w\\|_\\)" c-awk-escaped-nls* "[ \t]"
+         `(,(concat "\\(\\w\\|_\\)" c-awk-escaped-nls* "\\s "
                     c-awk-escaped-nls*-with-space* "(")
            (0 'font-lock-warning-face))
 
          ;; Space after \ in what looks like an escaped newline.  2002/5/31
-         '("\\\\[ \t]+$" 0 font-lock-warning-face t)
+         '("\\\\\\s +$" 0 font-lock-warning-face t)
 
          ;; Unbalanced string (") or regexp (/) delimiters.  2002/02/16.
          '("\\s|" 0 font-lock-warning-face t nil)
index 27753aa69c9e0ec01887d35ba11fa9cab48941d2..de2dab7ebc008d1e65179104fcda684156bf831b 100644 (file)
@@ -1,6 +1,7 @@
 ;;; cc-langs.el --- language specific settings for CC Mode
 
-;; Copyright (C) 1985,1987,1992-2003, 2004, 2005 Free Software Foundation, Inc.
+;; Copyright (C) 1985,1987,1992-2003, 2004, 2005 Free Software Foundation,
+;; Inc.
 
 ;; Authors:    1998- Martin Stjernholm
 ;;             1992-1999 Barry A. Warsaw
@@ -24,7 +25,7 @@
 ;; GNU General Public License for more details.
 
 ;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING.  If not, write to
+;; along with this program; see the file COPYING.  If not, write to
 ;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 ;; Boston, MA 02110-1301, USA.
 
 (cc-require 'cc-defs)
 (cc-require 'cc-vars)
 
+
 ;; This file is not always loaded.  See note above.
 (cc-external-require 'cl)
 
        c-lang-variable-inits-tail c-lang-variable-inits))
 
 (defmacro c-lang-defvar (var val &optional doc)
-  "Declares the buffer local variable VAR to get the value VAL at mode
-initialization, at which point VAL is evaluated.  More accurately, VAL
-is evaluated and bound to VAR when the result from the macro
+  "Declares the buffer local variable VAR to get the value VAL.  VAL is
+evaluated and assigned at mode initialization.  More precisely, VAL is
+evaluated and bound to VAR when the result from the macro
 `c-init-language-vars' is evaluated.
 
 `c-lang-const' is typically used in VAL to get the right value for the
 language being initialized, and such calls will be macro expanded to
-the evaluated constant value at compile time.
-
-This macro does not do any hidden buffer changes."
+the evaluated constant value at compile time."
 
   (when (and (not doc)
             (eq (car-safe val) 'c-lang-const)
@@ -177,6 +177,57 @@ This macro does not do any hidden buffer changes."
   '(def-edebug-spec c-lang-defvar
      (&define name def-form &optional stringp)))
 
+(eval-when-compile
+  ;; Some helper functions used when building the language constants.
+
+  (defun c-filter-ops (ops opgroup-filter op-filter &optional xlate)
+    ;; Used to filter operators from the list OPS in a DWIM:ey way:
+    ;; OPS either has the structure of `c-operators', as a single
+    ;; group in `c-operators', or is a plain list of operators.
+    ;; OPGROUP-FILTER is used filter out the operator groups.  It can
+    ;; be t to choose all groups, a list of the group type symbols to
+    ;; accept, or a function which will be called with the group
+    ;; symbol for each group and should return non-nil for those to
+    ;; include.  OP-FILTER filters the individual operators in each
+    ;; group.  It can be t to choose all operators, a regexp to test
+    ;; against each operator, or a function which will be called for
+    ;; each operator and should return non-nil for those to include.
+    ;; If XLATE is given, it's a function which is called for each
+    ;; matching operator and its return value is collected instead.
+    ;; If it returns a list, the elements are spliced directly into
+    ;; the final result, which is returned as a list with duplicates
+    ;; removed using `equal'.  `c-mode-syntax-table' for the current
+    ;; mode is in effect during the whole procedure.
+    (unless (listp (car-safe ops))
+      (setq ops (list ops)))
+    (cond ((eq opgroup-filter t)
+          (setq opgroup-filter (lambda (opgroup) t)))
+         ((not (functionp opgroup-filter))
+          (setq opgroup-filter `(lambda (opgroup)
+                                  (memq opgroup ',opgroup-filter)))))
+    (cond ((eq op-filter t)
+          (setq op-filter (lambda (op) t)))
+         ((stringp op-filter)
+          (setq op-filter `(lambda (op)
+                             (string-match ,op-filter op)))))
+    (unless xlate
+      (setq xlate 'identity))
+    (c-with-syntax-table (c-lang-const c-mode-syntax-table)
+      (delete-duplicates
+       (mapcan (lambda (opgroup)
+                (when (if (symbolp (car opgroup))
+                          (when (funcall opgroup-filter (car opgroup))
+                            (setq opgroup (cdr opgroup))
+                            t)
+                        t)
+                  (mapcan (lambda (op)
+                            (when (funcall op-filter op)
+                              (let ((res (funcall xlate op)))
+                                (if (listp res) res (list res)))))
+                          opgroup)))
+              ops)
+       :test 'equal))))
+
 \f
 ;;; Various mode specific values that aren't language related.
 
@@ -208,7 +259,7 @@ This macro does not do any hidden buffer changes."
       "----"
       ("Toggle..."
        ["Syntactic indentation" c-toggle-syntactic-indentation t]
-       ["Auto newline"          c-toggle-auto-state t]
+       ["Auto newline"          c-toggle-auto-newline t]
        ["Hungry delete"         c-toggle-hungry-state t])))
 
 \f
@@ -261,6 +312,10 @@ The syntax tables aren't stored directly since they're quite large."
         (c-populate-syntax-table table)
         ;; Mode specific syntaxes.
         ,(cond ((c-major-mode-is 'objc-mode)
+                ;; Let '@' be part of symbols in ObjC to cope with
+                ;; its compiler directives as single keyword tokens.
+                ;; This is then necessary since it's assumed that
+                ;; every keyword is a single symbol.
                 `(modify-syntax-entry ?@ "_" table))
                ((c-major-mode-is 'pike-mode)
                 `(modify-syntax-entry ?@ "." table)))
@@ -328,6 +383,7 @@ so that all identifiers are recognized as words.")
 keyword.  It's unspecified how far it matches.  Does not contain a \\|
 operator at the top level."
   t    (concat "[" c-alpha "_]")
+  objc (concat "[" c-alpha "@]")
   pike (concat "[" c-alpha "_`]"))
 (c-lang-defvar c-symbol-start (c-lang-const c-symbol-start))
 
@@ -340,8 +396,8 @@ This is on the form that fits inside [ ] in a regexp."
   objc (concat c-alnum "_$@"))
 
 (c-lang-defconst c-symbol-key
-  "Regexp matching identifiers and keywords.  Assumed to match if
-`c-symbol-start' matches on the same position."
+  "Regexp matching identifiers and keywords (with submatch 0).  Assumed
+to match if `c-symbol-start' matches on the same position."
   t    (concat (c-lang-const c-symbol-start)
               "[" (c-lang-const c-symbol-chars) "]*")
   pike (concat
@@ -355,7 +411,7 @@ This is on the form that fits inside [ ] in a regexp."
 
 (c-lang-defconst c-symbol-key-depth
   ;; Number of regexp grouping parens in `c-symbol-key'.
-  t (c-regexp-opt-depth (c-lang-const c-symbol-key)))
+  t (regexp-opt-depth (c-lang-const c-symbol-key)))
 
 (c-lang-defconst c-nonsymbol-chars
   "This is the set of chars that can't be part of a symbol, i.e. the
@@ -371,165 +427,181 @@ It's assumed to not contain any submatchers."
   ;; `c-symbol-key'.
   t (concat "[" (c-lang-const c-nonsymbol-chars) "]"))
 
-(c-lang-defconst c-opt-identifier-concat-key
-  "Regexp matching the operators that join symbols to fully qualified
-identifiers, or nil in languages that don't have such things.  Does
-not contain a \\| operator at the top level."
+(c-lang-defconst c-identifier-ops
+  "The operators that make up fully qualified identifiers.  nil in
+languages that don't have such things.  See `c-operators' for a
+description of the format.  Binary operators can concatenate symbols,
+e.g. \"::\" in \"A::B::C\".  Prefix operators can precede identifiers,
+e.g. \"~\" in \"~A::B\".  Other types of operators aren't supported.
+
+This value is by default merged into `c-operators'."
   t    nil
-  c++  "::"
+  c++  '((prefix "~" "??-" "compl")
+        (right-assoc "::")
+        (prefix "::"))
   ;; Java has "." to concatenate identifiers but it's also used for
   ;; normal indexing.  There's special code in the Java font lock
   ;; rules to fontify qualified identifiers based on the standard
   ;; naming conventions.  We still define "." here to make
   ;; `c-forward-name' move over as long names as possible which is
   ;; necessary to e.g. handle throws clauses correctly.
-  java "\\."
-  idl  "::"
-  pike "\\(::\\|\\.\\)")
+  java '((left-assoc "."))
+  idl  '((left-assoc "::")
+        (prefix "::"))
+  pike '((left-assoc "::")
+        (prefix "::")
+        (left-assoc ".")))
+
+(c-lang-defconst c-opt-identifier-concat-key
+  ;; Appendable adorned regexp matching the operators that join
+  ;; symbols to fully qualified identifiers, or nil in languages that
+  ;; don't have such things.
+  ;;
+  ;; This was a docstring constant in 5.30.  It still works but is now
+  ;; considered internal - change `c-identifier-ops' instead.
+  t (let ((ops (c-filter-ops (c-lang-const c-identifier-ops)
+                            '(left-assoc right-assoc)
+                            t)))
+      (when ops
+       (c-make-keywords-re 'appendable ops))))
 (c-lang-defvar c-opt-identifier-concat-key
   (c-lang-const c-opt-identifier-concat-key)
   'dont-doc)
 
+(c-lang-defconst c-opt-identifier-concat-key-depth
+  ;; Number of regexp grouping parens in `c-opt-identifier-concat-key'.
+  t (regexp-opt-depth (c-lang-const c-opt-identifier-concat-key)))
+
+(c-lang-defconst c-opt-identifier-prefix-key
+  ;; Appendable adorned regexp matching operators that might precede
+  ;; an identifier and that are part of the identifier in that case.
+  ;; nil in languages without such things.
+  t (let ((ops (c-filter-ops (c-lang-const c-identifier-ops)
+                            '(prefix)
+                            t)))
+      (when ops
+       (c-make-keywords-re 'appendable ops))))
+
+(c-lang-defconst c-after-id-concat-ops
+  "Operators that can occur after a binary operator on `c-identifier-ops'
+in identifiers.  nil in languages that don't have such things.
+
+Operators here should also have appropriate entries in `c-operators' -
+it's not taken care of by default."
+  t    nil
+  ;; '~' for destructors in C++, '*' for member pointers.
+  c++  '("~" "*")
+  ;; In Java we recognize '*' to deal with "foo.bar.*" that can occur
+  ;; in import declarations.  (This will also match bogus things like
+  ;; "foo.*bar" but we don't bother.)
+  java '("*"))
+
 (c-lang-defconst c-opt-after-id-concat-key
-  "Regexp that must match the token after `c-opt-identifier-concat-key'
-for it to be considered an identifier concatenation operator (which
-e.g. causes the preceding identifier to be fontified as a reference).
-Assumed to be a string if `c-opt-identifier-concat-key' is."
-  t    (if (c-lang-const c-opt-identifier-concat-key)
-          (c-lang-const c-symbol-start))
-  c++  (concat (c-lang-const c-symbol-start)
-              "\\|[~*]")
-  java (concat (c-lang-const c-symbol-start)
-              "\\|\\*"))
+  ;; Regexp that must match the token after
+  ;; `c-opt-identifier-concat-key' for it to be considered an
+  ;; identifier concatenation operator (which e.g. causes the
+  ;; preceding identifier to be fontified as a reference).  Assumed to
+  ;; be a string if `c-opt-identifier-concat-key' is.
+  ;;
+  ;; This was a docstring constant in 5.30.  It still works but is now
+  ;; considered internal - change `c-after-id-concat-ops' instead.
+  t (concat (c-lang-const c-symbol-start)
+           (if (c-lang-const c-after-id-concat-ops)
+               (concat "\\|" (c-make-keywords-re 'appendable
+                               (c-lang-const c-after-id-concat-ops)))
+             "")))
 
 (c-lang-defconst c-identifier-start
-  "Regexp that matches the start of an \(optionally qualified)
-identifier.  It should also match all keywords.  It's unspecified how
-far it matches."
-  t    (concat (c-lang-const c-symbol-start)
-              (if (c-lang-const c-opt-identifier-concat-key)
-                  (concat "\\|" (c-lang-const c-opt-identifier-concat-key))
-                ""))
-  c++  (concat (c-lang-const c-identifier-start)
-              "\\|"
-              "[~*][ \t\n\r\f\v]*" (c-lang-const c-symbol-start))
-  ;; Java does not allow a leading qualifier operator.
-  java (c-lang-const c-symbol-start))
+  "Regexp that matches the start of an (optionally qualified) identifier.
+It should also match all keywords.  It's unspecified how far it
+matches."
+  t (concat (c-lang-const c-symbol-start)
+           (if (c-lang-const c-opt-identifier-prefix-key)
+               (concat "\\|"
+                       (c-lang-const c-opt-identifier-prefix-key))
+             "")))
 (c-lang-defvar c-identifier-start (c-lang-const c-identifier-start))
 
 (c-lang-defconst c-identifier-key
   "Regexp matching a fully qualified identifier, like \"A::B::c\" in
 C++.  It does not recognize the full range of syntactic whitespace
-between the tokens; `c-forward-name' has to be used for that."
-  t    (c-lang-const c-symbol-key)     ; Default to `c-symbol-key'.
-  ;; C++ allows a leading qualifier operator and a `~' before the last
-  ;; symbol.  This regexp is more complex than strictly necessary to
-  ;; ensure that it can be matched with a minimum of backtracking.
-  c++  (concat
-       "\\(" (c-lang-const c-opt-identifier-concat-key) "[ \t\n\r\f\v]*\\)?"
-       (concat
-        "\\("
-        ;; The submatch below is depth of `c-opt-identifier-concat-key' + 3.
-        "\\(" (c-lang-const c-symbol-key) "\\)"
-        (concat "\\("
-                "[ \t\n\r\f\v]*"
-                (c-lang-const c-opt-identifier-concat-key)
-                "[ \t\n\r\f\v]*"
-                ;; The submatch below is: `c-symbol-key-depth' +
-                ;; 2 * depth of `c-opt-identifier-concat-key' + 5.
-                "\\(" (c-lang-const c-symbol-key) "\\)"
-                "\\)*")
-        (concat "\\("
-                "[ \t\n\r\f\v]*"
-                (c-lang-const c-opt-identifier-concat-key)
-                "[ \t\n\r\f\v]*"
-                "[~*]"
-                "[ \t\n\r\f\v]*"
-                ;; The submatch below is: 2 * `c-symbol-key-depth' +
-                ;; 3 * depth of `c-opt-identifier-concat-key' + 7.
-                "\\(" (c-lang-const c-symbol-key) "\\)"
+between the tokens; `c-forward-name' has to be used for that.  It
+should also not match identifiers containing parenthesis groupings,
+e.g. identifiers with template arguments such as \"A<X,Y>\" in C++."
+  ;; This regexp is more complex than strictly necessary to ensure
+  ;; that it can be matched with a minimum of backtracking.
+  t (concat (if (c-lang-const c-opt-identifier-prefix-key)
+               (concat
+                "\\("
+                (c-lang-const c-opt-identifier-prefix-key)
+                (c-lang-const c-simple-ws) "*"
                 "\\)?")
-        "\\|"
-        "~[ \t\n\r\f\v]*"
-        ;; The submatch below is: 3 * `c-symbol-key-depth' +
-        ;; 3 * depth of `c-opt-identifier-concat-key' + 8.
-        "\\(" (c-lang-const c-symbol-key) "\\)"
-        "\\)"))
-  ;; IDL and Pike allows a leading qualifier operator.
-  (idl pike) (concat
-             "\\("
-             (c-lang-const c-opt-identifier-concat-key)
-             "[ \t\n\r\f\v]*"
-             "\\)?"
-             ;; The submatch below is depth of
-             ;; `c-opt-identifier-concat-key' + 2.
-             "\\(" (c-lang-const c-symbol-key) "\\)"
-             (concat "\\("
-                     "[ \t\n\r\f\v]*"
-                     (c-lang-const c-opt-identifier-concat-key)
-                     "[ \t\n\r\f\v]*"
-                     ;; The submatch below is: `c-symbol-key-depth' +
-                     ;; 2 * depth of `c-opt-identifier-concat-key' + 4.
+             "")
+           "\\(" (c-lang-const c-symbol-key) "\\)"
+           (if (c-lang-const c-opt-identifier-concat-key)
+               (concat
+                "\\("
+                (c-lang-const c-simple-ws) "*"
+                (c-lang-const c-opt-identifier-concat-key)
+                (c-lang-const c-simple-ws) "*"
+                (if (c-lang-const c-after-id-concat-ops)
+                    (concat
+                     "\\("
+                      (c-make-keywords-re 'appendable
+                        (c-lang-const c-after-id-concat-ops))
+                     (concat
+                      ;; For flexibility, consider the symbol match
+                      ;; optional if we've hit a
+                      ;; `c-after-id-concat-ops' operator.  This is
+                      ;; also necessary to handle the "*" that can
+                      ;; end import declaration identifiers in Java.
+                      "\\("
+                      (c-lang-const c-simple-ws) "*"
+                      "\\(" (c-lang-const c-symbol-key) "\\)"
+                      "\\)?")
+                     "\\|"
                      "\\(" (c-lang-const c-symbol-key) "\\)"
-                     "\\)*"))
-  ;; Java does not allow a leading qualifier operator.  If it ends
-  ;; with ".*" (used in import declarations) we also consider that as
-  ;; part of the name.  ("*" is actually recognized in any position
-  ;; except the first by this regexp, but we don't bother.)
-  java (concat "\\(" (c-lang-const c-symbol-key) "\\)" ; 1
-              (concat "\\("
-                      "[ \t\n\r\f\v]*"
-                      (c-lang-const c-opt-identifier-concat-key)
-                      "[ \t\n\r\f\v]*"
-                      (concat "\\("
-                              ;; The submatch below is `c-symbol-key-depth' +
-                              ;; depth of `c-opt-identifier-concat-key' + 4.
-                              "\\(" (c-lang-const c-symbol-key) "\\)"
-                              "\\|\\*\\)")
-                      "\\)*")))
+                     "\\)")
+                  (concat "\\(" (c-lang-const c-symbol-key) "\\)"))
+                "\\)*")
+             "")))
 (c-lang-defvar c-identifier-key (c-lang-const c-identifier-key))
 
 (c-lang-defconst c-identifier-last-sym-match
-  "Used to identify the submatch in `c-identifier-key' that surrounds
-the last symbol in the qualified identifier.  It's a list of submatch
-numbers, of which the first that has a match is taken.  It's assumed
-that at least one does when the regexp has matched."
-  t    '(0)
-  c++  (list (+ (* 3 (c-lang-const c-symbol-key-depth))
-               (* 3 (c-regexp-opt-depth
-                     (c-lang-const c-opt-identifier-concat-key)))
-               8)
-            (+ (* 2 (c-lang-const c-symbol-key-depth))
-               (* 3 (c-regexp-opt-depth
-                     (c-lang-const c-opt-identifier-concat-key)))
-               7)
-            (+ (c-lang-const c-symbol-key-depth)
-               (* 2 (c-regexp-opt-depth
-                     (c-lang-const c-opt-identifier-concat-key)))
-               5)
-            (+ (c-regexp-opt-depth
-                (c-lang-const c-opt-identifier-concat-key))
-               3))
-  (idl pike) (list (+ (c-lang-const c-symbol-key-depth)
-                     (* 2 (c-regexp-opt-depth
-                           (c-lang-const c-opt-identifier-concat-key)))
-                     4)
-                  (+ (c-regexp-opt-depth
-                      (c-lang-const c-opt-identifier-concat-key))
-                     2))
-  java (list (+ (c-lang-const c-symbol-key-depth)
-               (c-regexp-opt-depth
-                (c-lang-const c-opt-identifier-concat-key))
-               4)
-            1))
-(c-lang-defvar c-identifier-last-sym-match
-  (c-lang-const c-identifier-last-sym-match)
-  'dont-doc)
+  ;; This was a docstring constant in 5.30 but it's no longer used.
+  ;; It's only kept to avoid breaking third party code.
+  ;;
+  ;; Used to identify the submatch in `c-identifier-key' that
+  ;; surrounds the last symbol in the qualified identifier.  It's a
+  ;; list of submatch numbers, of which the first that has a match is
+  ;; taken.  It's assumed that at least one does when the regexp has
+  ;; matched.
+  t nil)
+
+(c-lang-defconst c-string-escaped-newlines
+  "Set if the language support backslash escaped newlines inside string
+literals."
+  t nil
+  (c c++ objc pike) t)
+(c-lang-defvar c-string-escaped-newlines
+  (c-lang-const c-string-escaped-newlines))
+
+(c-lang-defconst c-multiline-string-start-char
+  "Set if the language supports multiline string literals without escaped
+newlines.  If t, all string literals are multiline.  If a character,
+only literals where the open quote is immediately preceded by that
+literal are multiline."
+  t    nil
+  pike ?#)
+(c-lang-defvar c-multiline-string-start-char
+  (c-lang-const c-multiline-string-start-char))
 
 (c-lang-defconst c-opt-cpp-prefix
   "Regexp matching the prefix of a cpp directive in the languages that
 normally use that macro preprocessor.  Tested at bol or at boi.
 Assumed to not contain any submatches or \\| operators."
+  ;; TODO (ACM, 2005-04-01).  Amend the following to recognise escaped NLs;
+  ;; amend all uses of c-opt-cpp-prefix which count regexp-depth.
   t "\\s *#\\s *"
   (java awk) nil)
 (c-lang-defvar c-opt-cpp-prefix (c-lang-const c-opt-cpp-prefix))
@@ -546,9 +618,46 @@ submatch surrounds the directive name."
               "\\([" c-alnum "]+\\|!\\)"))
 (c-lang-defvar c-opt-cpp-start (c-lang-const c-opt-cpp-start))
 
-(c-lang-defconst c-cpp-defined-fns
-  ;; Name of functions in cpp expressions that take an identifier as
-  ;; the argument.
+(c-lang-defconst c-cpp-message-directives
+  "List of cpp directives (without the prefix) that are followed by a
+string message."
+  t    (if (c-lang-const c-opt-cpp-prefix)
+          '("error"))
+  pike '("error" "warning"))
+
+(c-lang-defconst c-cpp-include-directives
+  "List of cpp directives (without the prefix) that are followed by a
+file name in angle brackets or quotes."
+  t    (if (c-lang-const c-opt-cpp-prefix)
+          '("include"))
+  objc '("include" "import"))
+
+(c-lang-defconst c-opt-cpp-macro-define
+  "Cpp directive (without the prefix) that is followed by a macro
+definition, or nil if the language doesn't have any."
+  t (if (c-lang-const c-opt-cpp-prefix)
+       "define"))
+
+(c-lang-defconst c-opt-cpp-macro-define-start
+  ;; Regexp matching everything up to the macro body of a cpp define,
+  ;; or the end of the logical line if there is none.  Set if
+  ;; c-opt-cpp-macro-define is.
+  t (if (c-lang-const c-opt-cpp-macro-define)
+       (concat (c-lang-const c-opt-cpp-prefix)
+               (c-lang-const c-opt-cpp-macro-define)
+               "[ \t]+\\(\\sw\\|_\\)+\\(\([^\)]*\)\\)?"
+               "\\([ \t]\\|\\\\\n\\)*")))
+(c-lang-defvar c-opt-cpp-macro-define-start
+  (c-lang-const c-opt-cpp-macro-define-start))
+
+(c-lang-defconst c-cpp-expr-directives
+  "List if cpp directives (without the prefix) that are followed by an
+expression."
+  t (if (c-lang-const c-opt-cpp-prefix)
+       '("if" "elif")))
+
+(c-lang-defconst c-cpp-expr-functions
+  "List of functions in cpp expressions."
   t    (if (c-lang-const c-opt-cpp-prefix)
           '("defined"))
   pike '("defined" "efun" "constant"))
@@ -559,7 +668,7 @@ submatch surrounds the directive name."
   java (append (c-lang-const c-assignment-operators)
               '(">>>="))
   c++  (append (c-lang-const c-assignment-operators)
-              '("and_eq" "or_eq" "xor_eq"))
+              '("and_eq" "or_eq" "xor_eq" "??!=" "??'="))
   idl  nil)
 
 (c-lang-defconst c-operators
@@ -573,6 +682,9 @@ it.  The operator group types are:
 
 'prefix         Unary prefix operators.
 'postfix        Unary postfix operators.
+'postfix-if-paren
+               Unary postfix operators if and only if the chars have
+               parenthesis syntax.
 'left-assoc     Binary left associative operators (i.e. a+b+c means (a+b)+c).
 'right-assoc    Binary right associative operators (i.e. a=b=c means a=(b=c)).
 'right-assoc-sequence
@@ -605,20 +717,14 @@ since CC Mode treats every identifier as an expression."
                        ,@(when (c-major-mode-is '(c-mode c++-mode))
                            '("%:%:" "??=??=")))))
 
-      ;; Primary.  Info duplicated in `c-opt-identifier-concat-key'
-      ;; and `c-identifier-key'.
+      ;; Primary.
+      ,@(c-lang-const c-identifier-ops)
       ,@(cond ((c-major-mode-is 'c++-mode)
-              `((postfix-if-paren "<" ">") ; Templates.
-                (prefix "~" "??-" "compl")
-                (right-assoc "::")
-                (prefix "::")))
+              `((postfix-if-paren "<" ">"))) ; Templates.
              ((c-major-mode-is 'pike-mode)
-              `((left-assoc "::")
-                (prefix "::" "global" "predef")))
+              `((prefix "global" "predef")))
              ((c-major-mode-is 'java-mode)
-              `(;; Not necessary since it's also in the postfix group below.
-                ;;(left-assoc ".")
-                (prefix "super"))))
+              `((prefix "super"))))
 
       ;; Postfix.
       ,@(when (c-major-mode-is 'c++-mode)
@@ -718,10 +824,8 @@ since CC Mode treats every identifier as an expression."
   idl `(;; Preprocessor.
        (prefix "#")
        (left-assoc "##")
-       ;; Primary.  Info duplicated in `c-opt-identifier-concat-key'
-       ;; and `c-identifier-key'.
-       (left-assoc "::")
-       (prefix "::")
+       ;; Primary.
+       ,@(c-lang-const c-identifier-ops)
        ;; Unary.
        (prefix  "+" "-" "~")
        ;; Multiplicative.
@@ -739,14 +843,12 @@ since CC Mode treats every identifier as an expression."
 
 (c-lang-defconst c-operator-list
   ;; The operators as a flat list (without duplicates).
-  t (delete-duplicates (mapcan (lambda (elem) (append (cdr elem) nil))
-                              (c-lang-const c-operators))
-                      :test 'string-equal))
+  t (c-filter-ops (c-lang-const c-operators) t t))
 
 (c-lang-defconst c-overloadable-operators
-  "List of the operators that are overloadable, in their \"identifier form\"."
+  "List of the operators that are overloadable, in their \"identifier
+form\".  See also `c-op-identitier-prefix'."
   t    nil
-  ;; The preceding "operator" keyword is treated separately in C++.
   c++  '("new" "delete" ;; Can be followed by "[]" but we ignore that.
         "+" "-" "*" "/" "%"
         "^" "??'" "xor" "&" "bitand" "|" "??!" "bitor" "~" "??-" "compl"
@@ -768,6 +870,20 @@ since CC Mode treats every identifier as an expression."
 (c-lang-defvar c-overloadable-operators-regexp
   (c-lang-const c-overloadable-operators-regexp))
 
+(c-lang-defconst c-opt-op-identitier-prefix
+  "Regexp matching the token before the ones in
+`c-overloadable-operators' when operators are specified in their
+\"identifier form\".  This typically matches \"operator\" in C++ where
+operator functions are specified as e.g. \"operator +\".  It's nil in
+languages without operator functions or where the complete operator
+identifier is listed in `c-overloadable-operators'.
+
+This regexp is assumed to not match any non-operator identifier."
+  t   nil
+  c++ (c-make-keywords-re t '("operator")))
+(c-lang-defvar c-opt-op-identitier-prefix
+  (c-lang-const c-opt-op-identitier-prefix))
+
 (c-lang-defconst c-other-op-syntax-tokens
   "List of the tokens made up of characters in the punctuation or
 parenthesis syntax classes that have uses other than as expression
@@ -776,9 +892,9 @@ operators."
   (c c++ pike) (append '("#" "##"      ; Used by cpp.
                         "::" "...")
                       (c-lang-const c-other-op-syntax-tokens))
-  (c c++) (append '("<%" "%>" "<:" ":>" "%:" "%:%:" "*")
-                 (c-lang-const c-other-op-syntax-tokens))
-  c++  (append '("&") (c-lang-const c-other-op-syntax-tokens))
+  (c c++) (append '("*") (c-lang-const c-other-op-syntax-tokens))
+  c++  (append '("&" "<%" "%>" "<:" ":>" "%:" "%:%:")
+              (c-lang-const c-other-op-syntax-tokens))
   objc (append '("#" "##"              ; Used by cpp.
                 "+" "-") (c-lang-const c-other-op-syntax-tokens))
   idl  (append '("#" "##")             ; Used by cpp.
@@ -788,17 +904,35 @@ operators."
               (c-lang-const c-overloadable-operators))
   awk '("{" "}" "(" ")" "[" "]" ";" "," "=" "/"))
 
+(c-lang-defconst c-all-op-syntax-tokens
+  ;; List of all tokens in the punctuation and parenthesis syntax
+  ;; classes.
+  t (delete-duplicates (append (c-lang-const c-other-op-syntax-tokens)
+                              (c-lang-const c-operator-list))
+                      :test 'string-equal))
+
+(c-lang-defconst c-nonsymbol-token-char-list
+  ;; List containing all chars not in the word, symbol or
+  ;; syntactically irrelevant syntax classes, i.e. all punctuation,
+  ;; parenthesis and string delimiter chars.
+  t (c-with-syntax-table (c-lang-const c-mode-syntax-table)
+      ;; Only go through the chars in the printable ASCII range.  No
+      ;; language so far has 8-bit or widestring operators.
+      (let (list (char 32))
+       (while (< char 127)
+         (or (memq (char-syntax char) '(?w ?_ ?< ?> ?\ ))
+             (setq list (cons (c-int-to-char char) list)))
+         (setq char (1+ char)))
+       list)))
+
 (c-lang-defconst c-nonsymbol-token-regexp
   ;; Regexp matching all tokens in the punctuation and parenthesis
   ;; syntax classes.  Note that this also matches ".", which can start
   ;; a float.
   t (c-make-keywords-re nil
-      (c-with-syntax-table (c-lang-const c-mode-syntax-table)
-       (mapcan (lambda (op)
-                 (if (string-match "\\`\\(\\s.\\|\\s\(\\|\\s\)\\)+\\'" op)
-                     (list op)))
-               (append (c-lang-const c-other-op-syntax-tokens)
-                       (c-lang-const c-operator-list))))))
+      (c-filter-ops (c-lang-const c-all-op-syntax-tokens)
+                   t
+                   "\\`\\(\\s.\\|\\s\(\\|\\s\)\\)+\\'")))
 (c-lang-defvar c-nonsymbol-token-regexp
   (c-lang-const c-nonsymbol-token-regexp))
 
@@ -819,26 +953,34 @@ operators."
 (c-lang-defvar c-assignment-op-regexp
   (c-lang-const c-assignment-op-regexp))
 
+(c-lang-defconst c-<>-multichar-token-regexp
+  ;; Regexp matching all tokens containing "<" or ">" which are longer
+  ;; than one char.
+  t (c-make-keywords-re nil
+      (c-filter-ops (c-lang-const c-all-op-syntax-tokens)
+                   t
+                   ".[<>]\\|[<>].")))
+(c-lang-defvar c-<>-multichar-token-regexp
+  (c-lang-const c-<>-multichar-token-regexp))
+
 (c-lang-defconst c-<-op-cont-regexp
   ;; Regexp matching the second and subsequent characters of all
   ;; multicharacter tokens that begin with "<".
   t (c-make-keywords-re nil
-      (mapcan (lambda (op)
-               (if (string-match "\\`<." op)
-                   (list (substring op 1))))
-             (append (c-lang-const c-other-op-syntax-tokens)
-                     (c-lang-const c-operator-list)))))
+      (c-filter-ops (c-lang-const c-all-op-syntax-tokens)
+                   t
+                   "\\`<."
+                   (lambda (op) (substring op 1)))))
 (c-lang-defvar c-<-op-cont-regexp (c-lang-const c-<-op-cont-regexp))
 
 (c-lang-defconst c->-op-cont-regexp
   ;; Regexp matching the second and subsequent characters of all
   ;; multicharacter tokens that begin with ">".
   t (c-make-keywords-re nil
-      (mapcan (lambda (op)
-               (if (string-match "\\`>." op)
-                   (list (substring op 1))))
-             (append (c-lang-const c-other-op-syntax-tokens)
-                     (c-lang-const c-operator-list)))))
+      (c-filter-ops (c-lang-const c-all-op-syntax-tokens)
+                   t
+                   "\\`>."
+                   (lambda (op) (substring op 1)))))
 (c-lang-defvar c->-op-cont-regexp (c-lang-const c->-op-cont-regexp))
 
 (c-lang-defconst c-stmt-delim-chars
@@ -847,7 +989,7 @@ operators."
   ;; begin with "^" to negate the set.  If ? : operators should be
   ;; detected then the string must end with "?:".
   t    "^;{}?:"
-  awk  "^;{}\n\r?:") ; The newline chars gets special treatment.
+  awk  "^;{}#\n\r?:") ; The newline chars gets special treatment.
 (c-lang-defvar c-stmt-delim-chars (c-lang-const c-stmt-delim-chars))
 
 (c-lang-defconst c-stmt-delim-chars-with-comma
@@ -860,15 +1002,69 @@ operators."
 \f
 ;;; Syntactic whitespace.
 
+(c-lang-defconst c-simple-ws
+  "Regexp matching an ordinary whitespace character.
+Does not contain a \\| operator at the top level."
+  ;; "\\s " is not enough since it doesn't match line breaks.
+  t "\\(\\s \\|[\n\r]\\)")
+
+(c-lang-defconst c-simple-ws-depth
+  ;; Number of regexp grouping parens in `c-simple-ws'.
+  t (regexp-opt-depth (c-lang-const c-simple-ws)))
+
+(c-lang-defconst c-line-comment-starter
+  "String that starts line comments, or nil if such don't exist.
+Line comments are always terminated by newlines.  At least one of
+`c-block-comment-starter' and this one is assumed to be set.
+
+Note that it's currently not enough to set this to support a new
+comment style.  Other stuff like the syntax table must also be set up
+properly."
+  t    "//"
+  awk  "#")
+(c-lang-defvar c-line-comment-starter (c-lang-const c-line-comment-starter))
+
+(c-lang-defconst c-block-comment-starter
+  "String that starts block comments, or nil if such don't exist.
+Block comments are ended by `c-block-comment-ender', which is assumed
+to be set if this is.  At least one of `c-line-comment-starter' and
+this one is assumed to be set.
+
+Note that it's currently not enough to set this to support a new
+comment style.  Other stuff like the syntax table must also be set up
+properly."
+  t    "/*"
+  awk  nil)
+
+(c-lang-defconst c-block-comment-ender
+  "String that ends block comments, or nil if such don't exist.
+
+Note that it's currently not enough to set this to support a new
+comment style.  Other stuff like the syntax table must also be set up
+properly."
+  t    "*/"
+  awk  nil)
+
 (c-lang-defconst c-comment-start-regexp
   ;; Regexp to match the start of any type of comment.
-  ;;
-  ;; TODO: Ought to use `c-comment-prefix-regexp' with some
-  ;; modifications instead of this.
-  t    "/[/*]"
-  awk  "#")
+  t (let ((re (c-make-keywords-re nil
+               (list (c-lang-const c-line-comment-starter)
+                     (c-lang-const c-block-comment-starter)))))
+      (if (memq 'gen-comment-delim c-emacs-features)
+         (concat re "\\|\\s!")
+       re)))
 (c-lang-defvar c-comment-start-regexp (c-lang-const c-comment-start-regexp))
 
+;;;; Added by ACM, 2003/9/18.
+(c-lang-defconst c-block-comment-start-regexp
+  ;; Regexp which matches the start of a block comment (if such exists in the
+  ;; language)
+  t (if (c-lang-const c-block-comment-starter)
+       (regexp-quote (c-lang-const c-block-comment-starter))
+      "\\<\\>"))
+(c-lang-defvar c-block-comment-start-regexp
+  (c-lang-const c-block-comment-start-regexp))
+
 (c-lang-defconst c-literal-start-regexp
   ;; Regexp to match the start of comments and string literals.
   t (concat (c-lang-const c-comment-start-regexp)
@@ -891,129 +1087,235 @@ operators."
 (c-lang-defconst comment-start
   "String that starts comments inserted with M-; etc.
 `comment-start' is initialized from this."
-  t    "// "
-  c    "/* "
-  awk  "# ")
+  ;; Default: Prefer line comments to block comments, and pad with a space.
+  t (concat (or (c-lang-const c-line-comment-starter)
+               (c-lang-const c-block-comment-starter))
+           " ")
+  ;; In C we still default to the block comment style since line
+  ;; comments aren't entirely portable.
+  c "/* ")
 (c-lang-defvar comment-start (c-lang-const comment-start)
   'dont-doc)
 
 (c-lang-defconst comment-end
   "String that ends comments inserted with M-; etc.
 `comment-end' is initialized from this."
-  t    ""
-  c    " */")
+  ;; Default: Use block comment style if comment-start uses block
+  ;; comments, and pad with a space in that case.
+  t (if (string-match (concat "\\`\\("
+                             (c-lang-const c-block-comment-start-regexp)
+                             "\\)")
+                     (c-lang-const comment-start))
+       (concat " " (c-lang-const c-block-comment-ender))
+      ""))
 (c-lang-defvar comment-end (c-lang-const comment-end)
   'dont-doc)
 
 (c-lang-defconst comment-start-skip
   "Regexp to match the start of a comment plus everything up to its body.
 `comment-start-skip' is initialized from this."
-  t    "/\\*+ *\\|//+ *"
-  awk  "#+ *")
+  ;; Default: Allow the last char of the comment starter(s) to be
+  ;; repeated, then allow any amount of horizontal whitespace.
+  t (concat "\\("
+           (c-concat-separated
+            (mapcar (lambda (cs)
+                      (when cs
+                        (concat (regexp-quote cs) "+")))
+                    (list (c-lang-const c-line-comment-starter)
+                          (c-lang-const c-block-comment-starter)))
+            "\\|")
+           "\\)\\s *"))
 (c-lang-defvar comment-start-skip (c-lang-const comment-start-skip)
   'dont-doc)
 
 (c-lang-defconst c-syntactic-ws-start
-  "Regexp matching any sequence that can start syntactic whitespace.
-The only uncertain case is '#' when there are cpp directives."
-  t     "[ \n\t\r\v\f#]\\|/[/*]\\|\\\\[\n\r]"
-  awk   "[ \n\t\r\v\f#]\\|\\\\[\n\r]")
-(c-lang-defvar c-syntactic-ws-start (c-lang-const c-syntactic-ws-start)
-  'dont-doc)
+  ;; Regexp matching any sequence that can start syntactic whitespace.
+  ;; The only uncertain case is '#' when there are cpp directives.
+  t (concat "\\s \\|"
+           (c-make-keywords-re nil
+             (append (list (c-lang-const c-line-comment-starter)
+                           (c-lang-const c-block-comment-starter)
+                           (when (c-lang-const c-opt-cpp-prefix)
+                             "#"))
+                     '("\n" "\r")))
+           "\\|\\\\[\n\r]"
+           (when (memq 'gen-comment-delim c-emacs-features)
+             "\\|\\s!")))
+(c-lang-defvar c-syntactic-ws-start (c-lang-const c-syntactic-ws-start))
 
 (c-lang-defconst c-syntactic-ws-end
-  "Regexp matching any single character that might end syntactic whitespace."
-  t     "[ \n\t\r\v\f/]"
-  awk   "[ \n\t\r\v\f]")
-(c-lang-defvar c-syntactic-ws-end (c-lang-const c-syntactic-ws-end)
-  'dont-doc)
+  ;; Regexp matching any single character that might end syntactic whitespace.
+  t (concat "\\s \\|"
+           (c-make-keywords-re nil
+             (append (when (c-lang-const c-block-comment-ender)
+                       (list
+                        (string
+                         (elt (c-lang-const c-block-comment-ender)
+                              (1- (length
+                                   (c-lang-const c-block-comment-ender)))))))
+                     '("\n" "\r")))
+           (when (memq 'gen-comment-delim c-emacs-features)
+             "\\|\\s!")))
+(c-lang-defvar c-syntactic-ws-end (c-lang-const c-syntactic-ws-end))
+
+(c-lang-defconst c-unterminated-block-comment-regexp
+  ;; Regexp matching an unterminated block comment that doesn't
+  ;; contain line breaks, or nil in languages without block comments.
+  ;; Does not contain a \| operator at the top level.
+  t (when (c-lang-const c-block-comment-starter)
+      (concat
+       (regexp-quote (c-lang-const c-block-comment-starter))
+       ;; It's messy to cook together a regexp that matches anything
+       ;; but c-block-comment-ender.
+       (let ((end (c-lang-const c-block-comment-ender)))
+        (cond ((= (length end) 1)
+               (concat "[^" end "\n\r]*"))
+              ((= (length end) 2)
+               (concat "[^" (substring end 0 1) "\n\r]*"
+                       "\\("
+                       (regexp-quote (substring end 0 1)) "+"
+                       "[^"
+                       ;; The quoting rules inside char classes are silly. :P
+                       (cond ((= (elt end 0) (elt end 1))
+                              (concat (substring end 0 1) "\n\r"))
+                             ((= (elt end 1) ?\])
+                              (concat (substring end 1 2) "\n\r"
+                                      (substring end 0 1)))
+                             (t
+                              (concat (substring end 0 1) "\n\r"
+                                      (substring end 1 2))))
+                       "]"
+                       "[^" (substring end 0 1) "\n\r]*"
+                       "\\)*"))
+              (t
+               (error "Can't handle a block comment ender of length %s"
+                      (length end))))))))
+
+(c-lang-defconst c-block-comment-regexp
+  ;; Regexp matching a block comment that doesn't contain line breaks,
+  ;; or nil in languages without block comments.  The reason we don't
+  ;; allow line breaks is to avoid going very far and risk running out
+  ;; of regexp stack; this regexp is intended to handle only short
+  ;; comments that might be put in the middle of limited constructs
+  ;; like declarations.  Does not contain a \| operator at the top
+  ;; level.
+  t (when (c-lang-const c-unterminated-block-comment-regexp)
+      (concat
+       (c-lang-const c-unterminated-block-comment-regexp)
+       (let ((end (c-lang-const c-block-comment-ender)))
+        (cond ((= (length end) 1)
+               (regexp-quote end))
+              ((= (length end) 2)
+               (concat (regexp-quote (substring end 0 1)) "+"
+                       (regexp-quote (substring end 1 2))))
+              (t
+               (error "Can't handle a block comment ender of length %s"
+                      (length end))))))))
 
 (c-lang-defconst c-nonwhite-syntactic-ws
   ;; Regexp matching a piece of syntactic whitespace that isn't a
   ;; sequence of simple whitespace characters.  As opposed to
   ;; `c-(forward|backward)-syntactic-ws', this doesn't regard cpp
   ;; directives as syntactic whitespace.
-  t (concat "/" (concat
-                "\\("
-                "/[^\n\r]*[\n\r]"      ; Line comment.
-                "\\|"
-                ;; Block comment. We intentionally don't allow line
-                ;; breaks in them to avoid going very far and risk
-                ;; running out of regexp stack; this regexp is
-                ;; intended to handle only short comments that
-                ;; might be put in the middle of limited constructs
-                ;; like declarations.
-                "\\*\\([^*\n\r]\\|\\*[^/\n\r]\\)*\\*/"
-                "\\)")
-           "\\|"
-           "\\\\[\n\r]")               ; Line continuations.
-  awk ("#.*[\n\r]\\|\\\\[\n\r]"))
+  t (c-concat-separated
+     (list (when (c-lang-const c-line-comment-starter)
+            (concat (regexp-quote (c-lang-const c-line-comment-starter))
+                    "[^\n\r]*[\n\r]"))
+          (c-lang-const c-block-comment-regexp)
+          "\\\\[\n\r]"
+          (when (memq 'gen-comment-delim c-emacs-features)
+            "\\s!\\S!*\\s!"))
+     "\\|"))
 
 (c-lang-defconst c-syntactic-ws
   ;; Regexp matching syntactic whitespace, including possibly the
   ;; empty string.  As opposed to `c-(forward|backward)-syntactic-ws',
   ;; this doesn't regard cpp directives as syntactic whitespace.  Does
   ;; not contain a \| operator at the top level.
-  t (concat "[ \t\n\r\f\v]*\\("
-           "\\(" (c-lang-const c-nonwhite-syntactic-ws) "\\)"
-           "[ \t\n\r\f\v]*\\)*"))
+  t (concat (c-lang-const c-simple-ws) "*"
+           "\\("
+           (concat "\\(" (c-lang-const c-nonwhite-syntactic-ws) "\\)"
+                   (c-lang-const c-simple-ws) "*")
+           "\\)*"))
 
 (c-lang-defconst c-syntactic-ws-depth
   ;; Number of regexp grouping parens in `c-syntactic-ws'.
-  t (c-regexp-opt-depth (c-lang-const c-syntactic-ws)))
+  t (regexp-opt-depth (c-lang-const c-syntactic-ws)))
 
 (c-lang-defconst c-nonempty-syntactic-ws
   ;; Regexp matching syntactic whitespace, which is at least one
   ;; character long.  As opposed to `c-(forward|backward)-syntactic-ws',
   ;; this doesn't regard cpp directives as syntactic whitespace.  Does
   ;; not contain a \| operator at the top level.
-  t (concat "\\([ \t\n\r\f\v]\\|"
+  t (concat "\\("
+           (c-lang-const c-simple-ws)
+           "\\|"
            (c-lang-const c-nonwhite-syntactic-ws)
            "\\)+"))
 
 (c-lang-defconst c-nonempty-syntactic-ws-depth
   ;; Number of regexp grouping parens in `c-nonempty-syntactic-ws'.
-  t (c-regexp-opt-depth (c-lang-const c-nonempty-syntactic-ws)))
+  t (regexp-opt-depth (c-lang-const c-nonempty-syntactic-ws)))
 
 (c-lang-defconst c-single-line-syntactic-ws
   ;; Regexp matching syntactic whitespace without any line breaks.  As
   ;; opposed to `c-(forward|backward)-syntactic-ws', this doesn't
   ;; regard cpp directives as syntactic whitespace.  Does not contain
   ;; a \| operator at the top level.
-  t (concat "[ \t]*\\("
-           "/\\*\\([^*\n\r]\\|\\*[^/\n\r]\\)*\\*/" ; Block comment
-           "[ \t]*\\)*")
-  awk ("[ \t]*\\(#.*$\\)?"))
+  t (if (c-lang-const c-block-comment-regexp)
+       (concat "\\s *\\("
+               (c-lang-const c-block-comment-regexp)
+               "\\s *\\)*")
+      "\\s *"))
 
 (c-lang-defconst c-single-line-syntactic-ws-depth
   ;; Number of regexp grouping parens in `c-single-line-syntactic-ws'.
-  t (c-regexp-opt-depth (c-lang-const c-single-line-syntactic-ws)))
+  t (regexp-opt-depth (c-lang-const c-single-line-syntactic-ws)))
 
-(c-lang-defvar c-syntactic-eol
+(c-lang-defconst c-syntactic-eol
   ;; Regexp that matches when there is no syntactically significant
   ;; text before eol.  Macros are regarded as syntactically
   ;; significant text here.
-  (concat (concat
-          ;; Match horizontal whitespace and block comments that
-          ;; don't contain newlines.
-          "\\(\\s \\|"
-          (concat "/\\*"
-                  "\\([^*\n\r]\\|\\*[^/\n\r]\\)*"
-                  "\\*/")
-          "\\)*")
-         (concat
-          ;; Match eol (possibly inside a block comment or preceded
-          ;; by a line continuation backslash), or the beginning of a
-          ;; line comment.  Note: This has to be modified for awk
-          ;; where line comments start with '#'.
-          "\\("
-          (concat "\\("
-                  "/\\*\\([^*\n\r]\\|\\*[^/\n\r]\\)*"
-                  "\\|"
-                  "\\\\"
-                  "\\)?"
+  t (concat (c-lang-const c-single-line-syntactic-ws)
+           ;; Match eol (possibly inside a block comment or preceded
+           ;; by a line continuation backslash), or the beginning of a
+           ;; line comment.  Note: This has to be modified for awk
+           ;; where line comments start with '#'.
+           "\\("
+           (c-concat-separated
+            (list (when (c-lang-const c-line-comment-starter)
+                    (regexp-quote (c-lang-const c-line-comment-starter)))
+                  (when (c-lang-const c-unterminated-block-comment-regexp)
+                    (concat (c-lang-const c-unterminated-block-comment-regexp)
+                            "$"))
+                  "\\\\$"
                   "$")
-          "\\|//\\)")))
+            "\\|")
+           "\\)"))
+(c-lang-defvar c-syntactic-eol (c-lang-const c-syntactic-eol))
+
+\f
+;;; Syntactic analysis ("virtual semicolons") for line-oriented languages (AWK).
+(c-lang-defconst c-at-vsemi-p-fn
+  "Contains a function \"Is there a virtual semicolon at POS or point?\".
+Such a function takes one optional parameter, a buffer position (defaults to
+point), and returns NIL or t.  This variable contains NIL for languages which
+don't have EOL terminated statements. "
+  t nil
+  awk 'c-awk-at-vsemi-p)
+(c-lang-defvar c-at-vsemi-p-fn (c-lang-const c-at-vsemi-p-fn))
+
+(c-lang-defconst c-vsemi-status-unknown-p-fn
+  "Contains a function \"are we unsure whether there is a virtual semicolon on this line?\".
+The (admittedly kludgey) purpose of such a function is to prevent an infinite
+recursion in c-beginning-of-statement-1 when point starts at a `while' token.
+The function MUST NOT UNDER ANY CIRCUMSTANCES call c-beginning-of-statement-1,
+even indirectly.  This variable contains NIL for languages which don't have
+EOL terminated statements."
+  t nil
+  awk 'c-awk-vsemi-status-unknown-p)
+(c-lang-defvar c-vsemi-status-unknown-p-fn
+  (c-lang-const c-vsemi-status-unknown-p-fn))
 
 \f
 ;;; In-comment text handling.
@@ -1137,6 +1439,14 @@ not the type face."
 (c-lang-defvar c-opt-type-component-key
   (c-lang-const c-opt-type-component-key))
 
+(c-lang-defconst c-type-start-kwds
+  ;; All keywords that can start a type (i.e. are either a type prefix
+  ;; or a complete type).
+  t (delete-duplicates (append (c-lang-const c-primitive-type-kwds)
+                              (c-lang-const c-type-prefix-kwds)
+                              (c-lang-const c-type-modifier-kwds))
+                      :test 'string-equal))
+
 (c-lang-defconst c-class-decl-kwds
   "Keywords introducing declarations where the following block (if any)
 contains another declaration level that should be considered a class.
@@ -1187,14 +1497,26 @@ will be handled."
 
 (c-lang-defconst c-other-block-decl-kwds
   "Keywords where the following block (if any) contains another
-declaration level that should not be considered a class.
+declaration level that should not be considered a class.  For every
+keyword here, CC Mode will add a set of special syntactic symbols for
+those blocks.  E.g. if the keyword is \"foo\" then there will be
+`foo-open', `foo-close', and `infoo' symbols.
+
+The intention is that this category should be used for block
+constructs that aren't related to object orientation concepts like
+classes (which thus also include e.g. interfaces, templates,
+contracts, structs, etc).  The more pragmatic distinction is that
+while most want some indentation inside classes, it's fairly common
+that they don't want it in some of these constructs, so it should be
+simple to configure that differently from classes.  See also
+`c-class-decl-kwds'.
 
 If any of these also are on `c-type-list-kwds', `c-ref-list-kwds',
 `c-colon-type-list-kwds', `c-paren-nontype-kwds', `c-paren-type-kwds',
 `c-<>-type-kwds', or `c-<>-arglist-kwds' then the associated clauses
 will be handled."
   t   nil
-  c   '("extern")
+  (c objc) '("extern")
   c++ '("namespace" "extern")
   idl '("module"
        ;; In CORBA CIDL:
@@ -1207,39 +1529,52 @@ will be handled."
 (c-lang-defvar c-other-decl-block-key (c-lang-const c-other-decl-block-key))
 
 (c-lang-defconst c-typedef-decl-kwds
-  "Keywords introducing declarations where the identifiers are defined
-to be types.
+  "Keywords introducing declarations where the identifier(s) being
+declared are types.
 
 If any of these also are on `c-type-list-kwds', `c-ref-list-kwds',
 `c-colon-type-list-kwds', `c-paren-nontype-kwds', `c-paren-type-kwds',
 `c-<>-type-kwds', or `c-<>-arglist-kwds' then the associated clauses
 will be handled."
-  t    '("typedef")
-  (java awk) nil)
+  ;; Default to `c-class-decl-kwds' and `c-brace-list-decl-kwds'
+  ;; (since e.g. "Foo" is a type that's being defined in "class Foo
+  ;; {...}").
+  t    (append (c-lang-const c-class-decl-kwds)
+              (c-lang-const c-brace-list-decl-kwds))
+  ;; Languages that have a "typedef" construct.
+  (c c++ objc idl pike) (append (c-lang-const c-typedef-decl-kwds)
+                               '("typedef"))
+  ;; Unlike most other languages, exception names are not handled as
+  ;; types in IDL since they only can occur in "raises" specs.
+  idl  (delete "exception" (append (c-lang-const c-typedef-decl-kwds) nil)))
 
 (c-lang-defconst c-typeless-decl-kwds
-  "Keywords introducing declarations where the identifier (declarator)
-list follows directly after the keyword, without any type.
+  "Keywords introducing declarations where the \(first) identifier
+\(declarator) follows directly after the keyword, without any type.
 
 If any of these also are on `c-type-list-kwds', `c-ref-list-kwds',
 `c-colon-type-list-kwds', `c-paren-nontype-kwds', `c-paren-type-kwds',
 `c-<>-type-kwds', or `c-<>-arglist-kwds' then the associated clauses
 will be handled."
-  t    nil
-  ;; Unlike most other languages, exception names are not handled as
-  ;; types in IDL since they only can occur in "raises" specs.
-  idl  '("exception" "factory" "finder" "native"
-        ;; In CORBA PSDL:
-        "key" "stores"
-        ;; In CORBA CIDL:
-        ;; Note that "manages" here clashes with its presence on
-        ;; `c-type-list-kwds' for IDL.
-        "executor" "facet" "manages" "segment")
-  pike '("constant"))
+  ;; Default to `c-class-decl-kwds' and `c-brace-list-decl-kwds'
+  ;; (since e.g. "Foo" is the identifier being defined in "class Foo
+  ;; {...}").
+  t    (append (c-lang-const c-class-decl-kwds)
+              (c-lang-const c-brace-list-decl-kwds))
+  ;; Note: "manages" for CORBA CIDL clashes with its presence on
+  ;; `c-type-list-kwds' for IDL.
+  idl  (append (c-lang-const c-typeless-decl-kwds)
+              '("factory" "finder" "native"
+                ;; In CORBA PSDL:
+                "key" "stores"
+                ;; In CORBA CIDL:
+                "facet"))
+  pike (append (c-lang-const c-class-decl-kwds)
+              '("constant")))
 
 (c-lang-defconst c-modifier-kwds
   "Keywords that can prefix normal declarations of identifiers
-\(and typically acts as flags).  Things like argument declarations
+\(and typically act as flags).  Things like argument declarations
 inside function headers are also considered declarations in this
 sense.
 
@@ -1270,53 +1605,119 @@ will be handled."
   "Keywords that can start or prefix any declaration level construct,
 besides those on `c-class-decl-kwds', `c-brace-list-decl-kwds',
 `c-other-block-decl-kwds', `c-typedef-decl-kwds',
-`c-typeless-decl-kwds' and `c-modifier-kwds'.  In a declaration, these
-keywords are also recognized inside or after the identifiers that
-makes up the type.
+`c-typeless-decl-kwds' and `c-modifier-kwds'.
 
 If any of these also are on `c-type-list-kwds', `c-ref-list-kwds',
 `c-colon-type-list-kwds', `c-paren-nontype-kwds', `c-paren-type-kwds',
 `c-<>-type-kwds', or `c-<>-arglist-kwds' then the associated clauses
 will be handled."
   t       nil
-  (c c++) '("__declspec")              ; MSVC extension.
   objc    '("@class" "@end" "@defs")
   java    '("import" "package")
   pike    '("import" "inherit"))
 
+(c-lang-defconst c-decl-start-kwds
+  "Keywords that always start declarations, wherever they occur.
+This can be used for declarations that aren't recognized by the normal
+combination of `c-decl-prefix-re' and `c-decl-start-re'."
+  t    nil
+  ;; Classes can be declared anywhere in a Pike expression.
+  pike '("class"))
+
+(c-lang-defconst c-decl-hangon-kwds
+  "Keywords that can occur anywhere in a declaration level construct.
+This is used for self-contained things that can be tacked on anywhere
+on a declaration and that should be ignored to be able to recognize it
+correctly.  Typical cases are compiler extensions like
+\"__attribute__\" or \"__declspec\":
+
+    __declspec(noreturn) void foo();
+    class __declspec(dllexport) classname {...};
+    void foo() __attribute__((noreturn));
+
+Note that unrecognized plain symbols are skipped anyway if they occur
+before the type, so such things are not necessary to mention here.
+Mentioning them here is necessary only if they can occur in other
+places, or if they are followed by a construct that must be skipped
+over \(like the parens in the \"__attribute__\" and \"__declspec\"
+examples above).  In the last case, they alse need to be present on
+one of `c-type-list-kwds', `c-ref-list-kwds',
+`c-colon-type-list-kwds', `c-paren-nontype-kwds', `c-paren-type-kwds',
+`c-<>-type-kwds', or `c-<>-arglist-kwds'."
+  ;; NB: These are currently not recognized in all parts of a
+  ;; declaration.  Specifically, they aren't recognized in the middle
+  ;; of multi-token types, inside declarators, and between the
+  ;; identifier and the arglist paren of a function declaration.
+  ;;
+  ;; FIXME: This ought to be user customizable since compiler stuff
+  ;; like this usually is wrapped in project specific macros.  (It'd
+  ;; of course be even better if we could cope without knowing this.)
+  t nil
+  (c c++) '(;; GCC extension.
+           "__attribute__"
+           ;; MSVC extension.
+           "__declspec"))
+
+(c-lang-defconst c-decl-hangon-key
+  ;; Adorned regexp matching `c-decl-hangon-kwds'.
+  t (c-make-keywords-re t (c-lang-const c-decl-hangon-kwds)))
+(c-lang-defvar c-decl-hangon-key (c-lang-const c-decl-hangon-key))
+
+(c-lang-defconst c-prefix-spec-kwds
+  ;; All keywords that can occur in the preamble of a declaration.
+  ;; They typically occur before the type, but they are also matched
+  ;; after presumptive types since we often can't be sure that
+  ;; something is a type or just some sort of macro in front of the
+  ;; declaration.  They might be ambiguous with types or type
+  ;; prefixes.
+  t (delete-duplicates (append (c-lang-const c-class-decl-kwds)
+                              (c-lang-const c-brace-list-decl-kwds)
+                              (c-lang-const c-other-block-decl-kwds)
+                              (c-lang-const c-typedef-decl-kwds)
+                              (c-lang-const c-typeless-decl-kwds)
+                              (c-lang-const c-modifier-kwds)
+                              (c-lang-const c-other-decl-kwds)
+                              (c-lang-const c-decl-start-kwds)
+                              (c-lang-const c-decl-hangon-kwds))
+                      :test 'string-equal))
+
+(c-lang-defconst c-prefix-spec-kwds-re
+  ;; Adorned regexp of `c-prefix-spec-kwds'.
+  t (c-make-keywords-re t (c-lang-const c-prefix-spec-kwds)))
+(c-lang-defvar c-prefix-spec-kwds-re (c-lang-const c-prefix-spec-kwds-re))
+
 (c-lang-defconst c-specifier-key
-  ;; Adorned regexp matching keywords that can start a declaration but
-  ;; not a type.
+  ;; Adorned regexp of the keywords in `c-prefix-spec-kwds' that
+  ;; aren't ambiguous with types or type prefixes.
   t (c-make-keywords-re t
-      (set-difference (append (c-lang-const c-class-decl-kwds)
-                             (c-lang-const c-brace-list-decl-kwds)
-                             (c-lang-const c-other-block-decl-kwds)
-                             (c-lang-const c-typedef-decl-kwds)
-                             (c-lang-const c-typeless-decl-kwds)
-                             (c-lang-const c-modifier-kwds)
-                             (c-lang-const c-other-decl-kwds))
-                     (append (c-lang-const c-primitive-type-kwds)
-                             (c-lang-const c-type-prefix-kwds)
-                             (c-lang-const c-type-modifier-kwds))
+      (set-difference (c-lang-const c-prefix-spec-kwds)
+                     (c-lang-const c-type-start-kwds)
                      :test 'string-equal)))
 (c-lang-defvar c-specifier-key (c-lang-const c-specifier-key))
 
+(c-lang-defconst c-postfix-spec-kwds
+  ;; Keywords that can occur after argument list of a function header
+  ;; declaration, i.e. in the "K&R region".
+  t (append (c-lang-const c-postfix-decl-spec-kwds)
+           (c-lang-const c-decl-hangon-kwds)))
+
+(c-lang-defconst c-not-decl-init-keywords
+  ;; Adorned regexp matching all keywords that can't appear at the
+  ;; start of a declaration.
+  t (c-make-keywords-re t
+      (set-difference (c-lang-const c-keywords)
+                     (append (c-lang-const c-type-start-kwds)
+                             (c-lang-const c-prefix-spec-kwds))
+                     :test 'string-equal)))
+(c-lang-defvar c-not-decl-init-keywords
+  (c-lang-const c-not-decl-init-keywords))
+
 (c-lang-defconst c-protection-kwds
-  "Protection label keywords in classes."
+  "Access protection label keywords in classes."
   t    nil
   c++  '("private" "protected" "public")
   objc '("@private" "@protected" "@public"))
 
-(c-lang-defconst c-opt-access-key
-  ;; Regexp matching an access protection label in a class, or nil in
-  ;; languages that don't have such things.
-  t    (if (c-lang-const c-protection-kwds)
-          (c-make-keywords-re t (c-lang-const c-protection-kwds)))
-  c++  (concat "\\("
-              (c-make-keywords-re nil (c-lang-const c-protection-kwds))
-              "\\)[ \t\n\r\f\v]*:"))
-(c-lang-defvar c-opt-access-key (c-lang-const c-opt-access-key))
-
 (c-lang-defconst c-block-decls-with-vars
   "Keywords introducing declarations that can contain a block which
 might be followed by variable declarations, e.g. like \"foo\" in
@@ -1342,7 +1743,6 @@ The keywords on list are assumed to also be present on one of the
 between the header and the body \(i.e. the \"K&R-region\") in
 declarations."
   t    nil
-  (c c++) '("__attribute__")           ; GCC extension.
   java '("extends" "implements" "throws")
   idl  '("context" "getraises" "manages" "primarykey" "raises" "setraises"
         "supports"
@@ -1366,22 +1766,18 @@ reason to put keywords on this list if they are on `c-type-prefix-kwds'.
 There's also no reason to add keywords that prefixes a normal
 declaration consisting of a type followed by a declarator (list), so
 the keywords on `c-modifier-kwds' should normally not be listed here
-too.
+either.
 
 Note: Use `c-typeless-decl-kwds' for keywords followed by a function
 or variable identifier (that's being defined)."
-  t    '("struct" "union" "enum")
-  (c awk) nil
+  t    nil
   c++  '("operator")
-  objc (append '("@class" "@interface" "@implementation" "@protocol")
-              (c-lang-const c-type-list-kwds))
-  java '("class" "import" "interface" "new" "extends" "implements" "throws")
-  idl  (append '("component" "eventtype" "home" "interface" "manages" "native"
-                "primarykey" "supports" "valuetype"
-                ;; In CORBA PSDL:
-                "as" "implements" "of" "scope" "storagehome" "storagetype")
-              (c-lang-const c-type-list-kwds))
-  pike '("class" "enum" "inherit"))
+  objc '("@class")
+  java '("import" "new" "extends" "implements" "throws")
+  idl  '("manages" "native" "primarykey" "supports"
+        ;; In CORBA PSDL:
+        "as" "implements" "of" "scope")
+  pike '("inherit"))
 
 (c-lang-defconst c-ref-list-kwds
   "Keywords that may be followed by a comma separated list of
@@ -1414,9 +1810,8 @@ special case when the list can contain only one element.)"
 (c-lang-defconst c-colon-type-list-re
   "Regexp matched after the keywords in `c-colon-type-list-kwds' to skip
 forward to the colon.  The end of the match is assumed to be directly
-after the colon, so the regexp should end with \":\" although that
-isn't necessary.  Must be a regexp if `c-colon-type-list-kwds' isn't
-nil."
+after the colon, so the regexp should end with \":\".  Must be a
+regexp if `c-colon-type-list-kwds' isn't nil."
   t (if (c-lang-const c-colon-type-list-kwds)
        ;; Disallow various common punctuation chars that can't come
        ;; before the ":" that starts the inherit list after "class"
@@ -1429,7 +1824,10 @@ nil."
   "Keywords that may be followed by a parenthesis expression that doesn't
 contain type identifiers."
   t       nil
-  (c c++) '("__declspec"))             ; MSVC extension.
+  (c c++) '(;; GCC extension.
+           "__attribute__"
+           ;; MSVC extension.
+           "__declspec"))
 
 (c-lang-defconst c-paren-type-kwds
   "Keywords that may be followed by a parenthesis expression containing
@@ -1512,6 +1910,12 @@ identifiers that follows the type in a normal declaration."
   t (c-make-keywords-re t (c-lang-const c-block-stmt-2-kwds)))
 (c-lang-defvar c-block-stmt-2-key (c-lang-const c-block-stmt-2-key))
 
+(c-lang-defconst c-block-stmt-kwds
+  ;; Union of `c-block-stmt-1-kwds' and `c-block-stmt-2-kwds'.
+  t (delete-duplicates (append (c-lang-const c-block-stmt-1-kwds)
+                              (c-lang-const c-block-stmt-2-kwds))
+                      :test 'string-equal))
+
 (c-lang-defconst c-opt-block-stmt-key
   ;; Regexp matching the start of any statement that has a
   ;; substatement (except a bare block).  Nil in languages that
@@ -1563,10 +1967,15 @@ nevertheless contains a list separated with ';' and not ','."
 (c-lang-defvar c-opt-asm-stmt-key (c-lang-const c-opt-asm-stmt-key))
 
 (c-lang-defconst c-label-kwds
-  "Keywords introducing labels in blocks."
+  "Keywords introducing colon terminated labels in blocks."
   t '("case" "default")
   awk nil)
 
+(c-lang-defconst c-label-kwds-regexp
+  ;; Adorned regexp matching any keyword that introduces a label.
+  t (c-make-keywords-re t (c-lang-const c-label-kwds)))
+(c-lang-defvar c-label-kwds-regexp (c-lang-const c-label-kwds-regexp))
+
 (c-lang-defconst c-before-label-kwds
   "Keywords that might be followed by a label identifier."
   t    '("goto")
@@ -1575,11 +1984,6 @@ nevertheless contains a list separated with ';' and not ','."
   idl  nil
   awk  nil)
 
-(c-lang-defconst c-label-kwds-regexp
-  ;; Regexp matching any keyword that introduces a label.
-  t (c-make-keywords-re t (c-lang-const c-label-kwds)))
-(c-lang-defvar c-label-kwds-regexp (c-lang-const c-label-kwds-regexp))
-
 (c-lang-defconst c-constant-kwds
   "Keywords for constants."
   t       nil
@@ -1602,11 +2006,9 @@ nevertheless contains a list separated with ';' and not ','."
   ;; `c-primary-expr-kwds' and all keyword operators in `c-operators'.
   t (delete-duplicates
      (append (c-lang-const c-primary-expr-kwds)
-            (c-with-syntax-table (c-lang-const c-mode-syntax-table)
-              (mapcan (lambda (op)
-                        (and (string-match "\\`\\(\\w\\|\\s_\\)+\\'" op)
-                             (list op)))
-                      (c-lang-const c-operator-list))))
+            (c-filter-ops (c-lang-const c-operator-list)
+                          t
+                          "\\`\\(\\w\\|\\s_\\)+\\'"))
      :test 'string-equal))
 
 (c-lang-defconst c-lambda-kwds
@@ -1615,40 +2017,19 @@ expressions."
   t    nil
   pike '("lambda"))
 
-(c-lang-defconst c-opt-lambda-key
-  ;; Adorned regexp matching the start of lambda constructs, or nil in
-  ;; languages that don't have such things.
-  t (and (c-lang-const c-lambda-kwds)
-        (c-make-keywords-re t (c-lang-const c-lambda-kwds))))
-(c-lang-defvar c-opt-lambda-key (c-lang-const c-opt-lambda-key))
-
 (c-lang-defconst c-inexpr-block-kwds
   "Keywords that start constructs followed by statement blocks which can
 be used in expressions \(the gcc extension for this in C and C++ is
-handled separately)."
+handled separately by `c-recognize-paren-inexpr-blocks')."
   t    nil
   pike '("catch" "gauge"))
 
-(c-lang-defconst c-opt-inexpr-block-key
-  ;; Regexp matching the start of in-expression statements, or nil in
-  ;; languages that don't have such things.
-  t    nil
-  pike (c-make-keywords-re t (c-lang-const c-inexpr-block-kwds)))
-(c-lang-defvar c-opt-inexpr-block-key (c-lang-const c-opt-inexpr-block-key))
-
 (c-lang-defconst c-inexpr-class-kwds
   "Keywords that can start classes inside expressions."
   t    nil
   java '("new")
   pike '("class"))
 
-(c-lang-defconst c-opt-inexpr-class-key
-  ;; Regexp matching the start of a class in an expression, or nil in
-  ;; languages that don't have such things.
-  t (and (c-lang-const c-inexpr-class-kwds)
-        (c-make-keywords-re t (c-lang-const c-inexpr-class-kwds))))
-(c-lang-defvar c-opt-inexpr-class-key (c-lang-const c-opt-inexpr-class-key))
-
 (c-lang-defconst c-inexpr-brace-list-kwds
   "Keywords that can start brace list blocks inside expressions.
 Note that Java specific rules are currently applied to tell this from
@@ -1665,30 +2046,26 @@ Note that Java specific rules are currently applied to tell this from
 (c-lang-defvar c-opt-inexpr-brace-list-key
   (c-lang-const c-opt-inexpr-brace-list-key))
 
-(c-lang-defconst c-any-class-key
-  ;; Regexp matching the start of any class, both at top level and in
-  ;; expressions.
-  t (c-make-keywords-re t
-      (append (c-lang-const c-class-decl-kwds)
-             (c-lang-const c-inexpr-class-kwds))))
-(c-lang-defvar c-any-class-key (c-lang-const c-any-class-key))
-
 (c-lang-defconst c-decl-block-key
-  ;; Regexp matching the start of any declaration-level block that
-  ;; contain another declaration level, i.e. that isn't a function
-  ;; block or brace list.
-  t (c-make-keywords-re t
-      (append (c-lang-const c-class-decl-kwds)
-             (c-lang-const c-other-block-decl-kwds)
-             (c-lang-const c-inexpr-class-kwds)))
-  ;; In Pike modifiers might be followed by a block
-  ;; to apply to several declarations.
-  pike (concat (c-lang-const c-decl-block-key)
-              "\\|"
-              "\\(" (c-make-keywords-re nil
-                      (c-lang-const c-modifier-kwds)) "\\)"
-              (c-lang-const c-syntactic-ws)
-              "{"))
+  ;; Regexp matching keywords in any construct that contain another
+  ;; declaration level, i.e. that isn't followed by a function block
+  ;; or brace list.  When the first submatch matches, it's an
+  ;; unambiguous construct, otherwise it's an ambiguous match that
+  ;; might also be the return type of a function declaration.
+  t (let* ((decl-kwds (append (c-lang-const c-class-decl-kwds)
+                             (c-lang-const c-other-block-decl-kwds)
+                             (c-lang-const c-inexpr-class-kwds)))
+          (unambiguous (set-difference decl-kwds
+                                       (c-lang-const c-type-start-kwds)
+                                       :test 'string-equal))
+          (ambiguous (intersection decl-kwds
+                                   (c-lang-const c-type-start-kwds)
+                                   :test 'string-equal)))
+      (if ambiguous
+         (concat (c-make-keywords-re t unambiguous)
+                 "\\|"
+                 (c-make-keywords-re t ambiguous))
+       (c-make-keywords-re t unambiguous))))
 (c-lang-defvar c-decl-block-key (c-lang-const c-decl-block-key))
 
 (c-lang-defconst c-bitfield-kwds
@@ -1794,7 +2171,7 @@ Note that Java specific rules are currently applied to tell this from
            alist (cdr alist))
       (setplist (intern kwd obarray)
                ;; Emacs has an odd bug that causes `mapcan' to fail
-               ;; with unintelligible errors.  (XEmacs >= 20 works.)
+               ;; with unintelligible errors.  (XEmacs works.)
                ;;(mapcan (lambda (lang-const)
                ;;            (list lang-const t))
                ;;          lang-const-list)
@@ -1804,8 +2181,8 @@ Note that Java specific rules are currently applied to tell this from
     obarray))
 
 (c-lang-defconst c-regular-keywords-regexp
-  ;; Adorned regexp matching all keywords that aren't types or
-  ;; constants.
+  ;; Adorned regexp matching all keywords that should be fontified
+  ;; with the keywords face.  I.e. that aren't types or constants.
   t (c-make-keywords-re t
       (set-difference (c-lang-const c-keywords)
                      (append (c-lang-const c-primitive-type-kwds)
@@ -1814,25 +2191,6 @@ Note that Java specific rules are currently applied to tell this from
 (c-lang-defvar c-regular-keywords-regexp
   (c-lang-const c-regular-keywords-regexp))
 
-(c-lang-defconst c-not-decl-init-keywords
-  ;; Adorned regexp matching all keywords that can't appear at the
-  ;; start of a declaration.
-  t (c-make-keywords-re t
-      (set-difference (c-lang-const c-keywords)
-                     (append (c-lang-const c-primitive-type-kwds)
-                             (c-lang-const c-type-prefix-kwds)
-                             (c-lang-const c-type-modifier-kwds)
-                             (c-lang-const c-class-decl-kwds)
-                             (c-lang-const c-brace-list-decl-kwds)
-                             (c-lang-const c-other-block-decl-kwds)
-                             (c-lang-const c-typedef-decl-kwds)
-                             (c-lang-const c-typeless-decl-kwds)
-                             (c-lang-const c-modifier-kwds)
-                             (c-lang-const c-other-decl-kwds))
-                     :test 'string-equal)))
-(c-lang-defvar c-not-decl-init-keywords
-  (c-lang-const c-not-decl-init-keywords))
-
 (c-lang-defconst c-primary-expr-regexp
   ;; Regexp matching the start of any primary expression, i.e. any
   ;; literal, symbol, prefix operator, and '('.  It doesn't need to
@@ -1842,92 +2200,108 @@ Note that Java specific rules are currently applied to tell this from
   ;; be a match of e.g. an infix operator. (The case with ambiguous
   ;; keyword operators isn't handled.)
 
-  t (c-with-syntax-table (c-lang-const c-mode-syntax-table)
-      (let* ((prefix-ops
-             (mapcan (lambda (op)
-                       ;; Filter out the special case prefix
-                       ;; operators that are close parens.
-                       (unless (string-match "\\s\)" op)
-                         (list op)))
-                     (mapcan
-                      (lambda (opclass)
-                        (when (eq (car opclass) 'prefix)
-                          (append (cdr opclass) nil)))
-                      (c-lang-const c-operators))))
-
-            (nonkeyword-prefix-ops
-             (mapcan (lambda (op)
-                       (unless (string-match "\\`\\(\\w\\|\\s_\\)+\\'" op)
-                         (list op)))
-                     prefix-ops))
-
-            (in-or-postfix-ops
-             (mapcan (lambda (opclass)
-                       (when (memq (car opclass)
-                                   '(postfix
-                                     left-assoc
-                                     right-assoc
-                                     right-assoc-sequence))
-                         (append (cdr opclass) nil)))
-                     (c-lang-const c-operators)))
-
-            (unambiguous-prefix-ops (set-difference nonkeyword-prefix-ops
-                                                    in-or-postfix-ops
-                                                    :test 'string-equal))
-            (ambiguous-prefix-ops (intersection nonkeyword-prefix-ops
-                                                in-or-postfix-ops
-                                                :test 'string-equal)))
-
-       (concat
-        "\\("
-        ;; Take out all symbol class operators from `prefix-ops' and make the
-        ;; first submatch from them together with `c-primary-expr-kwds'.
-        (c-make-keywords-re t
-          (append (c-lang-const c-primary-expr-kwds)
-                  (set-difference prefix-ops nonkeyword-prefix-ops
-                                  :test 'string-equal)))
-
-        "\\|"
-        ;; Match all ambiguous operators.
-        (c-make-keywords-re nil
-          (intersection nonkeyword-prefix-ops in-or-postfix-ops
-                        :test 'string-equal))
-        "\\)"
+  t (let* ((prefix-ops
+           (c-filter-ops (c-lang-const c-operators)
+                         '(prefix)
+                         (lambda (op)
+                           ;; Filter out the special case prefix
+                           ;; operators that are close parens.
+                           (not (string-match "\\s)" op)))))
+
+          (nonkeyword-prefix-ops
+           (c-filter-ops prefix-ops
+                         t
+                         "\\`\\(\\s.\\|\\s(\\|\\s)\\)+\\'"))
+
+          (in-or-postfix-ops
+           (c-filter-ops (c-lang-const c-operators)
+                         '(postfix
+                           postfix-if-paren
+                           left-assoc
+                           right-assoc
+                           right-assoc-sequence)
+                         t))
+
+          (unambiguous-prefix-ops (set-difference nonkeyword-prefix-ops
+                                                  in-or-postfix-ops
+                                                  :test 'string-equal))
+          (ambiguous-prefix-ops (intersection nonkeyword-prefix-ops
+                                              in-or-postfix-ops
+                                              :test 'string-equal)))
+
+      (concat
+       "\\("
+       ;; Take out all symbol class operators from `prefix-ops' and make the
+       ;; first submatch from them together with `c-primary-expr-kwds'.
+       (c-make-keywords-re t
+        (append (c-lang-const c-primary-expr-kwds)
+                (set-difference prefix-ops nonkeyword-prefix-ops
+                                :test 'string-equal)))
+
+       "\\|"
+       ;; Match all ambiguous operators.
+       (c-make-keywords-re nil
+        (intersection nonkeyword-prefix-ops in-or-postfix-ops
+                      :test 'string-equal))
+       "\\)"
 
-        "\\|"
-        ;; Now match all other symbols.
-        (c-lang-const c-symbol-start)
+       "\\|"
+       ;; Now match all other symbols.
+       (c-lang-const c-symbol-start)
 
-        "\\|"
-        ;; The chars that can start integer and floating point
-        ;; constants.
-        "\\.?[0-9]"
+       "\\|"
+       ;; The chars that can start integer and floating point
+       ;; constants.
+       "\\.?[0-9]"
 
-        "\\|"
-        ;; The nonambiguous operators from `prefix-ops'.
-        (c-make-keywords-re nil
-          (set-difference nonkeyword-prefix-ops in-or-postfix-ops
-                          :test 'string-equal))
+       "\\|"
+       ;; The nonambiguous operators from `prefix-ops'.
+       (c-make-keywords-re nil
+        (set-difference nonkeyword-prefix-ops in-or-postfix-ops
+                        :test 'string-equal))
 
-        "\\|"
-        ;; Match string and character literals.
-        "\\s\""
-        (if (memq 'gen-string-delim c-emacs-features)
-            "\\|\\s|"
-          "")))))
+       "\\|"
+       ;; Match string and character literals.
+       "\\s\""
+       (if (memq 'gen-string-delim c-emacs-features)
+          "\\|\\s|"
+        ""))))
 (c-lang-defvar c-primary-expr-regexp (c-lang-const c-primary-expr-regexp))
 
 \f
 ;;; Additional constants for parser-level constructs.
 
 (c-lang-defconst c-decl-prefix-re
-  "Regexp matching something that might precede a declaration or a cast,
-such as the last token of a preceding statement or declaration.  It
-should not match bob, though.  It can't require a match longer than
-one token.  The end of the token is taken to be at the end of the
-first submatch.  It must not include any following whitespace.  It's
-undefined whether identifier syntax (see `c-identifier-syntax-table')
-is in effect or not."
+  "Regexp matching something that might precede a declaration, cast or
+label, such as the last token of a preceding statement or declaration.
+This is used in the common situation where a declaration or cast
+doesn't start with any specific token that can be searched for.
+
+The regexp should not match bob; that is done implicitly.  It can't
+require a match longer than one token.  The end of the token is taken
+to be at the end of the first submatch, which is assumed to always
+match.  It's undefined whether identifier syntax (see
+`c-identifier-syntax-table') is in effect or not.  This regexp is
+assumed to be a superset of `c-label-prefix-re' if
+`c-recognize-colon-labels' is set.
+
+Besides this, `c-decl-start-kwds' is used to find declarations.
+
+Note: This variable together with `c-decl-start-re' and
+`c-decl-start-kwds' is only used to detect \"likely\"
+declaration/cast/label starts.  I.e. they might produce more matches
+but should not miss anything (or else it's necessary to use text
+properties - see the next note).  Wherever they match, the following
+construct is analyzed to see if it indeed is a declaration, cast or
+label.  That analysis is not cheap, so it's important that not too
+many false matches are triggered.
+
+Note: If a declaration/cast/label start can't be detected with this
+variable, it's necessary to use the `c-type' text property with the
+value `c-decl-end' on the last char of the last token preceding the
+declaration.  See the comment blurb at the start of cc-engine.el for
+more info."
+
   ;; We match a sequence of characters to skip over things like \"};\"
   ;; more quickly.  We match ")" in C for K&R region declarations, and
   ;; in all languages except Java for when a cpp macro definition
@@ -1937,12 +2311,7 @@ is in effect or not."
   ;; Match "<" in C++ to get the first argument in a template arglist.
   ;; In that case there's an additional check in `c-find-decl-spots'
   ;; that it got open paren syntax.
-  ;;
-  ;; Also match a single ":" for protection labels.  We cheat a little
-  ;; and require a symbol immediately before to avoid false matches
-  ;; when starting directly on a single ":", which can be the start of
-  ;; the base class initializer list in a constructor.
-  c++ "\\([\{\}\(\);,<]+\\|\\(\\w\\|\\s_\\):\\)\\([^:]\\|\\'\\)"
+  c++ "\\([\{\}\(\);,<]+\\)"
   ;; Additionally match the protection directives in Objective-C.
   ;; Note that this doesn't cope with the longer directives, which we
   ;; would have to match from start to end since they don't end with
@@ -1950,37 +2319,135 @@ is in effect or not."
   objc (concat "\\([\{\}\(\);,]+\\|"
               (c-make-keywords-re nil (c-lang-const c-protection-kwds))
               "\\)")
-  ;; Match ":" for switch labels inside union declarations in IDL.
-  idl "\\([\{\}\(\);:,]+\\)\\([^:]\\|\\'\\)"
   ;; Pike is like C but we also match "[" for multiple value
   ;; assignments and type casts.
   pike "\\([\{\}\(\)\[;,]+\\)")
 (c-lang-defvar c-decl-prefix-re (c-lang-const c-decl-prefix-re)
   'dont-doc)
 
+(c-lang-defconst c-decl-start-re
+  "Regexp matching the start of any declaration, cast or label.
+It's used on the token after the one `c-decl-prefix-re' matched.  This
+regexp should not try to match those constructs accurately as it's
+only used as a sieve to avoid spending more time checking other
+constructs."
+  t (c-lang-const c-identifier-start))
+(c-lang-defvar c-decl-start-re (c-lang-const c-decl-start-re))
+
+(c-lang-defconst c-decl-prefix-or-start-re
+  ;; Regexp matching something that might precede or start a
+  ;; declaration, cast or label.
+  ;;
+  ;; If the first submatch matches, it's taken to match the end of a
+  ;; token that might precede such a construct, e.g. ';', '}' or '{'.
+  ;; It's built from `c-decl-prefix-re'.
+  ;;
+  ;; If the first submatch did not match, the match of the whole
+  ;; regexp is taken to be at the first token in the declaration.
+  ;; `c-decl-start-re' is not checked in this case.
+  ;;
+  ;; Design note: The reason the same regexp is used to match both
+  ;; tokens that precede declarations and start them is to avoid an
+  ;; extra regexp search from the previous declaration spot in
+  ;; `c-find-decl-spots'.  Users of `c-find-decl-spots' also count on
+  ;; that it finds all declaration/cast/label starts in approximately
+  ;; linear order, so we can't do the searches in two separate passes.
+  t (if (c-lang-const c-decl-start-kwds)
+       (concat (c-lang-const c-decl-prefix-re)
+               "\\|"
+               (c-make-keywords-re t (c-lang-const c-decl-start-kwds)))
+      (c-lang-const c-decl-prefix-re)))
+(c-lang-defvar c-decl-prefix-or-start-re
+  (c-lang-const c-decl-prefix-or-start-re)
+  'dont-doc)
+
 (c-lang-defconst c-cast-parens
   ;; List containing the paren characters that can open a cast, or nil in
   ;; languages without casts.
-  t (c-with-syntax-table (c-lang-const c-mode-syntax-table)
-      (mapcan (lambda (opclass)
-               (when (eq (car opclass) 'prefix)
-                 (mapcan (lambda (op)
-                           (when (string-match "\\`\\s\(\\'" op)
-                             (list (elt op 0))))
-                         (cdr opclass))))
-             (c-lang-const c-operators))))
+  t (c-filter-ops (c-lang-const c-operators)
+                 '(prefix)
+                 "\\`\\s\(\\'"
+                 (lambda (op) (elt op 0))))
 (c-lang-defvar c-cast-parens (c-lang-const c-cast-parens))
 
+(c-lang-defconst c-block-prefix-disallowed-chars
+  "List of syntactically relevant characters that never can occur before
+the open brace in any construct that contains a brace block, e.g. in
+the \"class Foo: public Bar\" part of:
+
+    class Foo: public Bar {int x();} a, *b;
+
+If parens can occur, the chars inside those aren't filtered with this
+list.
+
+'<' and '>' should be disallowed even if angle bracket arglists can
+occur.  That since the search function needs to stop at them anyway to
+ensure they are given paren syntax.
+
+This is used to skip backward from the open brace to find the region
+in which to look for a construct like \"class\", \"enum\",
+\"namespace\" or whatever.  That skipping should be as tight as
+possible for good performance."
+
+  ;; Default to all chars that only occurs in nonsymbol tokens outside
+  ;; identifiers.
+  t (set-difference
+     (c-lang-const c-nonsymbol-token-char-list)
+     (c-filter-ops (append (c-lang-const c-identifier-ops)
+                          (list (cons nil
+                                      (c-lang-const c-after-id-concat-ops))))
+                  t
+                  t
+                  (lambda (op)
+                    (let ((pos 0) res)
+                      (while (string-match "\\(\\s.\\|\\s(\\|\\s)\\)"
+                                           op pos)
+                        (setq res (cons (aref op (match-beginning 1)) res)
+                              pos (match-end 0)))
+                      res))))
+
+  ;; Allow cpp operatios (where applicable).
+  t (if (c-lang-const c-opt-cpp-prefix)
+       (set-difference (c-lang-const c-block-prefix-disallowed-chars)
+                       '(?#))
+      (c-lang-const c-block-prefix-disallowed-chars))
+
+  ;; Allow ':' for inherit list starters.
+  (c++ objc idl) (set-difference (c-lang-const c-block-prefix-disallowed-chars)
+                                '(?:))
+
+  ;; Allow ',' for multiple inherits.
+  (c++ java) (set-difference (c-lang-const c-block-prefix-disallowed-chars)
+                            '(?,))
+
+  ;; Allow parentheses for anonymous inner classes in Java and class
+  ;; initializer lists in Pike.
+  (java pike) (set-difference (c-lang-const c-block-prefix-disallowed-chars)
+                             '(?\( ?\)))
+
+  ;; Allow '"' for extern clauses (e.g. extern "C" {...}).
+  (c c++ objc) (set-difference (c-lang-const c-block-prefix-disallowed-chars)
+                              '(?\" ?')))
+
+(c-lang-defconst c-block-prefix-charset
+  ;; `c-block-prefix-disallowed-chars' as an inverted charset suitable
+  ;; for `c-syntactic-skip-backward'.
+  t (c-make-bare-char-alt (c-lang-const c-block-prefix-disallowed-chars) t))
+(c-lang-defvar c-block-prefix-charset (c-lang-const c-block-prefix-charset))
+
 (c-lang-defconst c-type-decl-prefix-key
-  "Regexp matching the operators that might precede the identifier in a
-declaration, e.g. the \"*\" in \"char *argv\".  This regexp should
-match \"(\" if parentheses are valid in type declarations.  The end of
-the first submatch is taken as the end of the operator.  Identifier
-syntax is in effect when this is matched (see `c-identifier-syntax-table')."
+  "Regexp matching the declarator operators that might precede the
+identifier in a declaration, e.g. the \"*\" in \"char *argv\".  This
+regexp should match \"(\" if parentheses are valid in declarators.
+The end of the first submatch is taken as the end of the operator.
+Identifier syntax is in effect when this is matched \(see
+`c-identifier-syntax-table')."
   t (if (c-lang-const c-type-modifier-kwds)
-       (concat (c-regexp-opt (c-lang-const c-type-modifier-kwds) t) "\\>")
+       (concat (regexp-opt (c-lang-const c-type-modifier-kwds) t) "\\>")
       ;; Default to a regexp that never matches.
       "\\<\\>")
+  ;; Check that there's no "=" afterwards to avoid matching tokens
+  ;; like "*=".
   (c objc) (concat "\\("
                   "[*\(]"
                   "\\|"
@@ -2001,14 +2468,14 @@ syntax is in effect when this is matched (see `c-identifier-syntax-table')."
               (c-lang-const c-type-decl-prefix-key)
               "\\)"
               "\\([^=]\\|$\\)")
-  pike "\\([*\(!~]\\)\\([^=]\\|$\\)")
+  pike "\\(\\*\\)\\([^=]\\|$\\)")
 (c-lang-defvar c-type-decl-prefix-key (c-lang-const c-type-decl-prefix-key)
   'dont-doc)
 
 (c-lang-defconst c-type-decl-suffix-key
-  "Regexp matching the operators that might follow after the identifier
-in a declaration, e.g. the \"[\" in \"char argv[]\".  This regexp
-should match \")\" if parentheses are valid in type declarations.  If
+  "Regexp matching the declarator operators that might follow after the
+identifier in a declaration, e.g. the \"[\" in \"char argv[]\".  This
+regexp should match \")\" if parentheses are valid in declarators.  If
 it matches an open paren of some kind, the type declaration check
 continues at the corresponding close paren, otherwise the end of the
 first submatch is taken as the end of the operator.  Identifier syntax
@@ -2017,24 +2484,28 @@ is in effect when this is matched (see `c-identifier-syntax-table')."
   ;; function argument list parenthesis.
   t    (if (c-lang-const c-type-modifier-kwds)
           (concat "\\(\(\\|"
-                  (c-regexp-opt (c-lang-const c-type-modifier-kwds) t) "\\>"
+                  (regexp-opt (c-lang-const c-type-modifier-kwds) t) "\\>"
                   "\\)")
         "\\(\(\\)")
   (c c++ objc) (concat
                "\\("
                "[\)\[\(]"
-               "\\|"
-               ;; "throw" in `c-type-modifier-kwds' is followed by a
-               ;; parenthesis list, but no extra measures are
-               ;; necessary to handle that.
-               (c-regexp-opt (c-lang-const c-type-modifier-kwds) t) "\\>"
+               (if (c-lang-const c-type-modifier-kwds)
+                   (concat
+                    "\\|"
+                    ;; "throw" in `c-type-modifier-kwds' is followed
+                    ;; by a parenthesis list, but no extra measures
+                    ;; are necessary to handle that.
+                    (regexp-opt (c-lang-const c-type-modifier-kwds) t)
+                    "\\>")
+                 "")
                "\\)")
   (java idl) "\\([\[\(]\\)")
 (c-lang-defvar c-type-decl-suffix-key (c-lang-const c-type-decl-suffix-key)
   'dont-doc)
 
 (c-lang-defconst c-after-suffixed-type-decl-key
-  "This regexp is matched after a type declaration expression where
+  "This regexp is matched after a declarator expression where
 `c-type-decl-suffix-key' has matched.  If it matches then the
 construct is taken as a declaration.  It's typically used to match the
 beginning of a function body or whatever might occur after the
@@ -2052,11 +2523,11 @@ not \",\" or \";\"."
   ;; could however produce false matches on code like "FOO(bar) x"
   ;; where FOO is a cpp macro, so it's better to leave it out and rely
   ;; on the other heuristics in that case.
-  t (if (c-lang-const c-postfix-decl-spec-kwds)
-       ;; Add on the keywords in `c-postfix-decl-spec-kwds'.
+  t (if (c-lang-const c-postfix-spec-kwds)
+       ;; Add on the keywords in `c-postfix-spec-kwds'.
        (concat (c-lang-const c-after-suffixed-type-decl-key)
                "\\|"
-               (c-make-keywords-re t (c-lang-const c-postfix-decl-spec-kwds)))
+               (c-make-keywords-re t (c-lang-const c-postfix-spec-kwds)))
       (c-lang-const c-after-suffixed-type-decl-key))
   ;; Also match the colon that starts a base class initializer list in
   ;; C++.  That can be confused with a function call before the colon
@@ -2096,7 +2567,7 @@ It's undefined whether identifier syntax (see `c-identifier-syntax-table')
 is in effect or not."
   t nil
   (c c++ objc pike) "\\(\\.\\.\\.\\)"
-  java "\\(\\[[ \t\n\r\f\v]*\\]\\)")
+  java (concat "\\(\\[" (c-lang-const c-simple-ws) "*\\]\\)"))
 (c-lang-defvar c-opt-type-suffix-key (c-lang-const c-opt-type-suffix-key))
 
 (c-lang-defvar c-known-type-key
@@ -2105,13 +2576,26 @@ is in effect or not."
   ;; submatch is the one that matches the type.  Note that this regexp
   ;; assumes that symbol constituents like '_' and '$' have word
   ;; syntax.
-  (let ((extra-types (when (boundp (c-mode-symbol "font-lock-extra-types"))
-                       (c-mode-var "font-lock-extra-types"))))
+  (let* ((extra-types
+         (when (boundp (c-mode-symbol "font-lock-extra-types"))
+           (c-mode-var "font-lock-extra-types")))
+        (regexp-strings
+         (mapcan (lambda (re)
+                   (when (string-match "[][.*+?^$\\]" re)
+                     (list re)))
+                 extra-types))
+        (plain-strings
+         (mapcan (lambda (re)
+                   (unless (string-match "[][.*+?^$\\]" re)
+                     (list re)))
+                 extra-types)))
     (concat "\\<\\("
-           (c-make-keywords-re nil (c-lang-const c-primitive-type-kwds))
-           (if (consp extra-types)
-               (concat "\\|" (mapconcat 'identity extra-types "\\|"))
-             "")
+           (c-concat-separated
+            (append (list (c-make-keywords-re nil
+                            (append (c-lang-const c-primitive-type-kwds)
+                                    plain-strings)))
+                    regexp-strings)
+            "\\|")
            "\\)\\>")))
 
 (c-lang-defconst c-special-brace-lists
@@ -2163,6 +2647,14 @@ Foo bar = gnu;"
   c++ t)
 (c-lang-defvar c-recognize-paren-inits (c-lang-const c-recognize-paren-inits))
 
+(c-lang-defconst c-recognize-paren-inexpr-blocks
+  "Non-nil to recognize gcc style in-expression blocks,
+i.e. compound statements surrounded by parentheses inside expressions."
+  t nil
+  (c c++) t)
+(c-lang-defvar c-recognize-paren-inexpr-blocks
+  (c-lang-const c-recognize-paren-inexpr-blocks))
+
 (c-lang-defconst c-opt-<>-arglist-start
   ;; Regexp matching the start of angle bracket arglists in languages
   ;; where `c-recognize-<>-arglists' is set.  Does not exclude
@@ -2188,52 +2680,117 @@ Foo bar = gnu;"
 (c-lang-defvar c-opt-<>-arglist-start-in-paren
   (c-lang-const c-opt-<>-arglist-start-in-paren))
 
-(c-lang-defconst c-label-key
-  "Regexp matching a normal label, i.e. a label that doesn't begin with
-a keyword like switch labels.  It's only used at the beginning of a
-statement."
-  t "\\<\\>"
-  (c c++ objc java pike) (concat "\\(" (c-lang-const c-symbol-key) "\\)"
-                                "[ \t\n\r\f\v]*:\\([^:]\\|$\\)"))
-(c-lang-defvar c-label-key (c-lang-const c-label-key)
-  'dont-doc)
-
 (c-lang-defconst c-opt-postfix-decl-spec-key
   ;; Regexp matching the beginning of a declaration specifier in the
   ;; region between the header and the body of a declaration.
   ;;
   ;; TODO: This is currently not used uniformly; c++-mode and
   ;; java-mode each have their own ways of using it.
-  t nil
-  c++ (concat ":?[ \t\n\r\f\v]*\\(virtual[ \t\n\r\f\v]+\\)?\\("
-             (c-make-keywords-re nil (c-lang-const c-protection-kwds))
-             "\\)[ \t\n\r\f\v]+"
-             "\\(" (c-lang-const c-symbol-key) "\\)")
-  java (c-make-keywords-re t (c-lang-const c-postfix-decl-spec-kwds)))
+  t    nil
+  c++  (concat ":?"
+              (c-lang-const c-simple-ws) "*"
+              "\\(virtual" (c-lang-const c-simple-ws) "+\\)?\\("
+              (c-make-keywords-re nil (c-lang-const c-protection-kwds))
+              "\\)" (c-lang-const c-simple-ws) "+"
+              "\\(" (c-lang-const c-symbol-key) "\\)")
+  java (c-make-keywords-re t (c-lang-const c-postfix-spec-kwds)))
 (c-lang-defvar c-opt-postfix-decl-spec-key
   (c-lang-const c-opt-postfix-decl-spec-key))
 
+(c-lang-defconst c-recognize-colon-labels
+  "Non-nil if generic labels ending with \":\" should be recognized.
+That includes labels in code and access keys in classes.  This does
+not apply to labels recognized by `c-label-kwds' and
+`c-opt-extra-label-key'."
+  t nil
+  (c c++ objc java pike) t)
+(c-lang-defvar c-recognize-colon-labels
+  (c-lang-const c-recognize-colon-labels))
+
+(c-lang-defconst c-label-prefix-re
+  "Regexp like `c-decl-prefix-re' that matches any token that can precede
+a generic colon label.  Not used if `c-recognize-colon-labels' is
+nil."
+  t "\\([{};]+\\)")
+(c-lang-defvar c-label-prefix-re
+  (c-lang-const c-label-prefix-re))
+
+(c-lang-defconst c-nonlabel-token-key
+  "Regexp matching things that can't occur in generic colon labels,
+neither in a statement nor in a declaration context.  The regexp is
+tested at the beginning of every sexp in a suspected label,
+i.e. before \":\".  Only used if `c-recognize-colon-labels' is set."
+  t (concat
+     ;; Don't allow string literals.
+     "[\"']\\|"
+     ;; All keywords except `c-label-kwds' and `c-protection-kwds'.
+     (c-make-keywords-re t
+       (set-difference (c-lang-const c-keywords)
+                      (append (c-lang-const c-label-kwds)
+                              (c-lang-const c-protection-kwds))
+                      :test 'string-equal)))
+  ;; Also check for open parens in C++, to catch member init lists in
+  ;; constructors.  We normally allow it so that macros with arguments
+  ;; work in labels.
+  c++ (concat "\\s\(\\|" (c-lang-const c-nonlabel-token-key)))
+(c-lang-defvar c-nonlabel-token-key (c-lang-const c-nonlabel-token-key))
+
+(c-lang-defconst c-opt-extra-label-key
+  "Optional regexp matching labels.
+Normally, labels are detected according to `c-nonlabel-token-key',
+`c-decl-prefix-re' and `c-nonlabel-decl-prefix-re'.  This regexp can
+be used if there are additional labels that aren't recognized that
+way."
+  t    nil
+  objc (c-make-keywords-re t (c-lang-const c-protection-kwds)))
+(c-lang-defvar c-opt-extra-label-key (c-lang-const c-opt-extra-label-key))
+
 (c-lang-defconst c-opt-friend-key
   ;; Regexp describing friend declarations classes, or nil in
   ;; languages that don't have such things.
   ;;
-  ;; TODO: Ought to use `c-specifier-key' or similar, and the template
-  ;; skipping isn't done properly.  This will disappear soon.
-  t nil
-  c++ "friend[ \t]+\\|template[ \t]*<.+>[ \t]*friend[ \t]+")
+  ;; TODO: Ought to use `c-prefix-spec-kwds-re' or similar, and the
+  ;; template skipping isn't done properly.  This will disappear soon.
+  t    nil
+  c++  (concat "friend" (c-lang-const c-simple-ws) "+"
+              "\\|"
+              (concat "template"
+                      (c-lang-const c-simple-ws) "*"
+                      "<.+>"
+                      (c-lang-const c-simple-ws) "*"
+                      "friend"
+                      (c-lang-const c-simple-ws) "+")))
 (c-lang-defvar c-opt-friend-key (c-lang-const c-opt-friend-key))
 
 (c-lang-defconst c-opt-method-key
   ;; Special regexp to match the start of Objective-C methods.  The
   ;; first submatch is assumed to end after the + or - key.
-  t nil
+  t    nil
   objc (concat
        ;; TODO: Ought to use a better method than anchoring on bol.
-       "^[ \t]*\\([+-]\\)[ \t\n\r\f\v]*"
-       "\\(([^)]*)[ \t\n\r\f\v]*\\)?"  ; return type
+       "^\\s *"
+       "\\([+-]\\)"
+       (c-lang-const c-simple-ws) "*"
+       (concat "\\("                   ; Return type.
+               "([^\)]*)"
+               (c-lang-const c-simple-ws) "*"
+               "\\)?")
        "\\(" (c-lang-const c-symbol-key) "\\)"))
 (c-lang-defvar c-opt-method-key (c-lang-const c-opt-method-key))
 
+(c-lang-defconst c-type-decl-end-used
+  ;; Must be set in buffers where the `c-type' text property might be
+  ;; used with the value `c-decl-end'.
+  ;;
+  ;; `c-decl-end' is used to mark the ends of labels and access keys
+  ;; to make interactive refontification work better.
+  t (or (c-lang-const c-recognize-colon-labels)
+       (and (c-lang-const c-label-kwds) t))
+  ;; `c-decl-end' is used to mark the end of the @-style directives in
+  ;; Objective-C.
+  objc t)
+(c-lang-defvar c-type-decl-end-used (c-lang-const c-type-decl-end-used))
+
 \f
 ;;; Wrap up the `c-lang-defvar' system.
 
@@ -2249,9 +2806,7 @@ for the given mode.
 This function should be evaluated at compile time, so that the
 function it returns is byte compiled with all the evaluated results
 from the language constants.  Use the `c-init-language-vars' macro to
-accomplish that conveniently.
-
-This function does not do any hidden buffer changes."
+accomplish that conveniently."
 
   (if (and (not load-in-progress)
           (boundp 'byte-compile-dest-file)
@@ -2282,12 +2837,14 @@ This function does not do any hidden buffer changes."
                                                (elt init 1))))
                              (cdr c-lang-variable-inits))))
 
-                (unless (get ',mode 'c-has-warned-lang-consts)
-                  (message ,(concat "%s compiled with CC Mode %s "
-                                    "but loaded with %s - evaluating "
-                                    "language constants from source")
-                           ',mode ,c-version c-version)
-                  (put ',mode 'c-has-warned-lang-consts t))
+                ;; This diagnostic message isn't useful for end
+                ;; users, so it's disabled.
+                ;;(unless (get ',mode 'c-has-warned-lang-consts)
+                ;;  (message ,(concat "%s compiled with CC Mode %s "
+                ;;                    "but loaded with %s - evaluating "
+                ;;                    "language constants from source")
+                ;;           ',mode ,c-version c-version)
+                ;;  (put ',mode 'c-has-warned-lang-consts t))
 
                 (require 'cc-langs)
                 (let ((init (cdr c-lang-variable-inits)))
@@ -2328,9 +2885,7 @@ This function does not do any hidden buffer changes."
   "Initialize all the language dependent variables for the given mode.
 This macro is expanded at compile time to a form tailored for the mode
 in question, so MODE must be a constant.  Therefore MODE is not
-evaluated and should not be quoted.
-
-This macro does not do any hidden buffer changes."
+evaluated and should not be quoted."
   `(funcall ,(c-make-init-lang-vars-fun mode)))
 
 \f
index 6de4aa8c79c2a2027498172873ca091b1b3597b3..e11f50c581b62c79ef30d571f12c11583fd91fae 100644 (file)
@@ -1,6 +1,7 @@
 ;;; cc-menus.el --- imenu support for CC Mode
 
-;; Copyright (C) 1985,1987,1992-2003, 2004, 2005 Free Software Foundation, Inc.
+;; Copyright (C) 1985,1987,1992-2003, 2004, 2005 Free Software Foundation,
+;; Inc.
 
 ;; Authors:    1998- Martin Stjernholm
 ;;             1992-1999 Barry A. Warsaw
@@ -24,7 +25,7 @@
 ;; GNU General Public License for more details.
 
 ;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING.  If not, write to
+;; along with this program; see the file COPYING.  If not, write to
 ;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 ;; Boston, MA 02110-1301, USA.
 
@@ -240,7 +241,6 @@ Example:
 - perform: (SEL)aSelector withObject: object1 withObject: object2; /* METHOD */
 =>
 -perform:withObject:withObject:withObject: /* selector */"
-  ;; This function does not do any hidden buffer changes.
   (let ((return "")                    ; String to be returned
        (p 0)                           ; Current scanning position in METHOD  
        (pmax (length method))          ; 
@@ -281,7 +281,6 @@ Example:
 
 (defun cc-imenu-objc-remove-white-space  (str)
   "Remove all spaces and tabs from STR."
-  ;; This function does not do any hidden buffer changes.
   (let ((return "")
        (p 0)
        (max (length str)) 
@@ -296,7 +295,6 @@ Example:
 
 (defun cc-imenu-objc-function ()
   "imenu supports for objc-mode."
-  ;; This function does not do any hidden buffer changes.
   (let (methodlist
        clist
        ;;
@@ -415,7 +413,6 @@ Example:
 
 (defun cc-imenu-init (mode-generic-expression
                      &optional mode-create-index-function)
-  ;; This function does not do any hidden buffer changes.
   (setq imenu-generic-expression mode-generic-expression
        imenu-case-fold-search nil)
   (when mode-create-index-function
index 63c6aad3aa188e9cdd76849dd330f188696d7b85..247a4021abfe2a8b013a6d00e82f3529de2a9600 100644 (file)
@@ -1,6 +1,7 @@
 ;;; cc-mode.el --- major mode for editing C and similar languages
 
-;; Copyright (C) 1985,1987,1992-2003, 2004, 2005 Free Software Foundation, Inc.
+;; Copyright (C) 1985,1987,1992-2003, 2004, 2005 Free Software Foundation,
+;; Inc.
 
 ;; Authors:    2003- Alan Mackenzie
 ;;             1998- Martin Stjernholm
 (cc-require 'cc-menus)
 
 ;; Silence the compiler.
-(cc-bytecomp-defvar comment-line-break-function) ; (X)Emacs 20+
-(cc-bytecomp-defvar adaptive-fill-first-line-regexp) ; Emacs 20+
+(cc-bytecomp-defvar adaptive-fill-first-line-regexp) ; Emacs
 (cc-bytecomp-defun set-keymap-parents) ; XEmacs
-(cc-bytecomp-defun run-mode-hooks)     ; Emacs 21.1+
+(cc-bytecomp-defun run-mode-hooks)     ; Emacs 21.1
 (cc-bytecomp-obsolete-fun make-local-hook) ; Marked obsolete in Emacs 21.1.
 
 ;; We set these variables during mode init, yet we don't require
 ;; with your version of Emacs, you are incompatible!
 (cc-external-require 'easymenu)
 
+;; Autoload directive for emacsen that doesn't have an older CC Mode
+;; version in the dist.
+(autoload 'c-subword-mode "cc-subword"
+  "Mode enabling subword movement and editing keys." t)
+
 ;; Load cc-fonts first after font-lock is loaded, since it isn't
 ;; necessary until font locking is requested.
 (eval-after-load "font-lock"
@@ -153,7 +158,6 @@ directly supported by CC Mode.  This can be used instead of the
 `c-init-language-vars' macro if the language you want to use is one of
 those, rather than a derived language defined through the language
 variable system (see \"cc-langs.el\")."
-  ;; This function does not do any hidden buffer changes.
   (cond ((eq mode 'c-mode)    (c-init-language-vars c-mode))
        ((eq mode 'c++-mode)  (c-init-language-vars c++-mode))
        ((eq mode 'objc-mode) (c-init-language-vars objc-mode))
@@ -171,8 +175,6 @@ initialization to run CC Mode for the C language is done.  Otherwise
 only some basic setup is done, and a call to `c-init-language-vars' or
 `c-init-language-vars-for' is necessary too (which gives more
 control).  See \"cc-mode.el\" for more info."
-  ;;
-  ;; This function does not do any hidden buffer changes.
 
   (setq c-buffer-is-cc-mode t)
 
@@ -220,7 +222,7 @@ control).  See \"cc-mode.el\" for more info."
 (defun c-define-abbrev-table (name defs)
   ;; Compatibility wrapper for `define-abbrev' which passes a non-nil
   ;; sixth argument for SYSTEM-FLAG in emacsen that support it
-  ;; (currently only Emacs 21.2).
+  ;; (currently only Emacs >= 21.2).
   (let ((table (or (symbol-value name)
                   (progn (define-abbrev-table name nil)
                          (symbol-value name)))))
@@ -232,20 +234,25 @@ control).  See \"cc-mode.el\" for more info."
       (setq defs (cdr defs)))))
 (put 'c-define-abbrev-table 'lisp-indent-function 1)
 
+(defun c-bind-special-erase-keys ()
+  ;; Only used in Emacs to bind C-c C-<delete> and C-c C-<backspace>
+  ;; to the proper keys depending on `normal-erase-is-backspace'.
+  (if normal-erase-is-backspace
+      (progn
+       (define-key c-mode-base-map (kbd "C-c C-<delete>")
+         'c-hungry-delete-forward)
+       (define-key c-mode-base-map (kbd "C-c C-<backspace>")
+         'c-hungry-backspace))
+    (define-key c-mode-base-map (kbd "C-c C-<delete>")
+      'c-hungry-backspace)
+    (define-key c-mode-base-map (kbd "C-c C-<backspace>")
+      'c-hungry-delete-forward)))
+
 (if c-mode-base-map
     nil
-  ;; TBD: should we even worry about naming this keymap. My vote: no,
-  ;; because Emacs and XEmacs do it differently.
+
   (setq c-mode-base-map (make-sparse-keymap))
-  ;; put standard keybindings into MAP
-  ;; the following mappings correspond more or less directly to BOCM
-  (define-key c-mode-base-map "{"         'c-electric-brace)
-  (define-key c-mode-base-map "}"         'c-electric-brace)
-  (define-key c-mode-base-map ";"         'c-electric-semi&comma)
-  (define-key c-mode-base-map "#"         'c-electric-pound)
-  (define-key c-mode-base-map ":"         'c-electric-colon)
-  (define-key c-mode-base-map "("         'c-electric-paren)
-  (define-key c-mode-base-map ")"         'c-electric-paren)
+
   ;; Separate M-BS from C-M-h.  The former should remain
   ;; backward-kill-word.
   (define-key c-mode-base-map [(control meta h)] 'c-mark-function)
@@ -259,21 +266,23 @@ control).  See \"cc-mode.el\" for more info."
   (substitute-key-definition 'indent-new-comment-line
                             'c-indent-new-comment-line
                             c-mode-base-map global-map)
+  (substitute-key-definition 'indent-for-tab-command
+                            'c-indent-command
+                            c-mode-base-map global-map)
   (when (fboundp 'comment-indent-new-line)
     ;; indent-new-comment-line has changed name to
     ;; comment-indent-new-line in Emacs 21.
     (substitute-key-definition 'comment-indent-new-line
                               'c-indent-new-comment-line
                               c-mode-base-map global-map))
+
   ;; RMS says don't make these the default.
 ;;  (define-key c-mode-base-map "\e\C-a"    'c-beginning-of-defun)
 ;;  (define-key c-mode-base-map "\e\C-e"    'c-end-of-defun)
+
   (define-key c-mode-base-map "\C-c\C-n"  'c-forward-conditional)
   (define-key c-mode-base-map "\C-c\C-p"  'c-backward-conditional)
   (define-key c-mode-base-map "\C-c\C-u"  'c-up-conditional)
-  (substitute-key-definition 'indent-for-tab-command
-                            'c-indent-command
-                            c-mode-base-map global-map)
 
   ;; It doesn't suffice to put `c-fill-paragraph' on
   ;; `fill-paragraph-function' since `c-fill-paragraph' must be called
@@ -290,34 +299,74 @@ control).  See \"cc-mode.el\" for more info."
   (substitute-key-definition 'fill-paragraph-or-region 'c-fill-paragraph
                             c-mode-base-map global-map)
 
+  ;; We bind the forward deletion key and (implicitly) C-d to
+  ;; `c-electric-delete-forward', and the backward deletion key to
+  ;; `c-electric-backspace'.  The hungry variants are bound to the
+  ;; same keys but prefixed with C-c.  This implies that C-c C-d is
+  ;; `c-hungry-delete-forward'.  For consistency, we bind not only C-c
+  ;; <backspace> to `c-hungry-backspace' but also C-c C-<backspace>,
+  ;; so that the Ctrl key can be held down during the whole sequence
+  ;; regardless of the direction.  This in turn implies that we bind
+  ;; C-c C-<delete> to `c-hungry-delete-forward', for the same reason.
+
   ;; Bind the electric deletion functions to C-d and DEL.  Emacs 21
   ;; automatically maps the [delete] and [backspace] keys to these two
   ;; depending on window system and user preferences.  (In earlier
   ;; versions it's possible to do the same by using `function-key-map'.)
   (define-key c-mode-base-map "\C-d" 'c-electric-delete-forward)
   (define-key c-mode-base-map "\177" 'c-electric-backspace)
-  (when (boundp 'delete-key-deletes-forward)
-    ;; In XEmacs 20 and later we fix the forward and backward deletion
-    ;; behavior by binding the keysyms for the [delete] and
-    ;; [backspace] keys directly, and use `delete-forward-p' or
-    ;; `delete-key-deletes-forward' to decide what [delete] should do.
+  (define-key c-mode-base-map "\C-c\C-d"     'c-hungry-delete-forward)
+  (define-key c-mode-base-map [?\C-c ?\d]    'c-hungry-backspace)
+  (define-key c-mode-base-map [?\C-c ?\C-\d] 'c-hungry-backspace)
+  (define-key c-mode-base-map [?\C-c deletechar] 'c-hungry-delete-forward) ; C-c <delete> on a tty.
+  (define-key c-mode-base-map [?\C-c (control deletechar)] ; C-c C-<delete> on a tty.
+    'c-hungry-delete-forward)
+  (when (boundp 'normal-erase-is-backspace)
+    ;; The automatic C-d and DEL mapping functionality doesn't extend
+    ;; to special combinations like C-c C-<delete>, so we have to hook
+    ;; into the `normal-erase-is-backspace' system to bind it directly
+    ;; as appropriate.
+    (add-hook 'normal-erase-is-backspace-hook 'c-bind-special-erase-keys)
+    (c-bind-special-erase-keys))
+
+  (when (fboundp 'delete-forward-p)
+    ;; In XEmacs we fix the forward and backward deletion behavior by
+    ;; binding the keysyms for the [delete] and [backspace] keys
+    ;; directly, and use `delete-forward-p' to decide what [delete]
+    ;; should do.  That's done in the XEmacs specific
+    ;; `c-electric-delete' and `c-hungry-delete' functions.
     (define-key c-mode-base-map [delete]    'c-electric-delete)
-    (define-key c-mode-base-map [backspace] 'c-electric-backspace))
-  (define-key c-mode-base-map ","         'c-electric-semi&comma)
-  (define-key c-mode-base-map "*"         'c-electric-star)
+    (define-key c-mode-base-map [backspace] 'c-electric-backspace)
+    (define-key c-mode-base-map (kbd "C-c <delete>") 'c-hungry-delete)
+    (define-key c-mode-base-map (kbd "C-c C-<delete>") 'c-hungry-delete)
+    (define-key c-mode-base-map (kbd "C-c <backspace>") 'c-hungry-backspace)
+    (define-key c-mode-base-map (kbd "C-c C-<backspace>") 'c-hungry-backspace))
+
+  (define-key c-mode-base-map "#"         'c-electric-pound)
+  (define-key c-mode-base-map "{"         'c-electric-brace)
+  (define-key c-mode-base-map "}"         'c-electric-brace)
   (define-key c-mode-base-map "/"         'c-electric-slash)
-  (define-key c-mode-base-map "\C-c\C-q"  'c-indent-defun)
+  (define-key c-mode-base-map "*"         'c-electric-star)
+  (define-key c-mode-base-map ";"         'c-electric-semi&comma)
+  (define-key c-mode-base-map ","         'c-electric-semi&comma)
+  (define-key c-mode-base-map ":"         'c-electric-colon)
+  (define-key c-mode-base-map "("         'c-electric-paren)
+  (define-key c-mode-base-map ")"         'c-electric-paren)
+
   (define-key c-mode-base-map "\C-c\C-\\" 'c-backslash-region)
-  (define-key c-mode-base-map "\C-c\C-a"  'c-toggle-auto-state)
+  (define-key c-mode-base-map "\C-c\C-a"  'c-toggle-auto-newline)
   (define-key c-mode-base-map "\C-c\C-b"  'c-submit-bug-report)
   (define-key c-mode-base-map "\C-c\C-c"  'comment-region)
-  (define-key c-mode-base-map "\C-c\C-d"  'c-toggle-hungry-state)
+  (define-key c-mode-base-map "\C-c\C-l"  'c-toggle-electric-state)
   (define-key c-mode-base-map "\C-c\C-o"  'c-set-offset)
+  (define-key c-mode-base-map "\C-c\C-q"  'c-indent-defun)
   (define-key c-mode-base-map "\C-c\C-s"  'c-show-syntactic-information)
-  (define-key c-mode-base-map "\C-c\C-t"  'c-toggle-auto-hungry-state)
+  ;; (define-key c-mode-base-map "\C-c\C-t"  'c-toggle-auto-hungry-state)  Commented out by ACM, 2005-03-05.
   (define-key c-mode-base-map "\C-c."     'c-set-style)
   ;; conflicts with OOBR
   ;;(define-key c-mode-base-map "\C-c\C-v"  'c-version)
+  ;; (define-key c-mode-base-map "\C-c\C-y"  'c-toggle-hungry-state)  Commented out by ACM, 2005-11-22.
+  (define-key c-mode-base-map "\C-c\C-w" 'c-subword-mode)
   )
 
 ;; We don't require the outline package, but we configure it a bit anyway.
@@ -341,32 +390,47 @@ preferably use the `c-mode-menu' language constant directly."
     (let ((f (symbol-function 'c-populate-syntax-table)))
       (if (byte-code-function-p f) f (byte-compile f)))))
 
+;; CAUTION: Try to avoid installing things on
+;; `before-change-functions'.  The macro `combine-after-change-calls'
+;; is used and it doesn't work if there are things on that hook.  That
+;; can cause font lock functions to run in inconvenient places during
+;; temporary changes in some font lock support modes, causing extra
+;; unnecessary work and font lock glitches due to interactions between
+;; various text properties.
+
 (defun c-after-change (beg end len)
-  ;; Function put on `after-change-functions' to adjust various
-  ;; caches.  Prefer speed to finesse here, since there will be an
-  ;; order of magnitude more calls to this function than any of the
+  ;; Function put on `after-change-functions' to adjust various caches
+  ;; etc.  Prefer speed to finesse here, since there will be an order
+  ;; of magnitude more calls to this function than any of the
   ;; functions that use the caches.
   ;;
   ;; Note that care must be taken so that this is called before any
   ;; font-lock callbacks since we might get calls to functions using
   ;; these caches from inside them, and we must thus be sure that this
   ;; has already been executed.
-  ;;
-  ;; This function does not do any hidden buffer changes.
 
   (c-save-buffer-state ()
-    (when (> end (point-max))
-      ;; Some emacsen might return positions past the end. This has been
-      ;; observed in Emacs 20.7 when rereading a buffer changed on disk
-      ;; (haven't been able to minimize it, but Emacs 21.3 appears to
-      ;; work).
-      (setq end (point-max))
-      (when (> beg end)
-       (setq beg end)))
-
-    (c-invalidate-sws-region-after beg end)
-    (c-invalidate-state-cache beg)
-    (c-invalidate-find-decl-cache beg)))
+    ;; When `combine-after-change-calls' is used we might get calls
+    ;; with regions outside the current narrowing.  This has been
+    ;; observed in Emacs 20.7.
+    (save-restriction
+      (widen)
+
+      (when (> end (point-max))
+       ;; Some emacsen might return positions past the end. This has been
+       ;; observed in Emacs 20.7 when rereading a buffer changed on disk
+       ;; (haven't been able to minimize it, but Emacs 21.3 appears to
+       ;; work).
+       (setq end (point-max))
+       (when (> beg end)
+         (setq beg end)))
+
+      (c-invalidate-sws-region-after beg end)
+      (c-invalidate-state-cache beg)
+      (c-invalidate-find-decl-cache beg)
+
+      (when c-recognize-<>-arglists
+       (c-after-change-check-<>-operators beg end)))))
 
 (defun c-basic-common-init (mode default-style)
   "Do the necessary initialization for the syntax handling routines
@@ -380,8 +444,6 @@ same format as `c-default-style'.
 Note that `c-init-language-vars' must be called before this function.
 This function cannot do that since `c-init-language-vars' is a macro
 that requires a literal mode spec at compile time."
-  ;;
-  ;; This function does not do any hidden buffer changes.
 
   (setq c-buffer-is-cc-mode mode)
 
@@ -395,13 +457,20 @@ that requires a literal mode spec at compile time."
   (make-local-variable 'comment-end)
   (make-local-variable 'comment-start-skip)
   (make-local-variable 'comment-multi-line)
+  (make-local-variable 'comment-line-break-function)
+  (make-local-variable 'paragraph-start)
+  (make-local-variable 'paragraph-separate)
+  (make-local-variable 'paragraph-ignore-fill-prefix)
+  (make-local-variable 'adaptive-fill-mode)
+  (make-local-variable 'adaptive-fill-regexp)
 
   ;; now set their values
   (setq parse-sexp-ignore-comments t
        indent-line-function 'c-indent-line
        indent-region-function 'c-indent-region
        normal-auto-fill-function 'c-do-auto-fill
-       comment-multi-line t)
+       comment-multi-line t
+       comment-line-break-function 'c-indent-new-comment-line)
 
   ;; Install `c-fill-paragraph' on `fill-paragraph-function' so that a
   ;; direct call to `fill-paragraph' behaves better.  This still
@@ -409,21 +478,25 @@ that requires a literal mode spec at compile time."
   (make-local-variable 'fill-paragraph-function)
   (setq fill-paragraph-function 'c-fill-paragraph)
 
-  ;; (X)Emacs 20 and later.
-  (when (boundp 'comment-line-break-function)
-    (make-local-variable 'comment-line-break-function)
-    (setq comment-line-break-function
-         'c-indent-new-comment-line))
-
-  ;; Emacs 20 and later.
-  (when (boundp 'parse-sexp-lookup-properties)
-    (make-local-variable 'parse-sexp-lookup-properties)
-    (setq parse-sexp-lookup-properties t))
-
-  ;; Same as above for XEmacs 21 (although currently undocumented).
-  (when (boundp 'lookup-syntax-properties)
-    (make-local-variable 'lookup-syntax-properties)
-    (setq lookup-syntax-properties t))
+  (when (or c-recognize-<>-arglists
+           (c-major-mode-is 'awk-mode))
+    ;; We'll use the syntax-table text property to change the syntax
+    ;; of some chars for this language, so do the necessary setup for
+    ;; that.
+    ;;
+    ;; Note to other package developers: It's ok to turn this on in CC
+    ;; Mode buffers when CC Mode doesn't, but it's not ok to turn it
+    ;; off if CC Mode has turned it on.
+
+    ;; Emacs.
+    (when (boundp 'parse-sexp-lookup-properties)
+      (make-local-variable 'parse-sexp-lookup-properties)
+      (setq parse-sexp-lookup-properties t))
+
+    ;; Same as above for XEmacs.
+    (when (boundp 'lookup-syntax-properties)
+      (make-local-variable 'lookup-syntax-properties)
+      (setq lookup-syntax-properties t)))
 
   ;; Use this in Emacs 21 to avoid meddling with the rear-nonsticky
   ;; property on each character.
@@ -441,18 +514,12 @@ that requires a literal mode spec at compile time."
 
   ;; In Emacs 21 and later it's possible to turn off the ad-hoc
   ;; heuristic that open parens in column 0 are defun starters.  Since
-  ;; we have c-state-cache that isn't useful and only causes trouble
-  ;; so turn it off.
+  ;; we have c-state-cache, that heuristic isn't useful and only causes
+  ;; trouble, so turn it off.
   (when (memq 'col-0-paren c-emacs-features)
     (make-local-variable 'open-paren-in-column-0-is-defun-start)
     (setq open-paren-in-column-0-is-defun-start nil))
 
-  ;; The `c-type' text property with `c-decl-end' is used to mark the
-  ;; ends of access keys to make interactive refontification work
-  ;; better.
-  (when c-opt-access-key
-    (setq c-type-decl-end-used t))
-
   (c-clear-found-types)
 
   ;; now set the mode style based on default-style
@@ -483,14 +550,15 @@ that requires a literal mode spec at compile time."
   (make-local-variable 'comment-indent-function)
   (setq comment-indent-function 'c-comment-indent)
 
-  ;; put auto-hungry designators onto minor-mode-alist, but only once
-  (or (assq 'c-auto-hungry-string minor-mode-alist)
+  ;; Put submode indicators onto minor-mode-alist, but only once.
+  (or (assq 'c-submode-indicators minor-mode-alist)
       (setq minor-mode-alist
-           (cons '(c-auto-hungry-string c-auto-hungry-string)
+           (cons '(c-submode-indicators c-submode-indicators)
                  minor-mode-alist)))
 
   ;; Install the functions that ensure that various internal caches
   ;; don't become invalid due to buffer changes.
+  (make-local-hook 'after-change-functions)
   (add-hook 'after-change-functions 'c-after-change nil t))
 
 (defun c-after-font-lock-init ()
@@ -505,7 +573,7 @@ This does not load the font-lock package.  Use after
 
   (make-local-variable 'font-lock-defaults)
   (setq font-lock-defaults
-       `(,(if (c-mode-is-new-awk-p)
+       `(,(if (c-major-mode-is 'awk-mode)
               ;; awk-mode currently has only one font lock level.
               'awk-font-lock-keywords
             (mapcar 'c-mode-symbol
@@ -517,6 +585,8 @@ This does not load the font-lock package.  Use after
          (font-lock-lines-before . 1)
          (font-lock-mark-block-function
           . c-mark-function)))
+
+  (make-local-hook 'font-lock-mode-hook)
   (add-hook 'font-lock-mode-hook 'c-after-font-lock-init nil t))
 
 (defun c-setup-doc-comment-style ()
@@ -536,9 +606,7 @@ Mode to operate correctly.
 
 MODE is the symbol for the mode to initialize, like 'c-mode.  See
 `c-basic-common-init' for details.  It's only optional to be
-compatible with old code; callers should always specify it.
-
-This function does not do any hidden buffer changes."
+compatible with old code; callers should always specify it."
 
   (unless mode
     ;; Called from an old third party package.  The fallback is to
@@ -569,8 +637,6 @@ setting found in `c-file-style', then it applies any offset settings
 it finds in `c-file-offsets'.
 
 Note that the style variables are always made local to the buffer."
-  ;;
-  ;; This function does not do any hidden buffer changes.
 
   ;; apply file styles and offsets
   (when c-buffer-is-cc-mode
@@ -584,7 +650,18 @@ Note that the style variables are always made local to the buffer."
            (let ((langelem (car langentry))
                  (offset (cdr langentry)))
              (c-set-offset langelem offset)))
-         c-file-offsets))))
+         c-file-offsets))
+    ;; Problem: The file local variable block might have explicitly set a
+    ;; style variable.  The `c-set-style' or `mapcar' call might have
+    ;; overwritten this.  So we run `hack-local-variables' again to remedy
+    ;; this.  There are no guarantees this will work properly, particularly as
+    ;; we have no control over what the other hook functions on
+    ;; `hack-local-variables-hook' would have done, or what any "eval"
+    ;; expression will do when evaluated again.  C'est la vie!  ACM,
+    ;; 2005/11/2.
+    (if (or c-file-style c-file-offsets)
+       (let ((hack-local-variables-hook nil))
+         (hack-local-variables)))))
 
 (add-hook 'hack-local-variables-hook 'c-postprocess-file-styles)
 
@@ -794,9 +871,6 @@ Key bindings:
        mode-name "ObjC"
        local-abbrev-table objc-mode-abbrev-table
        abbrev-mode t)
-  ;; The `c-type' text property with `c-decl-end' is used to mark the
-  ;; end of the @-style directives.
-  (setq c-type-decl-end-used t)
   (use-local-map objc-mode-map)
   (c-init-language-vars-for 'objc-mode)
   (c-common-init 'objc-mode)
@@ -996,8 +1070,7 @@ Key bindings:
   (c-update-modeline))
 
 \f
-;; Support for awk.  This is purposely disabled for older (X)Emacsen which
-;; don't support syntax-table properties.
+;; Support for AWK
 
 ;;;###autoload (add-to-list 'auto-mode-alist '("\\.awk\\'" . awk-mode))
 ;;;###autoload (add-to-list 'interpreter-mode-alist '("awk" . awk-mode))
@@ -1009,37 +1082,34 @@ Key bindings:
 ;;; autoload form instead.
 ;;;###autoload (autoload 'awk-mode "cc-mode" "Major mode for editing AWK code." t)
 
-(if (not (memq 'syntax-properties c-emacs-features))
-    (autoload 'awk-mode "awk-mode" "Major mode for editing AWK code."  t)
-
-  (defvar awk-mode-abbrev-table nil
-    "Abbreviation table used in awk-mode buffers.")
-  (c-define-abbrev-table 'awk-mode-abbrev-table
-    '(("else" "else" c-electric-continued-statement 0)
-      ("while" "while" c-electric-continued-statement 0)))
-
-  (defvar awk-mode-map ()
-    "Keymap used in awk-mode buffers.")
-  (if awk-mode-map
-      nil
-    (setq awk-mode-map (c-make-inherited-keymap))
-    ;; add bindings which are only useful for awk.
-    (define-key awk-mode-map "#" 'self-insert-command)
-    (define-key awk-mode-map "/" 'self-insert-command)
-    (define-key awk-mode-map "*" 'self-insert-command)
-    (define-key awk-mode-map "\C-c\C-n" 'undefined) ; #if doesn't exist in awk.
-    (define-key awk-mode-map "\C-c\C-p" 'undefined)
-    (define-key awk-mode-map "\C-c\C-u" 'undefined)
-    (define-key awk-mode-map "\M-a" 'undefined) ; c-awk-beginning-of-statement isn't yet implemented.
-    (define-key awk-mode-map "\M-e" 'undefined) ; c-awk-end-of-statement isn't yet implemented.
-    (define-key awk-mode-map "\C-\M-a" 'c-awk-beginning-of-defun)
-    (define-key awk-mode-map "\C-\M-e" 'c-awk-end-of-defun))
-
-  (easy-menu-define c-awk-menu awk-mode-map "AWK Mode Commands"
-    (cons "AWK" (c-lang-const c-mode-menu awk)))
-
-  (defun awk-mode ()
-    "Major mode for editing AWK code.
+(defvar awk-mode-abbrev-table nil
+  "Abbreviation table used in awk-mode buffers.")
+(c-define-abbrev-table 'awk-mode-abbrev-table
+  '(("else" "else" c-electric-continued-statement 0)
+    ("while" "while" c-electric-continued-statement 0)))
+
+(defvar awk-mode-map ()
+  "Keymap used in awk-mode buffers.")
+(if awk-mode-map
+    nil
+  (setq awk-mode-map (c-make-inherited-keymap))
+  ;; add bindings which are only useful for awk.
+  (define-key awk-mode-map "#" 'self-insert-command)
+  (define-key awk-mode-map "/" 'self-insert-command)
+  (define-key awk-mode-map "*" 'self-insert-command)
+  (define-key awk-mode-map "\C-c\C-n" 'undefined) ; #if doesn't exist in awk.
+  (define-key awk-mode-map "\C-c\C-p" 'undefined)
+  (define-key awk-mode-map "\C-c\C-u" 'undefined)
+  (define-key awk-mode-map "\M-a" 'c-beginning-of-statement) ; 2003/10/7
+  (define-key awk-mode-map "\M-e" 'c-end-of-statement) ; 2003/10/7
+  (define-key awk-mode-map "\C-\M-a" 'c-awk-beginning-of-defun)
+  (define-key awk-mode-map "\C-\M-e" 'c-awk-end-of-defun))
+
+(easy-menu-define c-awk-menu awk-mode-map "AWK Mode Commands"
+                 (cons "AWK" (c-lang-const c-mode-menu awk)))
+
+(defun awk-mode ()
+  "Major mode for editing AWK code.
 To submit a problem report, enter `\\[c-submit-bug-report]' from an
 awk-mode buffer.  This automatically sets up a mail buffer with version
 information already added.  You just need to add a description of the
@@ -1052,41 +1122,40 @@ initialization, then `awk-mode-hook'.
 
 Key bindings:
 \\{awk-mode-map}"
-    (interactive)
-    (require 'cc-awk)                   ; Added 2003/6/10.
-    (kill-all-local-variables)
-    (c-initialize-cc-mode t)
-    (set-syntax-table awk-mode-syntax-table)
-    (setq major-mode 'awk-mode
-          mode-name "AWK"
-          local-abbrev-table awk-mode-abbrev-table
-          abbrev-mode t)
-    (use-local-map awk-mode-map)
-    (c-init-language-vars-for 'awk-mode)
-    (c-common-init 'awk-mode)
-    ;; The rest of CC Mode does not (yet) use `font-lock-syntactic-keywords',
-    ;; so it's not set by `c-font-lock-init'.
-    (make-local-variable 'font-lock-syntactic-keywords)
-    (setq font-lock-syntactic-keywords
-          '((c-awk-set-syntax-table-properties
-             0 (0)                      ; Everything on this line is a dummy.
-             nil t)))
-    (c-awk-unstick-NL-prop)
-    (add-hook 'before-change-functions 'c-awk-before-change nil t)
-    (add-hook 'after-change-functions 'c-awk-after-change nil t)
-    (c-save-buffer-state nil
-      (save-restriction
-        (widen)
-        (c-awk-clear-NL-props (point-min) (point-max))
-        (c-awk-after-change (point-min) (point-max) 0))) ; Set syntax-table props.
-
-    ;; Prevent Xemacs's buffer-syntactic-context being used.  See the comment
-    ;; in cc-engine.el, just before (defun c-fast-in-literal ...
-    (defalias 'c-in-literal 'c-slow-in-literal)
-
-    (c-run-mode-hooks 'c-mode-common-hook 'awk-mode-hook)
-    (c-update-modeline))
-) ;; closes the (if (not (memq 'syntax-properties c-emacs-features))
+  (interactive)
+  (require 'cc-awk)                    ; Added 2003/6/10.
+  (kill-all-local-variables)
+  (c-initialize-cc-mode t)
+  (set-syntax-table awk-mode-syntax-table)
+  (setq major-mode 'awk-mode
+       mode-name "AWK"
+       local-abbrev-table awk-mode-abbrev-table
+       abbrev-mode t)
+  (use-local-map awk-mode-map)
+  (c-init-language-vars-for 'awk-mode)
+  (c-common-init 'awk-mode)
+  ;; The rest of CC Mode does not (yet) use `font-lock-syntactic-keywords',
+  ;; so it's not set by `c-font-lock-init'.
+  (make-local-variable 'font-lock-syntactic-keywords)
+  (setq font-lock-syntactic-keywords
+       '((c-awk-set-syntax-table-properties
+          0 (0)                        ; Everything on this line is a dummy.
+          nil t)))
+  (c-awk-unstick-NL-prop)
+  (add-hook 'before-change-functions 'c-awk-before-change nil t)
+  (add-hook 'after-change-functions 'c-awk-after-change nil t)
+  (c-save-buffer-state nil
+    (save-restriction
+      (widen)
+      (c-awk-clear-NL-props (point-min) (point-max))
+      (c-awk-after-change (point-min) (point-max) 0))) ; Set syntax-table props.
+
+  ;; Prevent Xemacs's buffer-syntactic-context being used.  See the comment
+  ;; in cc-engine.el, just before (defun c-fast-in-literal ...
+  (defalias 'c-in-literal 'c-slow-in-literal)
+
+  (c-run-mode-hooks 'c-mode-common-hook 'awk-mode-hook)
+  (c-update-modeline))
 
 \f
 ;; bug reporting
@@ -1175,5 +1244,5 @@ Key bindings:
 \f
 (cc-provide 'cc-mode)
 
-;; arch-tag: 7825e5c4-fd09-439f-a04d-4c13208ba3d7
+;;; arch-tag: 7825e5c4-fd09-439f-a04d-4c13208ba3d7
 ;;; cc-mode.el ends here
index f20eb8e57de0f75bfa6d2e47a41a230f34467733..2377b4ce8bd37c3362f86a73ece5d67f4d86d412 100644 (file)
@@ -1,6 +1,7 @@
 ;;; cc-styles.el --- support for styles in CC Mode
 
-;; Copyright (C) 1985,1987,1992-2003, 2004, 2005 Free Software Foundation, Inc.
+;; Copyright (C) 1985,1987,1992-2003, 2004, 2005 Free Software Foundation,
+;; Inc.
 
 ;; Authors:    1998- Martin Stjernholm
 ;;             1992-1999 Barry A. Warsaw
@@ -24,7 +25,7 @@
 ;; GNU General Public License for more details.
 
 ;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING.  If not, write to
+;; along with this program; see the file COPYING.  If not, write to
 ;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 ;; Boston, MA 02110-1301, USA.
 
@@ -55,6 +56,7 @@
   '(("gnu"
      (c-basic-offset . 2)
      (c-comment-only-line-offset . (0 . 0))
+     (c-hanging-braces-alist     . ((substatement-open before after)))
      (c-offsets-alist . ((statement-block-intro . +)
                         (knr-argdecl-intro . 5)
                         (substatement-open . +)
                         (arglist-intro . c-lineup-arglist-intro-after-paren)
                         (arglist-close . c-lineup-arglist)
                         (inline-open . 0)
-                        (brace-list-open . +)
-                        ))
+                        (brace-list-open . +)))
      (c-special-indent-hook . c-gnu-impose-minimum)
-     (c-block-comment-prefix . "")
-     )
+     (c-block-comment-prefix . ""))
+
     ("k&r"
      (c-basic-offset . 5)
      (c-comment-only-line-offset . 0)
@@ -78,9 +79,8 @@
                         (substatement-open . 0)
                         (substatement-label . 0)
                         (label . 0)
-                        (statement-cont . +)
-                        ))
-     )
+                        (statement-cont . +))))
+
     ("bsd"
      (c-basic-offset . 8)
      (c-comment-only-line-offset . 0)
@@ -91,9 +91,8 @@
                         (label . 0)
                         (statement-cont . +)
                         (inline-open . 0)
-                        (inexpr-class . 0)
-                        ))
-     )
+                        (inexpr-class . 0))))
+
     ("stroustrup"
      (c-basic-offset . 4)
      (c-comment-only-line-offset . 0)
                         (substatement-open . 0)
                         (substatement-label . 0)
                         (label . 0)
-                        (statement-cont . +)
-                        ))
-     )
+                        (statement-cont . +))))
+
     ("whitesmith"
      (c-basic-offset . 4)
      (c-comment-only-line-offset . 0)
-     (c-offsets-alist . ((knr-argdecl-intro . +)
-                        (label . 0)
-                        (statement-cont . +)
-                        (substatement-open . +)
-                        (substatement-label . +)
-                        (block-open . +)
-                        (statement-block-intro . c-lineup-whitesmith-in-block)
-                        (block-close . c-lineup-whitesmith-in-block)
-                        (inline-open . +)
-                        (defun-open . +)
-                        (defun-block-intro . c-lineup-whitesmith-in-block)
+     ;; It's obvious that the CC Mode way of choosing anchor positions
+     ;; doesn't fit this style at all. :P
+     (c-offsets-alist . ((defun-open . +)
                         (defun-close . c-lineup-whitesmith-in-block)
+                        (defun-block-intro . (add c-lineup-whitesmith-in-block
+                                                  c-indent-multi-line-block))
+                        (class-open . +)
+                        (class-close . +)
+                        (inline-open . +)
+                        (inline-close . c-lineup-whitesmith-in-block)
+                        (knr-argdecl-intro . +)
+                        (block-open . 0) ; Get indentation from `statement' instead.
+                        (block-close . c-lineup-whitesmith-in-block)
                         (brace-list-open . +)
-                        (brace-list-intro . c-lineup-whitesmith-in-block)
-                        (brace-entry-open . c-indent-multi-line-block)
                         (brace-list-close . c-lineup-whitesmith-in-block)
-                        (class-open . +)
+                        (brace-list-intro . (add c-lineup-whitesmith-in-block
+                                                 c-indent-multi-line-block))
+                        (brace-list-entry . (add c-lineup-after-whitesmith-blocks
+                                                 c-indent-multi-line-block))
+                        (brace-entry-open . (add c-lineup-after-whitesmith-blocks
+                                                 c-indent-multi-line-block))
+                        (statement . (add c-lineup-after-whitesmith-blocks
+                                          c-indent-multi-line-block))
+                        (statement-block-intro . (add c-lineup-whitesmith-in-block
+                                                      c-indent-multi-line-block))
+                        (substatement-open . +)
+                        (substatement-label . +)
+                        (label . 0)
+                        (arglist-intro . (add c-lineup-whitesmith-in-block
+                                              c-indent-multi-line-block))
+                        (arglist-cont . (add c-lineup-after-whitesmith-blocks
+                                             c-indent-multi-line-block))
+                        (arglist-cont-nonempty . (add c-lineup-whitesmith-in-block
+                                                      c-indent-multi-line-block))
+                        (arglist-close . c-lineup-whitesmith-in-block)
                         (inclass . c-lineup-whitesmith-in-block)
-                        (class-close . +)
-                        (inexpr-class . 0)
                         (extern-lang-open . +)
-                        (inextern-lang . c-lineup-whitesmith-in-block)
-                        (extern-lang-close . +)
                         (namespace-open . +)
-                        (innamespace . c-lineup-whitesmith-in-block)
-                        (namespace-close . +)
                         (module-open . +)
-                        (inmodule . c-lineup-whitesmith-in-block)
-                        (module-close . +)
                         (composition-open . +)
-                        (incomposition . c-lineup-whitesmith-in-block)
+                        (extern-lang-close . +)
+                        (namespace-close . +)
+                        (module-close . +)
                         (composition-close . +)
-                        ))
-     )
+                        (inextern-lang . c-lineup-whitesmith-in-block)
+                        (innamespace . c-lineup-whitesmith-in-block)
+                        (inmodule . c-lineup-whitesmith-in-block)
+                        (incomposition . c-lineup-whitesmith-in-block)
+                        (inexpr-class . 0))))
+
     ("ellemtel"
      (c-basic-offset . 3)
      (c-comment-only-line-offset . 0)
                          (case-label           . +)
                          (access-label         . -)
                          (inclass              . ++)
-                         (inline-open          . 0)
-                         ))
-     )
+                        (inline-open          . 0))))
+
     ("linux"
      (c-basic-offset  . 8)
      (c-comment-only-line-offset . 0)
                         (substatement-open     . 0)
                         (substatement-label    . 0)
                         (label                 . 0)
-                        (statement-cont        . +)
-                        ))
-     )
+                        (statement-cont        . +))))
+
     ("python"
      (indent-tabs-mode . t)
      (fill-column      . 78)
      (c-offsets-alist  . ((substatement-open . 0)
                          (inextern-lang . 0)
                          (arglist-intro . +)
-                         (knr-argdecl-intro . +)
-                         ))
+                         (knr-argdecl-intro . +)))
      (c-hanging-braces-alist . ((brace-list-open)
                                (brace-list-intro)
                                (brace-list-close)
                                (brace-entry-open)
                                (substatement-open after)
-                               (block-close . c-snug-do-while)
-                               ))
-     (c-block-comment-prefix . "")
-     )
+                               (block-close . c-snug-do-while)))
+     (c-block-comment-prefix . ""))
+
     ("java"
      (c-basic-offset . 4)
      (c-comment-only-line-offset . (0 . 0))
                         (arglist-close  . c-lineup-arglist)
                         (access-label   . 0)
                         (inher-cont     . c-lineup-java-inher)
-                        (func-decl-cont . c-lineup-java-throws)
-                        ))
-     )
+                        (func-decl-cont . c-lineup-java-throws))))
+
+    ;; awk style exists primarily for auto-newline settings.  Otherwise it's
+    ;; pretty much like k&r.
+    ("awk"
+     (c-basic-offset . 4)
+     (c-comment-only-line-offset . 0)
+     (c-hanging-braces-alist . ((defun-open after)
+                               (defun-close . c-snug-1line-defun-close)
+                               (substatement-open after)
+                               (block-close . c-snug-do-while)))
+     (c-hanging-semi&comma-criteria . nil)
+     (c-cleanup-list . nil)            ; You might want one-liner-defun here.
+     (c-offsets-alist . ((statement-block-intro . +)
+                        (substatement-open . 0)
+                        (statement-cont . +))))
+
     )
   "Styles of indentation.
 Elements of this alist are of the form:
@@ -246,8 +270,6 @@ the existing style.")
 ;; Functions that manipulate styles
 (defun c-set-style-1 (conscell dont-override)
   ;; Set the style for one variable
-  ;;
-  ;; This function does not do any hidden buffer changes.
   (let ((attr (car conscell))
        (val  (cdr conscell)))
     (cond
@@ -291,8 +313,6 @@ the existing style.")
 
 (defun c-get-style-variables (style basestyles)
   ;; Return all variables in a style by resolving inheritances.
-  ;;
-  ;; This function does not do any hidden buffer changes.
   (if (not style)
       (copy-alist c-fallback-style)
     (let ((vars (cdr (or (assoc (downcase style) c-style-alist)
@@ -314,48 +334,36 @@ the existing style.")
 
 ;;;###autoload
 (defun c-set-style (stylename &optional dont-override)
-  "Set CC Mode variables to use one of several different indentation styles.
-STYLENAME is a string representing the desired style from the list of
-styles described in the variable `c-style-alist'.  See that variable
-for details of setting up styles.
-
-The variable `c-indentation-style' always contains the buffer's current
-style name.
-
-If the optional argument DONT-OVERRIDE is t, no style variables that
-already have values will be overridden.  I.e. in the case of
-`c-offsets-alist', syntactic symbols will only be added, and in the
-case of all other style variables, only those set to `set-from-style'
-will be reassigned.
-
-If DONT-OVERRIDE is neither nil nor t, only those style variables that
-have default (i.e. non-buffer local) values will keep their settings
-while the rest will be overridden.  This is useful to avoid overriding
-global settings done in ~/.emacs when setting a style from a mode hook
-\(providing the style variables are buffer local, which is the
-default).
-
-Obviously, setting DONT-OVERRIDE to t is useful mainly when the
-initial style is chosen for a CC Mode buffer by a major mode.  Since
-that is done internally by CC Mode, it typically won't have any effect
-when used elsewhere."
+  "Set the current buffer to use the style STYLENAME.
+STYLENAME, a string, must be an existing CC Mode style - These are contained
+in the variable `c-style-alist'.
+
+The variable `c-indentation-style' will get set to STYLENAME.
+
+\"Setting the style\" is done by setting CC Mode's \"style variables\" to the
+values indicated by the pertinent entry in `c-style-alist'.  Other variables
+might get set too.
+
+If DONT-OVERRIDE is neither nil nor t, style variables whose default values
+have been set (more precisely, whose default values are not the symbol
+`set-from-style') will not be changed.  This avoids overriding global settings
+done in ~/.emacs.  It is useful to call c-set-style from a mode hook in this
+way.
+
+If DONT-OVERRIDE is t, style variables that already have values (i.e., whose
+values are not the symbol `set-from-style') will not be overridden.  CC Mode
+calls c-set-style internally in this way whilst initializing a buffer; if
+cc-set-style is called like this from anywhere else, it will usually behave as
+a null operation."
   (interactive
    (list (let ((completion-ignore-case t)
               (prompt (format "Which %s indentation style? "
                               mode-name)))
-          (condition-case nil
-              ;; The default argument is preferred over
-              ;; initial-contents, but it only exists in Emacs >= 20
-              ;; and XEmacs >= 21.
-              (completing-read prompt c-style-alist nil t nil
-                               'c-set-style-history
-                               c-indentation-style)
-            (wrong-number-of-arguments
-             ;; If the call above failed, we fall back to the old way
-             ;; of specifying the default value.
-             (completing-read prompt c-style-alist nil t
-                              (cons c-indentation-style 0)
-                              'c-set-style-history))))))
+          (completing-read prompt c-style-alist nil t nil
+                           'c-set-style-history
+                           c-indentation-style))))
+  (or c-buffer-is-cc-mode
+      (error "Buffer %s is not a CC Mode buffer (c-set-style)" (buffer-name)))
   (or (stringp stylename)
       (error "Argument to c-set-style was not a string"))
   (c-initialize-builtin-style)
@@ -406,8 +414,6 @@ STYLE using `c-set-style' if the optional SET-P flag is non-nil."
 (defun c-read-offset (langelem)
   ;; read new offset value for LANGELEM from minibuffer. return a
   ;; legal value only
-  ;;
-  ;; This function does not do any hidden buffer changes.
   (let* ((oldoff  (cdr-safe (or (assq langelem c-offsets-alist)
                                (assq langelem (get 'c-offsets-alist
                                                    'c-stylevar-fallback)))))
@@ -475,20 +481,22 @@ and exists only for compatibility reasons."
              (setq c-offsets-alist (cons (cons symbol offset)
                                          c-offsets-alist))
            (c-benign-error "%s is not a valid syntactic symbol" symbol))))
-    (c-benign-error "Invalid indentation setting for symbol %s: %s"
+    (c-benign-error "Invalid indentation setting for symbol %s: %S"
                    symbol offset))
   (c-keep-region-active))
 
 \f
 (defun c-setup-paragraph-variables ()
-  "Fix things up for paragraph recognition and filling inside comments by
-incorporating the value of `c-comment-prefix-regexp' in the relevant
+  "Fix things up for paragraph recognition and filling inside comments and
+strings by incorporating the values of `c-comment-prefix-regexp',
+`sentence-end', `paragraph-start' and `paragraph-separate' in the relevant
 variables."
-  ;;
-  ;; This function does not do any hidden buffer changes.
 
   (interactive)
-
+  (or c-buffer-is-cc-mode
+      (error "Buffer %s is not a CC Mode buffer (c-setup-paragraph-variables)"
+            (buffer-name)))
+  ;; Set up the values for use in comments.
   (setq c-current-comment-prefix
        (if (listp c-comment-prefix-regexp)
            (cdr-safe (or (assoc major-mode c-comment-prefix-regexp)
@@ -498,34 +506,48 @@ variables."
   (let ((comment-line-prefix
         (concat "[ \t]*\\(" c-current-comment-prefix "\\)[ \t]*")))
 
-    (set (make-local-variable 'paragraph-start)
-         (concat comment-line-prefix
-                 c-paragraph-start
-                 "\\|"
-                 page-delimiter))
-    (set (make-local-variable 'paragraph-separate)
-         (concat comment-line-prefix
-                 c-paragraph-separate
-                 "\\|"
-                 page-delimiter))
-    (set (make-local-variable 'paragraph-ignore-fill-prefix) t)
-    (set (make-local-variable 'adaptive-fill-mode) t)
-    (set (make-local-variable 'adaptive-fill-regexp)
-         (concat comment-line-prefix
-                 (if (default-value 'adaptive-fill-regexp)
-                     (concat "\\("
-                             (default-value 'adaptive-fill-regexp)
-                             "\\)")
-                   "")))
+    (setq paragraph-start (concat comment-line-prefix
+                                 c-paragraph-start
+                                 "\\|"
+                                 page-delimiter)
+         paragraph-separate (concat comment-line-prefix
+                                    c-paragraph-separate
+                                    "\\|"
+                                    page-delimiter)
+         paragraph-ignore-fill-prefix t
+         adaptive-fill-mode t
+         adaptive-fill-regexp
+         (concat comment-line-prefix
+                 (if (default-value 'adaptive-fill-regexp)
+                     (concat "\\("
+                             (default-value 'adaptive-fill-regexp)
+                             "\\)")
+                   "")))
 
     (when (boundp 'adaptive-fill-first-line-regexp)
-      ;; XEmacs (20.x) adaptive fill mode doesn't have this.
-      (set (make-local-variable 'adaptive-fill-first-line-regexp)
-           (concat "\\`" comment-line-prefix
-                   ;; Maybe we should incorporate the old value here,
-                   ;; but then we have to do all sorts of kludges to
-                   ;; deal with the \` and \' it probably contains.
-                   "\\'")))))
+      ;; XEmacs adaptive fill mode doesn't have this.
+      (make-local-variable 'adaptive-fill-first-line-regexp)
+      (setq adaptive-fill-first-line-regexp
+           (concat "\\`" comment-line-prefix
+                   ;; Maybe we should incorporate the old value here,
+                   ;; but then we have to do all sorts of kludges to
+                   ;; deal with the \` and \' it probably contains.
+                   "\\'"))))
+
+  ;; Set up the values for use in strings.  These are the default
+  ;; paragraph-start/separate values, enhanced to accept escaped EOLs as
+  ;; whitespace.  Used in c-beginning/end-of-sentence-in-string in cc-cmds.
+  (setq c-string-par-start
+       ;;(concat "\\(" (default-value 'paragraph-start) "\\)\\|[ \t]*\\\\$"))
+       "\f\\|[ \t]*\\\\?$")
+  (setq c-string-par-separate
+       ;;(concat "\\(" (default-value 'paragraph-separate) "\\)\\|[ \t]*\\\\$"))
+       "[ \t\f]*\\\\?$")
+  (setq c-sentence-end-with-esc-eol
+       (concat "\\(\\(" (c-default-value-sentence-end) "\\)"
+               ;; N.B.:  "$" would be illegal when not enclosed like "\\($\\)".
+               "\\|" "[.?!][]\"')}]* ?\\\\\\($\\)[ \t\n]*"
+               "\\)")))
 
 \f
 ;; Helper for setting up Filladapt mode.  It's not used by CC Mode itself.
@@ -542,8 +564,6 @@ CC Mode by making sure the proper entries are present on
 `c-mode-common-hook' or similar."
   ;; This function is intended to be used explicitly by the end user
   ;; only.
-  ;;
-  ;; This function does not do any hidden buffer changes.
 
   ;; The default configuration already handles C++ comments, but we
   ;; need to add handling of C block comments.  A new filladapt token
@@ -573,8 +593,6 @@ CC Mode by making sure the proper entries are present on
   ;; crucial because future c-set-style calls will always reset the
   ;; variables first to the `cc-mode' style before instituting the new
   ;; style.  Only do this once!
-  ;;
-  ;; This function does not do any hidden buffer changes.
   (unless (get 'c-initialize-builtin-style 'is-run)
     (put 'c-initialize-builtin-style 'is-run t)
     ;;(c-initialize-cc-mode)
@@ -601,13 +619,11 @@ CC Mode by making sure the proper entries are present on
   "Make all CC Mode style variables buffer local.
 If `this-buf-only-p' is non-nil, the style variables will be made
 buffer local only in the current buffer.  Otherwise they'll be made
-permanently buffer local in any buffer that change their values.
+permanently buffer local in any buffer that changes their values.
 
 The buffer localness of the style variables are normally controlled
 with the variable `c-style-variables-are-local-p', so there's seldom
 any reason to call this function directly."
-  ;;
-  ;; This function does not do any hidden buffer changes.
 
   ;; style variables
   (let ((func (if this-buf-only-p
@@ -619,7 +635,7 @@ any reason to call this function directly."
     ;; Hooks must be handled specially
     (if this-buf-only-p
        (make-local-hook 'c-special-indent-hook)
-      (make-variable-buffer-local 'c-special-indent-hook)
+      (with-no-warnings (make-variable-buffer-local 'c-special-indent-hook))
       (setq c-style-variables-are-local-p t))
     ))
 
@@ -627,5 +643,5 @@ any reason to call this function directly."
 \f
 (cc-provide 'cc-styles)
 
-;; arch-tag: c764f61a-96ba-484a-a68f-101c0e9d5d2c
+;;; arch-tag: c764f61a-96ba-484a-a68f-101c0e9d5d2c
 ;;; cc-styles.el ends here
diff --git a/lisp/progmodes/cc-subword.el b/lisp/progmodes/cc-subword.el
new file mode 100644 (file)
index 0000000..fd4ca89
--- /dev/null
@@ -0,0 +1,312 @@
+;;; cc-subword.el --- Handling capitalized subwords in a nomenclature
+
+;; Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+
+;; Author: Masatake YAMATO
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program; see the file COPYING.  If not, write to
+;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; This package provides `subword' oriented commands and a minor mode
+;; (`c-subword-mode') that substitutes the common word handling
+;; functions with them.
+
+;; In spite of GNU Coding Standards, it is popular to name a symbol by
+;; mixing uppercase and lowercase letters, e.g. "GtkWidget",
+;; "EmacsFrameClass", "NSGraphicsContext", etc.  Here we call these
+;; mixed case symbols `nomenclatures'.  Also, each capitalized (or
+;; completely uppercase) part of a nomenclature is called a `subword'.
+;; Here are some examples:
+
+;;  Nomenclature           Subwords
+;;  ===========================================================
+;;  GtkWindow          =>  "Gtk" and "Window"
+;;  EmacsFrameClass    =>  "Emacs", "Frame" and "Class"
+;;  NSGraphicsContext  =>  "NS", "Graphics" and "Context"
+
+;; The subword oriented commands defined in this package recognize
+;; subwords in a nomenclature to move between them and to edit them as
+;; words.
+
+;; In the minor mode, all common key bindings for word oriented
+;; commands are overridden by the subword oriented commands:
+
+;; Key     Word oriented command      Subword oriented command
+;; ============================================================
+;; M-f     `forward-word'             `c-forward-subword'
+;; M-b     `backward-word'            `c-backward-subword'
+;; M-@     `mark-word'                `c-mark-subword'
+;; M-d     `kill-word'                `c-kill-subword'
+;; M-DEL   `backward-kill-word'       `c-backward-kill-subword'
+;; M-t     `transpose-words'          `c-transpose-subwords'
+;; M-c     `capitalize-word'          `c-capitalize-subword'
+;; M-u     `upcase-word'              `c-upcase-subword'
+;; M-l     `downcase-word'            `c-downcase-subword'
+;;
+;; Note: If you have changed the key bindings for the word oriented
+;; commands in your .emacs or a similar place, the keys you've changed
+;; to are also used for the corresponding subword oriented commands.
+
+;; To make the mode turn on automatically, put the following code in
+;; your .emacs:
+;;
+;; (add-hook 'c-mode-common-hook
+;;       (lambda () (c-subword-mode 1)))
+;;
+
+;; Acknowledgment:
+;; The regular expressions to detect subwords are mostly based on
+;; the old `c-forward-into-nomenclature' originally contributed by
+;; Terry_Glanfield dot Southern at rxuk dot xerox dot com.
+
+;; TODO: ispell-word and subword oriented C-w in isearch.
+
+;;; Code:
+
+(eval-when-compile
+  (let ((load-path
+        (if (and (boundp 'byte-compile-dest-file)
+                 (stringp byte-compile-dest-file))
+            (cons (file-name-directory byte-compile-dest-file) load-path)
+          load-path)))
+    (load "cc-bytecomp" nil t)))
+
+(cc-require 'cc-defs)
+(cc-require 'cc-cmds)
+
+;; Don't complain about the `define-minor-mode' form if it isn't defined.
+(cc-bytecomp-defvar c-subword-mode)
+
+;;; Autoload directives must be on the top level, so we construct an
+;;; autoload form instead.
+;;;###autoload (autoload 'c-subword-mode "cc-subword" "Mode enabling subword movement and editing keys." t)
+
+(if (not (fboundp 'define-minor-mode))
+    (defun c-subword-mode ()
+      "(Missing) mode enabling subword movement and editing keys.
+This mode is not (yet) available in this version of (X)Emacs.  Sorry!  If
+you really want it, please send a request to <bug-gnu-emacs@gnu.org>,
+telling us which (X)Emacs version you're using."
+      (interactive)
+      (error
+       "c-subword-mode is not (yet) available in this version of (X)Emacs.  Sorry!"))
+
+  (defvar c-subword-mode-map
+    (let ((map (make-sparse-keymap)))
+      (substitute-key-definition 'forward-word
+                                'c-forward-subword
+                                map global-map)
+      (substitute-key-definition 'backward-word
+                                'c-backward-subword
+                                map global-map)
+      (substitute-key-definition 'mark-word
+                                'c-mark-subword
+                                map global-map)
+    
+      (substitute-key-definition 'kill-word
+                                'c-kill-subword
+                                map global-map)
+      (substitute-key-definition 'backward-kill-word
+                                'c-backward-kill-subword
+                                map global-map)
+    
+      (substitute-key-definition 'transpose-words
+                                'c-transpose-subwords
+                                map global-map)
+    
+      (substitute-key-definition 'capitalize-word
+                                'c-capitalize-subword
+                                map global-map)
+      (substitute-key-definition 'upcase-word
+                                'c-upcase-subword
+                                map global-map)
+      (substitute-key-definition 'downcase-word
+                                'c-downcase-subword
+                                map global-map)
+      map)
+    "Keymap used in command `c-subword-mode' minor mode.")
+
+  (define-minor-mode c-subword-mode
+    "Mode enabling subword movement and editing keys.
+In spite of GNU Coding Standards, it is popular to name a symbol by
+mixing uppercase and lowercase letters, e.g. \"GtkWidget\",
+\"EmacsFrameClass\", \"NSGraphicsContext\", etc.  Here we call these
+mixed case symbols `nomenclatures'. Also, each capitalized (or
+completely uppercase) part of a nomenclature is called a `subword'.
+Here are some examples:
+
+  Nomenclature           Subwords
+  ===========================================================
+  GtkWindow          =>  \"Gtk\" and \"Window\"
+  EmacsFrameClass    =>  \"Emacs\", \"Frame\" and \"Class\"
+  NSGraphicsContext  =>  \"NS\", \"Graphics\" and \"Context\"
+
+The subword oriented commands activated in this minor mode recognize
+subwords in a nomenclature to move between subwords and to edit them
+as words.
+
+\\{c-subword-mode-map}"
+    nil
+    nil
+    c-subword-mode-map
+    (c-update-modeline))
+
+  )
+
+(defun c-forward-subword (&optional arg)
+  "Do the same as `forward-word' but on subwords.
+See the command `c-subword-mode' for a description of subwords.
+Optional argument ARG is the same as for `forward-word'."
+  (interactive "p")
+  (unless arg (setq arg 1))
+  (c-keep-region-active)
+  (cond
+   ((< 0 arg)
+    (dotimes (i arg (point))
+      (c-forward-subword-internal)))
+   ((> 0 arg)
+    (dotimes (i (- arg) (point))
+      (c-backward-subword-internal)))
+   (t
+    (point))))
+
+(defun c-backward-subword (&optional arg)
+  "Do the same as `backward-word' but on subwords.
+See the command `c-subword-mode' for a description of subwords.
+Optional argument ARG is the same as for `backward-word'."
+  (interactive "p")
+  (c-forward-subword (- (or arg 1))))
+
+(defun c-mark-subword (arg)
+  "Do the same as `mark-word' but on subwords.
+See the command `c-subword-mode' for a description of subwords.
+Optional argument ARG is the same as for `mark-word'."
+  ;; This code is almost copied from `mark-word' in GNU Emacs.
+  (interactive "p")
+  (cond ((and (eq last-command this-command) (mark t))
+        (set-mark
+         (save-excursion
+           (goto-char (mark))
+           (c-forward-subword arg)
+           (point))))
+       (t
+        (push-mark
+         (save-excursion
+           (c-forward-subword arg)
+           (point))
+         nil t))))
+
+(defun c-kill-subword (arg)
+  "Do the same as `kill-word' but on subwords.
+See the command `c-subword-mode' for a description of subwords.
+Optional argument ARG is the same as for `kill-word'."
+  (interactive "p")
+  (kill-region (point) (c-forward-subword arg)))
+
+(defun c-backward-kill-subword (arg)
+  "Do the same as `backward-kill-word' but on subwords.
+See the command `c-subword-mode' for a description of subwords.
+Optional argument ARG is the same as for `backward-kill-word'."
+  (interactive "p")
+  (c-kill-subword (- arg)))
+
+(defun c-transpose-subwords (arg)
+  "Do the same as `transpose-words' but on subwords.
+See the command `c-subword-mode' for a description of subwords.
+Optional argument ARG is the same as for `transpose-words'."
+  (interactive "*p")
+  (transpose-subr 'c-forward-subword arg))
+
+(defun c-capitalize-subword (arg)
+  "Do the same as `capitalize-word' but on subwords.
+See the command `c-subword-mode' for a description of subwords.
+Optional argument ARG is the same as for `capitalize-word'."
+  (interactive "p")
+  (let ((count (abs arg))
+       (direction (if (< 0 arg) 1 -1)))
+    (dotimes (i count)
+      (when (re-search-forward 
+            (concat "[" c-alpha "]")
+            nil t)
+       (goto-char (match-beginning 0)))
+      (let* ((p (point))
+            (pp (1+ p))
+            (np (c-forward-subword direction)))
+       (upcase-region p pp)
+       (downcase-region pp np)
+       (goto-char np)))))
+
+(defun c-downcase-subword (arg)
+  "Do the same as `downcase-word' but on subwords.
+See the command `c-subword-mode' for a description of subwords.
+Optional argument ARG is the same as for `downcase-word'."
+  (interactive "p")
+  (downcase-region (point) (c-forward-subword arg)))
+
+(defun c-upcase-subword (arg)
+  "Do the same as `upcase-word' but on subwords.
+See the command `c-subword-mode' for a description of subwords.
+Optional argument ARG is the same as for `upcase-word'."
+  (interactive "p")
+  (upcase-region (point) (c-forward-subword arg)))
+
+\f
+;;
+;; Internal functions
+;;
+(defun c-forward-subword-internal ()
+  (if (and
+       (save-excursion 
+        (let ((case-fold-search nil))
+          (re-search-forward 
+           (concat "\\W*\\(\\([" c-upper "]*\\W?\\)[" c-lower c-digit "]*\\)")
+           nil t)))
+       (> (match-end 0) (point))) ; So we don't get stuck at a
+                                 ; "word-constituent" which isn't c-upper,
+                                 ; c-lower or c-digit
+      (goto-char 
+       (cond
+       ((< 1 (- (match-end 2) (match-beginning 2)))
+        (1- (match-end 2)))
+       (t
+        (match-end 0))))
+    (forward-word 1)))
+
+
+(defun c-backward-subword-internal ()
+  (if (save-excursion 
+       (let ((case-fold-search nil)) 
+         (re-search-backward
+          (concat
+           "\\(\\(\\W\\|[" c-lower c-digit "]\\)\\([" c-upper "]+\\W*\\)"
+           "\\|\\W\\w+\\)") 
+          nil t)))
+      (goto-char 
+       (cond 
+       ((and (match-end 3)
+             (< 1 (- (match-end 3) (match-beginning 3)))
+             (not (eq (point) (match-end 3))))
+        (1- (match-end 3)))
+       (t
+        (1+ (match-beginning 0)))))
+    (backward-word 1)))
+
+\f
+(cc-provide 'cc-subword)
+
+;;; arch-tag: 2be9d294-7f30-4626-95e6-9964bb93c7a3
+;;; cc-subword.el ends here
index b6a3c40495737ebc79105bc39f3a6906eabea816..4c5d03c6f4ccd2d70c98670be46c49813a96b3eb 100644 (file)
@@ -1,6 +1,7 @@
 ;;; cc-vars.el --- user customization variables for CC Mode
 
-;; Copyright (C) 1985,1987,1992-2003, 2004, 2005 Free Software Foundation, Inc.
+;; Copyright (C) 1985,1987,1992-2003, 2004, 2005 Free Software
+;; Foundation, Inc.
 
 ;; Authors:    1998- Martin Stjernholm
 ;;             1992-1999 Barry A. Warsaw
@@ -24,7 +25,7 @@
 ;; GNU General Public License for more details.
 
 ;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING.  If not, write to
+;; along with this program; see the file COPYING.  If not, write to
 ;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 ;; Boston, MA 02110-1301, USA.
 
 (cc-require 'cc-defs)
 
 ;; Silence the compiler.
-(cc-bytecomp-defun get-char-table)     ; XEmacs 20+
-(cc-bytecomp-defun char-table-range)   ; Emacs 19+
-(cc-bytecomp-defun char-table-p)       ; Emacs 19+, XEmacs 20+
-
-;; Pull in custom if it exists and is recent enough (the one in Emacs
-;; 19.34 isn't).
-(eval
- (cc-eval-when-compile
-   (condition-case nil
-       (progn
-        (require 'custom)
-        (or (fboundp 'defcustom) (error ""))
-        (require 'widget)
-        '(progn                        ; Compile in the require's.
-           (require 'custom)
-           (require 'widget)))
-     (error
-      (message "Warning: Compiling without Customize support \
-since a (good enough) custom library wasn't found")
-      (cc-bytecomp-defmacro define-widget (name class doc &rest args))
-      (cc-bytecomp-defmacro defgroup (symbol members doc &rest args))
-      (cc-bytecomp-defmacro defcustom (symbol value doc &rest args)
-       `(defvar ,symbol ,value ,doc))
-      (cc-bytecomp-defmacro custom-declare-variable (symbol value doc
-                                                    &rest args)
-       `(defvar ,(eval symbol) ,(eval value) ,doc))
-      nil))))
+(cc-bytecomp-defun get-char-table)     ; XEmacs
+
+(cc-eval-when-compile
+  (require 'custom)
+  (require 'widget))
 
 (cc-eval-when-compile
   ;; Need the function form of `backquote', which isn't standardized
@@ -207,7 +186,6 @@ the value set here overrides the style system (there is a variable
 (defun c-valid-offset (offset)
   "Return non-nil iff OFFSET is a valid offset for a syntactic symbol.
 See `c-offsets-alist'."
-  ;; This function does not do any hidden buffer changes.
   (or (eq offset '+)
       (eq offset '-)
       (eq offset '++)
@@ -216,17 +194,19 @@ See `c-offsets-alist'."
       (eq offset '/)
       (integerp offset)
       (functionp offset)
-      (and (symbolp offset)
-          (or (boundp offset)
-              (fboundp offset)))
+      (and (symbolp offset) (boundp offset))
       (and (vectorp offset)
           (= (length offset) 1)
           (integerp (elt offset 0)))
-      (progn
-       (while (and (consp offset)
-                   (c-valid-offset (car offset)))
-         (setq offset (cdr offset)))
-       (null offset))))
+      (and (consp offset)
+          (not (eq (car offset) 'quote)) ; Detect misquoted lists.
+          (progn
+            (when (memq (car offset) '(first min max add))
+              (setq offset (cdr offset)))
+            (while (and (consp offset)
+                        (c-valid-offset (car offset)))
+              (setq offset (cdr offset)))
+            (null offset)))))
 
 
 \f
@@ -311,6 +291,7 @@ effect in this mode, nor any of the indentation associated variables,
 e.g. `c-special-indent-hook'."
   :type 'boolean
   :group 'c)
+(make-variable-buffer-local 'c-syntactic-indentation)
 
 (defcustom c-syntactic-indentation-in-macros t
   "*Enable syntactic analysis inside macros.
@@ -470,6 +451,7 @@ style comments."
 
 (defcustom-c-stylevar c-comment-prefix-regexp
   '((pike-mode . "//+!?\\|\\**")
+    (awk-mode . "#+")
     (other . "//+\\|\\**"))
   "*Regexp to match the line prefix inside comments.
 This regexp is used to recognize the fill prefix inside comments for
@@ -517,14 +499,17 @@ variable in a mode hook."
            (cons :format "%v"
                  (const :format "IDL   " idl-mode) (regexp :format "%v"))
            (cons :format "%v"
-                 (const :format "Pike  " pike-mode) (regexp :format "%v")))
+                 (const :format "Pike  " pike-mode) (regexp :format "%v"))
+            (cons :format "%v"
+                 (const :format "AWK   " awk-mode) (regexp :format "%v")))
           (cons :format "    %v"
                 (const :format "Other " other) (regexp :format "%v"))))
   :group 'c)
 
 (defcustom-c-stylevar c-doc-comment-style
   '((java-mode . javadoc)
-    (pike-mode . autodoc))
+    (pike-mode . autodoc)
+    (c-mode    . gtkdoc))
   "*Specifies documentation comment style(s) to recognize.
 This is primarily used to fontify doc comments and the markup within
 them, e.g. Javadoc comments.
@@ -534,6 +519,7 @@ comment styles:
 
  javadoc -- Javadoc style for \"/** ... */\" comments (default in Java mode).
  autodoc -- Pike autodoc style for \"//! ...\" comments (default in Pike mode).
+ gtkdoc  -- GtkDoc style for \"/** ... **/\" comments (default in C mode).
 
 The value may also be a list of doc comment styles, in which case all
 of them are recognized simultaneously (presumably with markup cues
@@ -585,6 +571,9 @@ afterwards to redo that work."
            (cons :format "%v"
                  (const :format "Pike  " pike-mode)
                  (c-symbol-list :format "%v"))
+           (cons :format "%v"
+                 (const :format "AWK   " awk-mode)
+                 (c-symbol-list :format "%v"))
            (cons :format "%v"
                  (const :format "Other " other)
                  (c-symbol-list :format "%v")))))
@@ -613,8 +602,8 @@ contexts are:
 (defcustom-c-stylevar c-cleanup-list '(scope-operator)
   "*List of various C/C++/ObjC constructs to \"clean up\".
 The following clean ups only take place when the auto-newline feature
-is turned on, as evidenced by the `/a' or `/ah' appearing next to the
-mode name:
+is turned on, as evidenced by the `/la' appearing next to the mode
+name:
 
  brace-else-brace    -- Clean up \"} else {\" constructs by placing
                         entire construct on a single line.  This clean
@@ -630,21 +619,28 @@ mode name:
                         \"} catch (...) {\" constructs.
  empty-defun-braces  -- Clean up empty defun braces by placing the
                         braces on the same line.  Clean up occurs when
-                       the defun closing brace is typed.
+                        the defun closing brace is typed.
+ one-liner-defun     -- If the code inside a function body is a single
+                        line then remove any newlines between that
+                        line and the defun braces so that the whole
+                        body becomes a single line.
+                        `c-max-one-liner-length' gives the maximum
+                        length allowed for the resulting line.  Clean
+                        up occurs when the closing brace is typed.
  defun-close-semi    -- Clean up the terminating semi-colon on defuns
-                       by placing the semi-colon on the same line as
-                       the closing brace.  Clean up occurs when the
-                       semi-colon is typed.
+                        by placing the semi-colon on the same line as
+                        the closing brace.  Clean up occurs when the
+                        semi-colon is typed.
  list-close-comma    -- Clean up commas following braces in array
                         and aggregate initializers.  Clean up occurs
-                       when the comma is typed.
+                        when the comma is typed.
  scope-operator      -- Clean up double colons which may designate
-                       a C++ scope operator split across multiple
-                       lines.  Note that certain C++ constructs can
-                       generate ambiguous situations.  This clean up
-                       only takes place when there is nothing but
-                       whitespace between colons.  Clean up occurs
-                       when the second colon is typed.
+                        a C++ scope operator split across multiple
+                        lines.  Note that certain C++ constructs can
+                        generate ambiguous situations.  This clean up
+                        only takes place when there is nothing but
+                        whitespace between colons.  Clean up occurs
+                        when the second colon is typed.
 
 The following clean ups always take place when they are on this list,
 regardless of the auto-newline feature, since they typically don't
@@ -654,31 +650,39 @@ involve auto-newline inserted newlines:
                         parenthesis of a function call.  Clean up
                         occurs when the opening parenthesis is typed.
  compact-empty-funcall -- Clean up any space before the function call
-                       opening parenthesis if and only if the
+                        opening parenthesis if and only if the
                         argument list is empty.  This is typically
                         useful together with `space-before-funcall' to
                         get the style \"foo (bar)\" and \"foo()\".
                         Clean up occurs when the closing parenthesis
-                        is typed."
+                        is typed.
+ comment-close-slash -- When a slash is typed after the comment prefix
+                        on a bare line in a c-style comment, the comment
+                        is closed by cleaning up preceding space and
+                        inserting a star if needed."
   :type '(set
-         (const :tag "Put \"} else {\" on one line"
+         (const :tag "Put \"} else {\" on one line (brace-else-brace)"
                 brace-else-brace)
-         (const :tag "Put \"} else if (...) {\" on one line"
+         (const :tag "Put \"} else if (...) {\" on one line (brace-elseif-brace)"
                 brace-elseif-brace)
-         (const :tag "Put \"} catch (...) {\" on one line"
+         (const :tag "Put \"} catch (...) {\" on one line (brace-catch-brace)"
                 brace-catch-brace)
-         (const :tag "Put empty defun braces on one line"
+         (const :tag "Put empty defun braces on one line (empty-defun-braces)"
                 empty-defun-braces)
-         (const :tag "Put \"};\" ending defuns on one line"
+         (const :tag "Put short function bodies on one line (one-liner-defun)"
+                one-liner-defun)
+         (const :tag "Put \"};\" ending defuns on one line (defun-close-semi)"
                 defun-close-semi)
-         (const :tag "Put \"},\" in aggregates on one line"
+         (const :tag "Put \"},\" in aggregates on one line (list-close-comma)"
                 list-close-comma)
-         (const :tag "Put C++ style \"::\" on one line"
+         (const :tag "Put C++ style \"::\" on one line (scope-operator)"
                 scope-operator)
-         (const :tag "Put a space before funcall parens, e.g. \"foo (bar)\""
+         (const :tag "Put a space before funcall parens, e.g. \"foo (bar)\" (space-before-funcall)"
                 space-before-funcall)
-         (const :tag "Remove space before empty funcalls, e.g. \"foo()\""
-                compact-empty-funcall))
+         (const :tag "Remove space before empty funcalls, e.g. \"foo()\" (compact-empty-funcall)"
+                compact-empty-funcall)
+         (const :tag "Make / on a bare line of a C-style comment close it (comment-close-slash)"
+                comment-close-slash))
   :group 'c)
 
 (defcustom-c-stylevar c-hanging-braces-alist '((brace-list-open)
@@ -751,6 +755,12 @@ syntactic context for the brace line."
              inexpr-class-open inexpr-class-close)))
     :group 'c)
 
+(defcustom c-max-one-liner-length 80
+  "Maximum length of line that clean-up \"one-liner-defun\" will compact to.
+Zero or nil means no limit."
+  :type 'integer
+  :group 'c)
+
 (defcustom-c-stylevar c-hanging-colons-alist nil
   "*Controls the insertion of newlines before and after certain colons.
 This variable contains an association list with elements of the
@@ -832,35 +842,40 @@ space."
   :group 'c)
 
 (defcustom c-require-final-newline
-  ;; C and C++ mandates that all nonempty files should end with a
+  ;; C and C++ mandate that all nonempty files should end with a
   ;; newline.  Objective-C refers to C for all things it doesn't
-  ;; specify, so the same holds there.  The other languages does not
+  ;; specify, so the same holds there.  The other languages do not
   ;; require it (at least not explicitly in a normative text).
   '((c-mode    . t)
     (c++-mode  . t)
     (objc-mode . t))
-  "*Controls `require-final-newline' in C-related major modes.
-The value is an association list specifying, for each specific mode,
-whether to override `require-final-newline'.  If the cdr of the element
-is non-nil, that means to use `mode-require-final-newline' instead."
+  "*Controls whether a final newline is ensured when the file is saved.
+The value is an association list that for each language mode specifies
+the value to give to `require-final-newline' at mode initialization;
+see that variable for details about the value.  If a language isn't
+present on the association list, CC Mode won't touch
+`require-final-newline' in buffers for that language."
   :type `(set (cons :format "%v"
                    (const :format "C     " c-mode)
-                   (const t))
+                   (symbol :format "%v" :value ,require-final-newline))
              (cons :format "%v"
                    (const :format "C++   " c++-mode)
-                   (const t))
+                   (symbol :format "%v" :value ,require-final-newline))
              (cons :format "%v"
                    (const :format "ObjC  " objc-mode)
-                   (const t))
+                   (symbol :format "%v" :value ,require-final-newline))
              (cons :format "%v"
                    (const :format "Java  " java-mode)
-                   (const t))
+                   (symbol :format "%v" :value ,require-final-newline))
              (cons :format "%v"
                    (const :format "IDL   " idl-mode)
-                   (const t))
+                   (symbol :format "%v" :value ,require-final-newline))
              (cons :format "%v"
                    (const :format "Pike  " pike-mode)
-                   (const t)))
+                   (symbol :format "%v" :value ,require-final-newline))
+             (cons :format "%v"
+                   (const :format "AWK   " awk-mode)
+                   (symbol :format "%v" :value ,require-final-newline)))
   :group 'c)
 
 (defcustom c-electric-pound-behavior nil
@@ -892,7 +907,8 @@ this variable to nil."
   :type 'integer
   :group 'c)
 
-(defcustom c-default-style '((java-mode . "java") (other . "gnu"))
+(defcustom c-default-style '((java-mode . "java") (awk-mode . "awk")
+                            (other . "gnu"))
   "*Style which gets installed by default when a file is visited.
 
 The value of this variable can be any style defined in
@@ -926,6 +942,8 @@ can always override the use of `c-default-style' by making calls to
                  (const :format "IDL   " idl-mode) (string :format "%v"))
            (cons :format "%v"
                  (const :format "Pike  " pike-mode) (string :format "%v"))
+           (cons :format "%v"
+                 (const :format "AWK   " awk-mode) (string :format "%v"))
            (cons :format "%v"
                  (const :format "Other " other) (string :format "%v"))))
   :group 'c)
@@ -939,170 +957,170 @@ can always override the use of `c-default-style' by making calls to
 ;; symbol and continue searching.
 (c-set-stylevar-fallback 'c-offsets-alist
      '((string                . c-lineup-dont-change)
-       ;; Relpos: Beg of previous line.
+       ;; Anchor pos: Beg of previous line.
        (c                     . c-lineup-C-comments)
-       ;; Relpos: Beg of the comment.
+       ;; Anchor pos: Beg of the comment.
        (defun-open            . 0)
-       ;; Relpos: When inside a class: Boi at the func decl start.
+       ;; Anchor pos: When inside a class: Boi at the func decl start.
        ;; When at top level: Bol at the func decl start.  When inside
        ;; a code block (only possible in Pike): At the func decl
        ;; start(*).
        (defun-close           . 0)
-       ;; Relpos: At the defun block open if it's at boi, otherwise
-       ;; boi at the func decl start.
+       ;; Anchor pos: At the defun block open if it's at boi,
+       ;; otherwise boi at the func decl start.
        (defun-block-intro     . +)
-       ;; Relpos: At the block open(*).
+       ;; Anchor pos: At the block open(*).
        (class-open            . 0)
-       ;; Relpos: Boi at the class decl start.
+       ;; Anchor pos: Boi at the class decl start.
        (class-close           . 0)
-       ;; Relpos: Boi at the class decl start.
+       ;; Anchor pos: Boi at the class decl start.
        (inline-open           . +)
-       ;; Relpos: None for functions (inclass got the relpos then),
-       ;; boi at the lambda start for lambdas.
+       ;; Anchor pos: None for functions (inclass got the relpos
+       ;; then), boi at the lambda start for lambdas.
        (inline-close          . 0)
-       ;; Relpos: Inexpr functions: At the lambda block open if it's
-       ;; at boi, else at the statement(*) at boi of the start of the
-       ;; lambda construct.  Otherwise: At the inline block open if
-       ;; it's at boi, otherwise boi at the func decl start.
+       ;; Anchor pos: Inexpr functions: At the lambda block open if
+       ;; it's at boi, else at the statement(*) at boi of the start of
+       ;; the lambda construct.  Otherwise: At the inline block open
+       ;; if it's at boi, otherwise boi at the func decl start.
        (func-decl-cont        . +)
-       ;; Relpos: Boi at the func decl start.
+       ;; Anchor pos: Boi at the func decl start.
        (knr-argdecl-intro     . +)
-       ;; Relpos: Boi at the topmost intro line.
+       ;; Anchor pos: Boi at the topmost intro line.
        (knr-argdecl           . 0)
-       ;; Relpos: At the beginning of the first K&R argdecl.
+       ;; Anchor pos: At the beginning of the first K&R argdecl.
        (topmost-intro         . 0)
-       ;; Relpos: Bol at the last line of previous construct.
+       ;; Anchor pos: Bol at the last line of previous construct.
        (topmost-intro-cont    . c-lineup-topmost-intro-cont)
-       ;; Relpos: Boi at the topmost intro line.
+       ;; Anchor pos: Boi at the topmost intro line.
        (member-init-intro     . +)
-       ;; Relpos: Boi at the func decl arglist open.
+       ;; Anchor pos: Boi at the func decl arglist open.
        (member-init-cont      . c-lineup-multi-inher)
-       ;; Relpos: Beg of the first member init.
+       ;; Anchor pos: Beg of the first member init.
        (inher-intro           . +)
-       ;; Relpos: Boi at the class decl start.
+       ;; Anchor pos: Boi at the class decl start.
        (inher-cont            . c-lineup-multi-inher)
-       ;; Relpos: Java: At the implements/extends keyword start.
+       ;; Anchor pos: Java: At the implements/extends keyword start.
        ;; Otherwise: At the inher start colon, or boi at the class
        ;; decl start if the first inherit clause hangs and it's not a
        ;; func-local inherit clause (when does that occur?).
        (block-open            . 0)
-       ;; Relpos: Inexpr statement: At the statement(*) at boi of the
-       ;; start of the inexpr construct.  Otherwise: None.
+       ;; Anchor pos: Inexpr statement: At the statement(*) at boi of
+       ;; the start of the inexpr construct.  Otherwise: None.
        (block-close           . 0)
-       ;; Relpos: Inexpr statement: At the inexpr block open if it's
-       ;; at boi, else at the statement(*) at boi of the start of the
-       ;; inexpr construct.  Block hanging on a case/default label: At
-       ;; the closest preceding label that starts at boi.  Otherwise:
-       ;; At the block open(*).
+       ;; Anchor pos: Inexpr statement: At the inexpr block open if
+       ;; it's at boi, else at the statement(*) at boi of the start of
+       ;; the inexpr construct.  Block hanging on a case/default
+       ;; label: At the closest preceding label that starts at boi.
+       ;; Otherwise: At the block open(*).
        (brace-list-open       . 0)
-       ;; Relpos: Boi at the brace list decl start, but a starting
+       ;; Anchor pos: Boi at the brace list decl start, but a starting
        ;; "typedef" token is ignored.
        (brace-list-close      . 0)
-       ;; Relpos: At the brace list decl start(*).
+       ;; Anchor pos: At the brace list decl start(*).
        (brace-list-intro      . +)
-       ;; Relpos: At the brace list decl start(*).
+       ;; Anchor pos: At the brace list decl start(*).
        (brace-list-entry      . 0)
-       ;; Relpos: At the first non-ws char after the open paren if the
-       ;; first token is on the same line, otherwise boi at that
+       ;; Anchor pos: At the first non-ws char after the open paren if
+       ;; the first token is on the same line, otherwise boi at that
        ;; token.
        (brace-entry-open      . 0)
-       ;; Relpos: Same as brace-list-entry.
+       ;; Anchor pos: Same as brace-list-entry.
        (statement             . 0)
-       ;; Relpos: After a `;' in the condition clause of a for
+       ;; Anchor pos: After a `;' in the condition clause of a for
        ;; statement: At the first token after the starting paren.
        ;; Otherwise: At the preceding statement(*).
        (statement-cont        . +)
-       ;; Relpos: After the first token in the condition clause of a
-       ;; for statement: At the first token after the starting paren.
-       ;; Otherwise: At the containing statement(*).
+       ;; Anchor pos: After the first token in the condition clause of
+       ;; a for statement: At the first token after the starting
+       ;; paren.  Otherwise: At the containing statement(*).
        (statement-block-intro . +)
-       ;; Relpos: In inexpr statement block: At the inexpr block open
-       ;; if it's at boi, else at the statement(*) at boi of the start
-       ;; of the inexpr construct.  In a block hanging on a
+       ;; Anchor pos: In inexpr statement block: At the inexpr block
+       ;; open if it's at boi, else at the statement(*) at boi of the
+       ;; start of the inexpr construct.  In a block hanging on a
        ;; case/default label: At the closest preceding label that
        ;; starts at boi.  Otherwise: At the start of the containing
        ;; block(*).
        (statement-case-intro  . +)
-       ;; Relpos: At the case/default label(*).
+       ;; Anchor pos: At the case/default label(*).
        (statement-case-open   . 0)
-       ;; Relpos: At the case/default label(*).
+       ;; Anchor pos: At the case/default label(*).
        (substatement          . +)
-       ;; Relpos: At the containing statement(*).
+       ;; Anchor pos: At the containing statement(*).
        (substatement-open     . +)
-       ;; Relpos: At the containing statement(*).
+       ;; Anchor pos: At the containing statement(*).
        (substatement-label    . 2)
-       ;; Relpos: At the containing statement(*).
+       ;; Anchor pos: At the containing statement(*).
        (case-label            . 0)
-       ;; Relpos: At the start of the switch block(*).
+       ;; Anchor pos: At the start of the switch block(*).
        (access-label          . -)
-       ;; Relpos: Same as inclass.
+       ;; Anchor pos: Same as inclass.
        (label                 . 2)
-       ;; Relpos: At the start of the containing block(*).
+       ;; Anchor pos: At the start of the containing block(*).
        (do-while-closure      . 0)
-       ;; Relpos: At the corresponding while statement(*).
+       ;; Anchor pos: At the corresponding while statement(*).
        (else-clause           . 0)
-       ;; Relpos: At the corresponding if statement(*).
+       ;; Anchor pos: At the corresponding if statement(*).
        (catch-clause          . 0)
-       ;; Relpos: At the previous try or catch statement clause(*).
+       ;; Anchor pos: At the previous try or catch statement clause(*).
        (comment-intro         . (c-lineup-knr-region-comment c-lineup-comment))
-       ;; Relpos: None.
+       ;; Anchor pos: None.
        (arglist-intro         . +)
-       ;; Relpos: Boi at the open paren, or at the first non-ws after
-       ;; the open paren of the surrounding sexp, whichever is later.
+       ;; Anchor pos: At the containing statement(*).
+       ;; 2nd pos: At the open paren.
        (arglist-cont          . (c-lineup-gcc-asm-reg 0))
-       ;; Relpos: At the first token after the open paren.
+       ;; Anchor pos: At the first token after the open paren.
        (arglist-cont-nonempty . (c-lineup-gcc-asm-reg c-lineup-arglist))
-       ;; Relpos: At the containing statement(*).
+       ;; Anchor pos: At the containing statement(*).
        ;; 2nd pos: At the open paren.
        (arglist-close         . +)
-       ;; Relpos: At the containing statement(*).
+       ;; Anchor pos: At the containing statement(*).
        ;; 2nd pos: At the open paren.
        (stream-op             . c-lineup-streamop)
-       ;; Relpos: Boi at the first stream op in the statement.
+       ;; Anchor pos: Boi at the first stream op in the statement.
        (inclass               . +)
-       ;; Relpos: At the class open brace if it's at boi, otherwise
-       ;; boi at the class decl start.
+       ;; Anchor pos: At the class open brace if it's at boi,
+       ;; otherwise boi at the class decl start.
        (cpp-macro             . [0])
-       ;; Relpos: None.
+       ;; Anchor pos: None.
        (cpp-macro-cont        . +)
-       ;; Relpos: At the macro start (always at boi).
+       ;; Anchor pos: At the macro start (always at boi).
        (cpp-define-intro      . (c-lineup-cpp-define +))
-       ;; Relpos: None.
+       ;; Anchor pos: None.
        (friend                . 0)
-       ;; Relpos: None.
+       ;; Anchor pos: None.
        (objc-method-intro     . [0])
-       ;; Relpos: Boi.
+       ;; Anchor pos: Boi.
        (objc-method-args-cont . c-lineup-ObjC-method-args)
-       ;; Relpos: At the method start (always at boi).
+       ;; Anchor pos: At the method start (always at boi).
        (objc-method-call-cont . c-lineup-ObjC-method-call)
-       ;; Relpos: At the open bracket.
+       ;; Anchor pos: At the open bracket.
        (extern-lang-open      . 0)
        (namespace-open        . 0)
        (module-open           . 0)
        (composition-open      . 0)
-       ;; Relpos: Boi at the extern/namespace/etc keyword.
+       ;; Anchor pos: Boi at the extern/namespace/etc keyword.
        (extern-lang-close     . 0)
        (namespace-close       . 0)
        (module-close          . 0)
        (composition-close     . 0)
-       ;; Relpos: Boi at the corresponding extern/namespace/etc keyword.
+       ;; Anchor pos: Boi at the corresponding extern/namespace/etc keyword.
        (inextern-lang         . +)
        (innamespace           . +)
        (inmodule              . +)
        (incomposition         . +)
-       ;; Relpos: At the extern/namespace/etc block open brace if it's
-       ;; at boi, otherwise boi at the keyword.
+       ;; Anchor pos: At the extern/namespace/etc block open brace if
+       ;; it's at boi, otherwise boi at the keyword.
        (template-args-cont    . (c-lineup-template-args +))
-       ;; Relpos: Boi at the decl start.  This might be changed; the
-       ;; logical position is clearly the opening '<'.
+       ;; Anchor pos: Boi at the decl start.  This might be changed;
+       ;; the logical position is clearly the opening '<'.
        (inlambda              . c-lineup-inexpr-block)
-       ;; Relpos: None.
+       ;; Anchor pos: None.
        (lambda-intro-cont     . +)
-       ;; Relpos: Boi at the lambda start.
+       ;; Anchor pos: Boi at the lambda start.
        (inexpr-statement      . +)
-       ;; Relpos: None.
+       ;; Anchor pos: None.
        (inexpr-class          . +)
-       ;; Relpos: None.
+       ;; Anchor pos: None.
        ))
 (defcustom c-offsets-alist nil
   "Association list of syntactic element symbols and indentation offsets.
@@ -1112,50 +1130,66 @@ As described below, each cons cell in this list has the form:
 
 When a line is indented, CC Mode first determines the syntactic
 context of it by generating a list of symbols called syntactic
-elements.  This list can contain more than one syntactic element and
-the global variable `c-syntactic-context' contains the context list
-for the line being indented.  Each element in this list is actually a
-cons cell of the syntactic symbol and a buffer position.  This buffer
-position is called the relative indent point for the line.  Some
-syntactic symbols may not have a relative indent point associated with
-them.
-
-After the syntactic context list for a line is generated, CC Mode
-calculates the absolute indentation for the line by looking at each
-syntactic element in the list.  It compares the syntactic element
-against the SYNTACTIC-SYMBOL's in `c-offsets-alist'.  When it finds a
-match, it adds the OFFSET to the column of the relative indent point.
-The sum of this calculation for each element in the syntactic list is
+elements.  The global variable `c-syntactic-context' is bound to the
+that list.  Each element in the list is in turn a list where the first
+element is a syntactic symbol which tells what kind of construct the
+indentation point is located within.  More elements in the syntactic
+element lists are optional.  If there is one more and it isn't nil,
+then it's the anchor position for that construct.
+
+After generating the syntactic context for the line, CC Mode
+calculates the absolute indentation: First the base indentation is
+found by using the anchor position for the first syntactic element
+that provides one.  If none does, zero is used as base indentation.
+Then CC Mode looks at each syntactic element in the context in turn.
+It compares the car of the syntactic element against the
+SYNTACTIC-SYMBOL's in `c-offsets-alist'.  When it finds a match, it
+adds OFFSET to the base indentation.  The sum of this calculation is
 the absolute offset for line being indented.
 
 If the syntactic element does not match any in the `c-offsets-alist',
 the element is ignored.
 
-If OFFSET is nil, the syntactic element is ignored in the offset
-calculation.
+OFFSET can specify an offset in several different ways:
+
+  If OFFSET is nil then it's ignored.
+
+  If OFFSET is an integer then it's used as relative offset, i.e. it's
+  added to the base indentation.
 
-If OFFSET is an integer, it's added to the relative indent.
+  If OFFSET is one of the symbols `+', `-', `++', `--', `*', or `/'
+  then a positive or negative multiple of `c-basic-offset' is added to
+  the base indentation; 1, -1, 2, -2, 0.5, and -0.5, respectively.
 
-If OFFSET is one of the symbols `+', `-', `++', `--', `*', or `/', a
-positive or negative multiple of `c-basic-offset' is added; 1, -1, 2,
--2, 0.5, and -0.5, respectively.
+  If OFFSET is a symbol with a value binding then that value, which
+  must be an integer, is used as relative offset.
 
-If OFFSET is a vector, it's first element, which must be an integer,
-is used as an absolute indentation column.  This overrides all
-relative offsets.  If there are several syntactic elements which
-evaluates to absolute indentation columns, the first one takes
-precedence.  You can see in which order CC Mode combines the syntactic
-elements in a certain context by using \\[c-show-syntactic-information] on the line.
+  If OFFSET is a vector then it's first element, which must be an
+  integer, is used as an absolute indentation column.  This overrides
+  the previous base indentation and the relative offsets applied to
+  it, and it becomes the new base indentation.
 
-If OFFSET is a function, it's called with a single argument
-containing the cons of the syntactic element symbol and the relative
-indent point.  The return value from the function is then
-reinterpreted as an OFFSET value.
+  If OFFSET is a function or a lambda expression then it's called with
+  a single argument containing the cons of the syntactic symbol and
+  the anchor position (or nil if there is none).  The return value
+  from the function is then reinterpreted as an offset specification.
 
-If OFFSET is a list, it's recursively evaluated using the semantics
-described above.  The first element of the list to return a non-nil
-value succeeds.  If none of the elements returns a non-nil value, the
-syntactic element is ignored.
+  If OFFSET is a list then its elements are evaluated recursively as
+  offset specifications.  If the first element is any of the symbols
+  below then it isn't evaluated but instead specifies how the
+  remaining offsets in the list should be combined.  If it's something
+  else then the list is combined according the method `first'.  The
+  valid combination methods are:
+
+  `first' -- Use the first offset (that doesn't evaluate to nil).
+  `min'   -- Use the minimum of all the offsets.  All must be either
+             relative or absolute - they can't be mixed.
+  `max'   -- Use the maximum of all the offsets.  All must be either
+             relative or absolute - they can't be mixed.
+  `add'   -- Add all the evaluated offsets together.  Exactly one of
+             them may be absolute, in which case the result is
+             absolute.  Any relative offsets that preceded the
+             absolute one in the list will be ignored in that case.
 
 `c-offsets-alist' is a style variable.  This means that the offsets on
 this variable are normally taken from the style system in CC Mode
@@ -1336,6 +1370,11 @@ The list of variables to buffer localize are:
   :type 'hook
   :group 'c)
 
+(defcustom awk-mode-hook nil
+  "*Hook called by `awk-mode'."
+  :type 'hook
+  :group 'c)
+
 (defcustom c-mode-common-hook nil
   "*Hook called by all CC Mode modes for common initializations."
   :type 'hook
@@ -1380,16 +1419,17 @@ working due to this change.")
   :args '((const :tag "none" nil)
          (repeat :tag "types" regexp)))
 
-(eval-and-compile
-  ;; XEmacs 19 evaluates this at compile time below, while most other
-  ;; versions delays the evaluation until the package is loaded.
-  (defun c-make-font-lock-extra-types-blurb (mode1 mode2 example)
-    (concat "\
+(defun c-make-font-lock-extra-types-blurb (mode1 mode2 example)
+  (concat "\
 *List of extra types (aside from the type keywords) to recognize in "
 mode1 " mode.
 Each list item should be a regexp matching a single identifier.
 " example "
 
+Note that items on this list that don't include any regexp special
+characters are automatically optimized using `regexp-opt', so you
+should not use `regexp-opt' explicitly to build regexps here.
+
 On decoration level 3 (and higher, where applicable), a method is used
 that finds most types and declarations by syntax alone.  This variable
 is still used as a first step, but other types are recognized
@@ -1401,43 +1441,58 @@ initialized.  If you change it later you have to reinitialize CC Mode
 by doing \\[" mode2 "].
 
 Despite the name, this variable is not only used for font locking but
-also elsewhere in CC Mode to tell types from other identifiers.")))
+also elsewhere in CC Mode to tell types from other identifiers."))
 
 ;; Note: Most of the variables below are also defined in font-lock.el
-;; in older versions in Emacs, so depending on the load order we might
+;; in older versions of Emacs, so depending on the load order we might
 ;; not install the values below.  There's no kludge to cope with this
 ;; (as opposed to the *-font-lock-keywords-* variables) since the old
 ;; values work fairly well anyway.
 
 (defcustom c-font-lock-extra-types
-  '("FILE" "\\sw+_t"
-    "bool" "complex" "imaginary"       ; Defined in C99.
+  '("\\sw+_t"
+    ;; Defined in C99:
+    "bool" "complex" "imaginary"
+    ;; Standard library types (except those matched by the _t pattern):
+    "FILE" "lconv" "tm" "va_list" "jmp_buf"
     ;; I do not appreciate the following very Emacs-specific luggage
     ;; in the default value, but otoh it can hardly get in the way for
     ;; other users, and removing it would cause unnecessary grief for
     ;; the old timers that are used to it. /mast
     "Lisp_Object")
   (c-make-font-lock-extra-types-blurb "C" "c-mode"
-"For example, a value of (\"FILE\" \"\\\\sw+_t\") means the word FILE
-and words ending in _t are treated as type names.")
+"For example, a value of (\"FILE\" \"\\\\sw+_t\") means the word \"FILE\"
+and words ending in \"_t\" are treated as type names.")
   :type 'c-extra-types-widget
   :group 'c)
 
 (defcustom c++-font-lock-extra-types
   '("\\sw+_t"
-    "\\([iof]\\|str\\)+stream\\(buf\\)?" "ios"
+    ;; C library types (except those matched by the _t pattern):
+    "FILE" "lconv" "tm" "va_list" "jmp_buf"
+    ;; Some standard C++ types that came from font-lock.el.
+    ;; Experienced C++ users says there's no clear benefit in
+    ;; extending this to all the types in the standard library, at
+    ;; least not when they'll be recognized without "std::" too.
+    "istream" "istreambuf"
+    "ostream" "ostreambuf"
+    "ifstream" "ofstream" "fstream"
+    "strstream" "strstreambuf" "istrstream" "ostrstream"
+    "ios"
     "string" "rope"
     "list" "slist"
     "deque" "vector" "bit_vector"
     "set" "multiset"
     "map" "multimap"
-    "hash\\(_\\(m\\(ap\\|ulti\\(map\\|set\\)\\)\\|set\\)\\)?"
+    "hash"
+    "hash_set" "hash_multiset"
+    "hash_map" "hash_multimap"
     "stack" "queue" "priority_queue"
     "type_info"
     "iterator" "const_iterator" "reverse_iterator" "const_reverse_iterator"
     "reference" "const_reference")
   (c-make-font-lock-extra-types-blurb "C++" "c++-mode"
-"For example, a value of (\"string\") means the word string is treated
+"For example, a value of (\"string\") means the word \"string\" is treated
 as a type name.")
   :type 'c-extra-types-widget
   :group 'c)
@@ -1499,40 +1554,49 @@ Note that file offset settings are applied after file style settings
 as designated in the variable `c-file-style'.")
 (make-variable-buffer-local 'c-file-offsets)
 
-;; It isn't possible to specify a docstring without specifying an
-;; initial value with `defvar', so the following two variables have
-;; only doc comments even though they are part of the API.  It's
-;; really good not to have an initial value for variables like these
-;; that always should be dynamically bound, so it's worth the
-;; inconvenience.
+;; It isn't possible to specify a doc-string without specifying an
+;; initial value with `defvar', so the following two variables have been
+;; given doc-strings by setting the property `variable-documentation'
+;; directly.  C-h v will read this documentation only for versions of GNU
+;; Emacs from 22.1.  It's really good not to have an initial value for
+;; variables like these that always should be dynamically bound, so it's
+;; worth the inconvenience.
 
 (cc-bytecomp-defvar c-syntactic-context)
 (defvar c-syntactic-context)
-;; Variable containing the syntactic analysis list during indentation.
-;; It is a list with one element for each found syntactic symbol.  See
-;; `c-syntactic-element' for further info.
-;;
-;; This is always bound dynamically.  It should never be set
-;; statically (e.g. with `setq').
+(put 'c-syntactic-context 'variable-documentation
+  "Variable containing the syntactic analysis list for a line of code.
+
+It is a list with one element for each syntactic symbol pertinent to the
+line, for example \"((defun-block-intro 1) (comment-intro))\".
+
+It is dynamically bound when calling \(i) a brace hanging \"action
+function\"; \(ii) a semicolon/comma hanging \"criteria function\"; \(iii) a
+\"line-up function\"; \(iv) a c-special-indent-hook function.  It is also
+used internally by CC Mode.
+
+c-syntactic-context is always bound dynamically.  It must NEVER be set
+statically (e.g. with `setq').")
+
 
 (cc-bytecomp-defvar c-syntactic-element)
 (defvar c-syntactic-element)
-;; Variable containing the info regarding the current syntactic
-;; element during calls to the lineup functions.  The value is one of
-;; the elements in the list in `c-syntactic-context' and is a list
-;; with the symbol name in the first position, followed by zero or
-;; more elements containing any additional info associated with the
-;; syntactic symbol.  There are accessor functions `c-langelem-sym',
-;; `c-langelem-pos', `c-langelem-col', and `c-langelem-2nd-pos' to
-;; access the list.
-;;
-;; Specifically, the element returned by `c-langelem-pos' is the
-;; relpos (a.k.a. anchor position), or nil if there isn't any.  See
-;; the comments in the `c-offsets-alist' variable for more detailed
-;; info about the data each syntactic symbol provides.
-;; 
-;; This is always bound dynamically.  It should never be set
-;; statically (e.g. with `setq').
+(put 'c-syntactic-element 'variable-documentation
+     "Variable containing the current syntactic element during calls to
+the lineup functions.  The value is one of the elements in the list in
+`c-syntactic-context' and is a list with the symbol name in the first
+position, followed by zero or more elements containing any additional
+info associated with the syntactic symbol.  There are accessor functions
+`c-langelem-sym', `c-langelem-pos', `c-langelem-col', and
+`c-langelem-2nd-pos' to access the list.
+
+Specifically, the element returned by `c-langelem-pos' is the anchor
+position, or nil if there isn't any.  See the comments in the
+`c-offsets-alist' variable and the CC Mode manual for more detailed info
+about the data each syntactic symbol provides.
+
+This is always bound dynamically.  It should never be set
+statically (e.g. with `setq').")
 
 (defvar c-indentation-style nil
   "Name of the currently installed style.
@@ -1543,6 +1607,29 @@ Don't change this directly; call `c-set-style' instead.")
 Set from `c-comment-prefix-regexp' at mode initialization.")
 (make-variable-buffer-local 'c-current-comment-prefix)
 
+;; N.B. The next three variables are initialized in
+;; c-setup-paragraph-variables.  Their initializations here are "just in
+;; case".  ACM, 2004/2/15.  They are NOT buffer local (yet?).
+(defvar c-string-par-start
+;;   (concat "\\(" (default-value 'paragraph-start) "\\)\\|[ \t]*\\\\$")
+  "\f\\|[ \t]*\\\\?$"
+  "Value of paragraph-start used when scanning strings.
+It treats escaped EOLs as whitespace.")
+
+(defvar c-string-par-separate
+  ;; (concat "\\(" (default-value 'paragraph-separate) "\\)\\|[ \t]*\\\\$")
+  "[ \t\f]*\\\\?$"
+  "Value of paragraph-separate used when scanning strings.
+It treats escaped EOLs as whitespace.")
+
+(defvar c-sentence-end-with-esc-eol
+  (concat "\\(\\(" (c-default-value-sentence-end) "\\)"
+               ;; N.B.:  "$" would be illegal when not enclosed like "\\($\\)".
+               "\\|" "[.?!][]\"')}]* ?\\\\\\($\\)[ \t\n]*"
+               "\\)")
+  "Value used like sentence-end used when scanning strings.
+It treats escaped EOLs as whitespace.")
+
 \f
 (cc-provide 'cc-vars)