diff lisp/progmodes/cc-engine.el @ 44728:7a3ac6c387fe

CC Mode update to version 5.29. This is for testing; it's not a released version.
author Martin Stjernholm <mast@lysator.liu.se>
date Mon, 22 Apr 2002 00:35:36 +0000
parents 4733cde26cbb
children 11c11cb2b8a8
line wrap: on
line diff
--- a/lisp/progmodes/cc-engine.el	Sun Apr 21 18:21:47 2002 +0000
+++ b/lisp/progmodes/cc-engine.el	Mon Apr 22 00:35:36 2002 +0000
@@ -25,12 +25,22 @@
 ;; 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
+;; along with GNU Emacs; see the file COPYING.  If not, write to
 ;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 ;; Boston, MA 02111-1307, USA.
 
 ;;; Commentary:
 
+;; The functions which have docstring documentation can be considered
+;; part of an API which other packages can use in CC Mode buffers.
+;; Otoh, undocumented functions and functions with the documentation
+;; in comments are considered purely internal and can change semantics
+;; or even disappear in the future.
+;;
+;; (This policy applies to CC Mode as a whole, not just this file.  It
+;; probably also applies to many other Emacs packages, but here it's
+;; clearly spelled out.)
+
 ;;; Code:
 
 (eval-when-compile
@@ -49,8 +59,18 @@
 (cc-bytecomp-defun buffer-syntactic-context) ; XEmacs
 
 
-(defvar c-state-cache nil)
+(defun c-calculate-state (arg prevstate)
+  ;; Calculate the new state of PREVSTATE, t or nil, based on arg. If
+  ;; arg is nil or zero, toggle the state. If arg is negative, turn
+  ;; the state off, and if arg is positive, turn the state on
+  (if (or (not arg)
+	  (zerop (setq arg (prefix-numeric-value arg))))
+      (not prevstate)
+    (> arg 0)))
+
+
 (defvar c-in-literal-cache t)
+(defvar c-parsing-error nil)
 
 ;; KLUDGE ALERT: c-maybe-labelp is used to pass information between
 ;; c-crosses-statement-barrier-p and c-beginning-of-statement-1.  A
@@ -58,285 +78,657 @@
 ;; the byte compiler.
 (defvar c-maybe-labelp nil)
 
-;; WARNING WARNING WARNING
-;;
-;; Be *exceptionally* careful about modifications to this function!
-;; Much of CC Mode depends on this Doing The Right Thing.  If you
-;; break it you will be sorry.  If you think you know how this works,
-;; you probably don't.  No human on Earth does! :-)
-;;
-;; WARNING WARNING WARNING
+;; Macros used internally in c-beginning-of-statement-1 for the
+;; automaton actions.
+(defmacro c-bos-push-state ()
+  '(setq stack (cons (cons state saved-pos)
+		     stack)))
+(defmacro c-bos-pop-state (&optional do-if-done)
+  `(if (setq state (car (car stack))
+	     saved-pos (cdr (car stack))
+	     stack (cdr stack))
+       t
+     ,do-if-done
+     (throw 'loop nil)))
+(defmacro c-bos-pop-state-and-retry ()
+  '(throw 'loop (setq state (car (car stack))
+		      saved-pos (cdr (car stack))
+		      ;; Throw nil if stack is empty, else throw non-nil.
+		      stack (cdr stack))))
+(defmacro c-bos-save-pos ()
+  '(setq saved-pos (vector pos tok ptok pptok)))
+(defmacro c-bos-restore-pos ()
+  '(unless (eq (elt saved-pos 0) start)
+     (setq pos (elt saved-pos 0)
+	   tok (elt saved-pos 1)
+	   ptok (elt saved-pos 2)
+	   pptok (elt saved-pos 3))
+     (goto-char pos)
+     (setq sym nil)))
+(defmacro c-bos-save-error-info (missing got)
+  `(setq saved-pos (vector pos ,missing ,got)))
+(defmacro c-bos-report-error ()
+  '(unless noerror
+     (setq c-parsing-error
+	   (format "No matching `%s' found for `%s' on line %d"
+		   (elt saved-pos 1)
+		   (elt saved-pos 2)
+		   (1+ (count-lines (point-min)
+				    (c-point 'bol (elt saved-pos 0))))))))
+
+(defun c-beginning-of-statement-1 (&optional lim ignore-labels
+					     noerror comma-delim)
+  "Move to the start of the current statement or declaration, or to
+the previous one if already at the beginning of one.  Only
+statements/declarations on the same level are considered, i.e. don't
+move into or out of sexps (not even normal expression parentheses).
+
+Stop at statement continuations like \"else\", \"catch\", \"finally\"
+and the \"while\" in \"do ... while\" if the start point is within
+them.  If starting at such a continuation, move to the 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.
+
+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
+statement starts found in it, stop at the first token of the content
+in the macro, i.e. the expression of an \"#if\" or the start of the
+definition in a \"#define\".  Also stop at start of macros before
+leaving them.
+
+Return 'label if stopped at a label, 'same if stopped at the beginning
+of the current statement, 'up if stepped to a containing statement,
+'previous if stepped to a preceding statement, 'beginning if stepped
+from a statement continuation clause to its start clause, or 'macro if
+stepped to a macro start.  Note that 'same and not 'label is returned
+if stopped at the same label without crossing the colon character.
+
+LIM may be given to limit the search.  If the search hits the limit,
+point will be left at the closest following token, or at the start
+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."
 
-(defun c-beginning-of-statement-1 (&optional lim)
-  ;; move to the start of the current statement, or the previous
-  ;; statement if already at the beginning of one.
-  (let ((firstp t)
-	(substmt-p t)
-	donep c-in-literal-cache saved
-	(last-begin (point)))
-    ;; first check for bare semicolon
-    (if (and (progn (c-backward-syntactic-ws lim)
-		    (eq (char-before) ?\;))
-	     (c-safe (progn (forward-char -1)
-			    (setq saved (point))
-			    t))
-	     (progn (c-backward-syntactic-ws lim)
-		    (memq (char-before) '(?\; ?{ ?:)))
-	     )
-	(setq last-begin saved)
-      (goto-char last-begin)
-      (while (not donep)
-	;; stop at beginning of buffer
-	(if (bobp) (setq donep t)
-	  ;; go backwards one balanced expression, but be careful of
-	  ;; unbalanced paren being reached
-	  (if (not (c-safe (progn (c-backward-sexp 1) t)))
-	      (progn
-		(if firstp
-		    (backward-up-list 1)
-		  (goto-char last-begin))
-		;; skip over any unary operators, or other special
-		;; characters appearing at front of identifier
-		(save-excursion
-		  (c-backward-syntactic-ws lim)
-		  (skip-chars-backward "-+!*&:.~@ \t\n")
-		  (if (eq (char-before) ?\()
-		      (setq last-begin (point))))
-		(goto-char last-begin)
-		(setq donep t)))
+  ;; The bulk of this function is a pushdown automaton that looks at
+  ;; statement boundaries and the tokens in c-opt-block-stmt-key.
+  ;;
+  ;; Note: The position of a boundary is the following token.
+  ;;
+  ;; Begin with current token, stop when stack is empty and the
+  ;; position has been moved.
+  ;;
+  ;; Common state:
+  ;;   "else": Push state, goto state `else':
+  ;;     boundary: Goto state `else-boundary':
+  ;;       "if": Pop state.
+  ;;       boundary: Error, pop state.
+  ;;       other: See common state.
+  ;;     other: Error, pop state, retry token.
+  ;;   "while": Push state, goto state `while':
+  ;;     boundary: Save position, goto state `while-boundary':
+  ;;       "do": Pop state.
+  ;;       boundary: Restore position if it's not at start, pop state.
+  ;;       other: See common state.
+  ;;     other: Pop state, retry token.
+  ;;   "catch" or "finally": Push state, goto state `catch':
+  ;;     boundary: Goto state `catch-boundary':
+  ;;       "try": Pop state.
+  ;;       "catch": Goto state `catch'.
+  ;;       boundary: Error, pop state.
+  ;;       other: See common state.
+  ;;     other: Error, pop state, retry token.
+  ;;   other: Do nothing special.
+  ;;
+  ;; In addition to the above there is some special handling of labels
+  ;; and macros.
+
+  (let ((case-fold-search nil)
+	(start (point))
+	macro-start
+	(delims (if comma-delim '(?\; ?,) '(?\;)))
+	(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 boundary.
+	after-labels-pos		; Value of tok after first found colon.
+	last-label-pos			; Value of tok after last found colon.
+	sym				; Current symbol in the alphabet.
+	state				; Current state in the automaton.
+	saved-pos			; Current saved positions.
+	stack				; Stack of conses (state . saved-pos).
+	(cond-key (or c-opt-block-stmt-key
+		      "\\<\\>"))	; Matches nothing.
+	(ret 'same)
+	tok ptok pptok			; Pos of last three sexps or bounds.
+	c-in-literal-cache c-maybe-labelp saved)
+
+    (save-restriction
+      (if lim (narrow-to-region lim (point-max)))
+
+      (if (save-excursion
+	    (and (c-beginning-of-macro)
+		 (/= (point) start)))
+	  (setq macro-start (point)))
+
+      ;; Try to skip over unary operator characters, to register
+      ;; that we've moved.
+      (while (progn
+	       (setq pos (point))
+	       (c-backward-syntactic-ws)
+	       (/= (skip-chars-backward "-+!*&~@`#") 0)))
+
+      ;; First check for bare semicolon.  Later on we ignore the
+      ;; boundaries for statements that doesn'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))
+		      (c-backward-syntactic-ws)
+		      (or (memq (char-before) delims)
+			  (memq (char-before) '(?: nil))
+			  (eq (char-syntax (char-before)) ?\())))
+	  (setq ret 'previous
+		pos saved)
+
+	;; Begin at start and not pos to detect macros if we stand
+	;; directly after the #.
+	(goto-char start)
+	(if (looking-at "\\<\\|\\W")
+	    ;; Record this as the first token if not starting inside it.
+	    (setq tok start))
+
+	(while
+	    (catch 'loop ;; Throw nil to break, non-nil to continue.
+	      (cond
+	       ;; Check for macro start.
+	       ((save-excursion
+		  (and macro-start
+		       (looking-at "[ \t]*[a-zA-Z0-9!]")
+		       (progn (skip-chars-backward " \t")
+			      (eq (char-before) ?#))
+		       (progn (setq saved (1- (point)))
+			      (beginning-of-line)
+			      (not (eq (char-before (1- (point))) ?\\)))
+		       (progn (skip-chars-forward " \t")
+			      (eq (point) saved))))
+		(goto-char saved)
+		(if (and (c-forward-to-cpp-define-body)
+			 (progn (c-forward-syntactic-ws start)
+				(< (point) start)))
+		    ;; Stop at the first token in the content of the macro.
+		    (setq pos (point)
+			  ignore-labels t) ; Avoid the label check on exit.
+		  (setq pos saved
+			ret 'macro
+			ignore-labels t))
+		(throw 'loop nil))
+
+	       ;; Do a round through the automaton if we found a
+	       ;; boundary or if looking at a statement keyword.
+	       ((or sym
+		    (and (looking-at cond-key)
+			 (setq sym (intern (match-string 1)))))
+
+		(when (and (< pos start) (null stack))
+		  (throw 'loop nil))
 
-	  (setq c-maybe-labelp nil)
-	  ;; see if we're in a literal. if not, then this bufpos may be
-	  ;; a candidate for stopping
-	  (cond
-	   ;; CASE 0: did we hit the error condition above?
-	   (donep)
-	   ;; CASE 1: are we in a literal?
-	   ((eq (c-in-literal lim) 'pound)
-	    (beginning-of-line))
-	   ;; CASE 2: some other kind of literal?
-	   ((c-in-literal lim))
-	   ;; CASE 3: are we looking at a conditional keyword?
-	   ((or (and c-conditional-key (looking-at c-conditional-key))
-		(and (eq (char-after) ?\()
-		     (save-excursion
-		       (c-forward-sexp 1)
-		       (c-forward-syntactic-ws)
-		       (not (eq (char-after) ?\;)))
-		     (let ((here (point))
-			   (foundp (progn
-				     (c-backward-syntactic-ws lim)
-				     (forward-word -1)
-				     (and lim
-					  (<= lim (point))
-					  (not (c-in-literal lim))
-					  (not (eq (char-before) ?_))
-					  c-conditional-key
-					  (looking-at c-conditional-key)
-					  ))))
-		       ;; did we find a conditional?
-		       (if (not foundp)
-			   (goto-char here))
-		       foundp)))
-	    ;; are we in the middle of an else-if clause?
-	    (if (save-excursion
-		  (and (not substmt-p)
-		       (c-safe (progn (c-forward-sexp -1) t))
-		       (looking-at "\\<else\\>[ \t\n]+\\<if\\>")
-		       (not (c-in-literal lim))))
-		(progn
-		  (c-forward-sexp -1)
-		  (c-backward-to-start-of-if lim)))
-	    ;; are we sitting at an else clause, that we are not a
-	    ;; substatement of?
-	    (if (and (not substmt-p)
-		     (looking-at "\\<else\\>[^_]"))
-		(c-backward-to-start-of-if lim))
-	    ;; a finally or a series of catches?
-	    (if (not substmt-p)
-		(while (looking-at "\\<\\(catch\\|finally\\)\\>[^_]")
-		  (c-safe (c-backward-sexp 2))
-		  (if (eq (char-after) ?\()
-		      (c-safe (c-backward-sexp)))))
-	    ;; are we sitting at the while of a do-while?
-	    (if (and (looking-at "\\<while\\>[^_]")
-		     (c-backward-to-start-of-do lim))
-		(setq substmt-p nil))
-	    (setq last-begin (point)
-		  donep substmt-p))
-	   ;; CASE 4: are we looking at a label?  (But we handle
-	   ;; switch labels later.)
-	   ((and (looking-at c-label-key)
-		 (not (looking-at "default\\>"))
-		 (not (and (c-major-mode-is 'pike-mode)
-			   (save-excursion
-			     ;; Not inside a Pike type declaration?
-			     (and (c-safe (backward-up-list 1) t)
-				  (eq (char-after) ?\()))))))
-	   ;; CASE 5: is this the first time we're checking?
-	   (firstp (setq firstp nil
-			 substmt-p (not (c-crosses-statement-barrier-p
-					 (point) last-begin))
-			 last-begin (point)))
-	   ;; CASE 6: have we crossed a statement barrier?
-	   ((save-excursion
-	      ;; Move over in-expression blocks before checking the
-	      ;; barrier
-	      (if (or (memq (char-after) '(?\( ?\[))
-		      (and (eq (char-after) ?{)
-			   (c-looking-at-inexpr-block lim)))
-		  (c-forward-sexp 1))
-	      (c-crosses-statement-barrier-p (point) last-begin))
-	    (setq donep t))
-	   ;; CASE 7: ignore labels
-	   ((and c-maybe-labelp
-		 (or (and c-access-key (looking-at c-access-key))
-		     ;; with switch labels, we have to go back further
-		     ;; to try to pick up the case or default
-		     ;; keyword. Potential bogosity alert: we assume
-		     ;; `case' or `default' is first thing on line
-		     (let ((here (point)))
-		       (beginning-of-line)
-		       (c-forward-syntactic-ws here)
-		       (if (looking-at c-switch-label-key)
-			   t
-			 (goto-char here)
-			 nil)))))
-	   ;; CASE 8: ObjC or Java method def
-	   ((and c-method-key
-		 (setq last-begin (c-in-method-def-p)))
-	    (setq donep t))
-	   ;; CASE 9: Normal token.  At bob, we can end up at ws or a
-	   ;; comment, and last-begin shouldn't be updated then.
-	   ((not (looking-at "\\s \\|/[/*]"))
-	    (setq last-begin (point)))
-	   ))))
-    (goto-char last-begin)
-    ;; We always want to skip over the non-whitespace modifier
-    ;; characters that can start a statement.
-    (let ((lim (point)))
-      (skip-chars-backward "-+!*&~@`# \t\n" (c-point 'boi))
-      (skip-chars-forward " \t\n" lim))))
+		;; The state handling.  Continue in the common state for
+		;; unhandled cases.
+		(or (cond
+		     ((eq state 'else)
+		      (if (eq sym 'boundary)
+			  (setq state 'else-boundary)
+			(c-bos-report-error)
+			(c-bos-pop-state-and-retry)))
+
+		     ((eq state 'else-boundary)
+		      (cond ((eq sym 'if)
+			     (c-bos-pop-state (setq ret 'beginning)))
+			    ((eq sym 'boundary)
+			     (c-bos-report-error)
+			     (c-bos-pop-state))))
+
+		     ((eq state 'while)
+		      (if (and (eq sym 'boundary)
+			       ;; Since this can cause backtracking we do a
+			       ;; little more careful analysis to avoid it:
+			       ;; If there's a label in front of the while
+			       ;; it can't be part of a do-while.
+			       (not after-labels-pos))
+			  (progn (c-bos-save-pos)
+				 (setq state 'while-boundary))
+			(c-bos-pop-state-and-retry)))
+
+		     ((eq state 'while-boundary)
+		      (cond ((eq sym 'do)
+			     (c-bos-pop-state (setq ret 'beginning)))
+			    ((eq sym 'boundary)
+			     (c-bos-restore-pos)
+			     (c-bos-pop-state))))
+
+		     ((eq state 'catch)
+		      (if (eq sym 'boundary)
+			  (setq state 'catch-boundary)
+			(c-bos-report-error)
+			(c-bos-pop-state-and-retry)))
+
+		     ((eq state 'catch-boundary)
+		      (cond
+		       ((eq sym 'try)
+			(c-bos-pop-state (setq ret 'beginning)))
+		       ((eq sym 'catch)
+			(setq state 'catch))
+		       ((eq sym 'boundary)
+			(c-bos-report-error)
+			(c-bos-pop-state)))))
+
+		    ;; This is state common.
+		    (cond ((eq sym 'boundary)
+			   (if (< pos start)
+			       (c-bos-pop-state)
+			     (c-bos-push-state)))
+			  ((eq sym 'else)
+			   (c-bos-push-state)
+			   (c-bos-save-error-info 'if 'else)
+			   (setq state 'else))
+			  ((eq sym 'while)
+			   (when (or (not pptok)
+				     (memq (char-after pptok) delims))
+			     ;; 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.
+			     (c-bos-push-state)
+			     (setq state 'while)))
+			  ((memq sym '(catch finally))
+			   (c-bos-push-state)
+			   (c-bos-save-error-info 'try sym)
+			   (setq state 'catch))))
+
+		(when c-maybe-labelp
+		  ;; We're either past a statement boundary or at the
+		  ;; start of a statement, so throw away any label data
+		  ;; for the previous one.
+		  (setq after-labels-pos nil
+			last-label-pos nil
+			c-maybe-labelp nil))))
 
-(defun c-end-of-statement-1 ()
-  (condition-case nil
-      (let (beg end found)
-	(while (and (not (eobp))
+	      ;; Step to next sexp, but not if we crossed a boundary, since
+	      ;; that doesn't consume an sexp.
+	      (if (eq sym 'boundary)
+		  (setq ret 'previous)
+		(while
 		    (progn
-		      (setq beg (point))
-		      (c-forward-sexp 1)
-		      (setq end (point))
-		      (goto-char beg)
-		      (setq found nil)
-		      (while (and (not found)
-				  (re-search-forward "[;{}]" end t))
-			(if (not (c-in-literal beg))
-			    (setq found t)))
-		      (not found)))
-	  (goto-char end))
-	(re-search-backward "[;{}]")
-	(forward-char 1))
-    (error
-     (let ((beg (point)))
-       (c-safe (backward-up-list -1))
-       (let ((end (point)))
-	 (goto-char beg)
-	 (search-forward ";" end 'move)))
-     )))
+		      (or (c-safe (goto-char (scan-sexps (point) -1)) t)
+			  (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)
+			    (t
+			     ;; 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))))))
+
+		;; Check for statement boundary.
+		(when (save-excursion
+			(if (if (eq (char-after) ?{)
+				(c-looking-at-inexpr-block lim nil)
+			      (eq (char-syntax (char-after)) ?\())
+			    ;; Need to move over parens and
+			    ;; in-expression blocks to get a good start
+			    ;; position for the boundary check.
+			    (c-forward-sexp 1))
+			(setq boundary-pos (c-crosses-statement-barrier-p
+					    (point) pos)))
+		  (setq pptok ptok
+			ptok tok
+			tok boundary-pos
+			sym 'boundary)
+		  (throw 'loop t)))
+
+	      (when (and (numberp c-maybe-labelp) (not ignore-labels))
+		;; 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))
+
+	      ;; ObjC method def?
+	      (when (and c-opt-method-key
+			 (setq saved (c-in-method-def-p)))
+		(setq pos saved
+		      ignore-labels t)	; Avoid the label check on exit.
+		(throw 'loop nil))
+
+	      (setq sym nil
+		    pptok ptok
+		    ptok tok
+		    tok (point)
+		    pos tok)))		; Not nil.
+
+	;; If the stack isn't empty there might be errors to report.
+	(while stack
+	  (if (and (vectorp saved-pos) (eq (length saved-pos) 3))
+	      (c-bos-report-error))
+	  (setq saved-pos (cdr (car stack))
+		stack (cdr stack)))
+
+	(when (and (eq ret 'same)
+		   (not (memq sym '(boundary ignore nil))))
+	  ;; Need to investigate closer whether we've crossed
+	  ;; between a substatement and its containing statement.
+	  (if (setq saved (if (looking-at c-block-stmt-1-key)
+			      ptok
+			    pptok))
+	      (cond ((> start saved) (setq pos saved))
+		    ((= start saved) (setq ret 'up)))))
+
+	(when (and c-maybe-labelp (not ignore-labels) after-labels-pos)
+	  ;; 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)
+		(setq pos last-label-pos)))))
+
+      ;; Skip over the unary operators that can start the statement.
+      (goto-char pos)
+      (while (progn
+	       (c-backward-syntactic-ws)
+	       (/= (skip-chars-backward "-+!*&~@`#") 0))
+	(setq pos (point)))
+      (goto-char pos)
+      ret)))
+
+(defun c-crosses-statement-barrier-p (from to)
+  "Return non-nil if buffer positions FROM to TO cross one or more
+statement or declaration boundaries.  The returned value is actually
+the position of the earliest boundary char.
+
+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."
+  (let ((skip-chars c-stmt-delim-chars)
+	lit-range)
+    (save-excursion
+      (catch 'done
+	(goto-char from)
+	(while (progn (skip-chars-forward skip-chars to)
+		      (< (point) to))
+	  (if (setq lit-range (c-literal-limits from))
+	      (goto-char (setq from (cdr lit-range)))
+	    (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)))
+		  (t (throw 'done (point))))))
+	nil))))
 
 
-(defun c-crosses-statement-barrier-p (from to)
-  ;; Does buffer positions FROM to TO cross a C statement boundary?
-  (let ((here (point))
-	(lim from)
-	crossedp)
-    (condition-case ()
-	(progn
-	  (goto-char from)
-	  (while (and (not crossedp)
-		      (< (point) to))
-	    (skip-chars-forward "^;{}:" (1- to))
-	    (if (not (c-in-literal lim))
-		(progn
-		  (if (memq (char-after) '(?\; ?{ ?}))
-		      (setq crossedp t)
-		    (if (eq (char-after) ?:)
-			(setq c-maybe-labelp t))
-		    (forward-char 1))
-		  (setq lim (point)))
-	      (forward-char 1))))
-      (error (setq crossedp nil)))
-    (goto-char here)
-    crossedp))
+;; This is a dynamically bound cache used together with
+;; c-query-macro-start and c-query-and-set-macro-start.  It only works
+;; as long as point doesn't cross a macro boundary.
+(defvar c-macro-start 'unknown)
+
+(defsubst c-query-and-set-macro-start ()
+  (if (symbolp c-macro-start)
+      (setq c-macro-start (save-excursion
+			    (and (c-beginning-of-macro)
+				 (point))))
+    c-macro-start))
+
+(defsubst c-query-macro-start ()
+  (if (symbolp c-macro-start)
+      (save-excursion
+	(and (c-beginning-of-macro)
+	     (point)))
+    c-macro-start))
+
+(defun c-beginning-of-macro (&optional lim)
+  "Go to the beginning of a cpp macro definition.
+Leave point at the beginning of the macro and return t if in a cpp
+macro definition, otherwise return nil and leave point unchanged."
+  (let ((here (point)))
+    (save-restriction
+      (if lim (narrow-to-region lim (point-max)))
+      (beginning-of-line)
+      (while (eq (char-before (1- (point))) ?\\)
+	(forward-line -1))
+      (back-to-indentation)
+      (if (and (<= (point) here)
+	       (looking-at "#[ \t]*[a-zA-Z0-9!]"))
+	  t
+	(goto-char here)
+	nil))))
+
+(defun c-end-of-macro ()
+  "Go to the end of a cpp macro definition.
+More accurately, move point to the end of the closest following line
+that doesn't end with a line continuation backslash."
+  (while (progn
+	   (end-of-line)
+	   (when (and (eq (char-before) ?\\)
+		      (not (eobp)))
+	     (forward-char)
+	     t))))
 
-
-(defun c-beginning-of-macro (&optional lim)
-  ;; Go to the beginning of a cpp macro definition.  Leaves point at
-  ;; the beginning of the macro and returns t if in a cpp macro
-  ;; definition, otherwise returns nil and leaves point unchanged.
-  ;; `lim' is currently ignored, but the interface requires it.
+(defun c-forward-comment (count)
+  ;; Insulation from various idiosyncrasies in implementations of
+  ;; `forward-comment'.
+  ;;
+  ;; Note: Some emacsen considers incorrectly that any line comment
+  ;; ending with a backslash continues to the next line.  I can't
+  ;; think of any way to work around that in a reliable way without
+  ;; changing the buffer, though.  Suggestions welcome. ;)  (No,
+  ;; temporarily changing the syntax for backslash doesn't work since
+  ;; we must treat escapes in string literals correctly.)
+  ;;
+  ;; Another note: When moving backwards over a block comment, there's
+  ;; a bug in forward-comment that can make it stop at "/*" inside a
+  ;; line comment.  Haven't yet found a reasonably cheap way to kludge
+  ;; around that one either. :\
   (let ((here (point)))
-    (beginning-of-line)
-    (while (eq (char-before (1- (point))) ?\\)
-      (forward-line -1))
-    (back-to-indentation)
-    (if (and (<= (point) here)
-	     (eq (char-after) ?#))
-	t
-      (goto-char here)
-      nil)))
+    (if (>= count 0)
+	(when (forward-comment count)
+	  (if (eobp)
+	      ;; Some emacsen (e.g. XEmacs 21) return t when moving
+	      ;; forwards at eob.
+	      nil
+	    ;; Emacs includes the ending newline in a b-style (c++)
+	    ;; comment, but XEmacs doesn't.  We depend on the Emacs
+	    ;; behavior (which also is symmetric).
+	    (if (and (eolp) (nth 7 (parse-partial-sexp here (point))))
+		(condition-case nil (forward-char 1)))
+	    t))
+      ;; When we got newline terminated comments,
+      ;; forward-comment in all supported emacsen so far will
+      ;; stop at eol of each line not ending with a comment when
+      ;; moving backwards.  The following corrects for it when
+      ;; count is -1.  The other common case, when count is
+      ;; large and negative, works regardless.  It's too much
+      ;; work to correct for the rest of the cases.
+      (skip-chars-backward " \t\n\r\f")
+      (if (bobp)
+	  ;; Some emacsen return t when moving backwards at bob.
+	  nil
+	(re-search-forward "[\n\r]" here t)
+	(let* ((res (if (forward-comment count)
+			(if (eolp) (forward-comment -1) t)))
+	       (savepos (point)))
+	  ;; XEmacs treats line continuations as whitespace (but only
+	  ;; in the backward direction).
+	  (while (and (progn (end-of-line) (< (point) here))
+		      (eq (char-before) ?\\))
+	    (setq res nil
+		  savepos (point))
+	    (forward-line))
+	  (goto-char savepos)
+	  res)))))
 
-;; Skipping of "syntactic whitespace", defined as lexical whitespace,
-;; C and C++ style comments, and preprocessor directives.  Search no
-;; farther back or forward than optional LIM.  If LIM is omitted,
-;; `beginning-of-defun' is used for backward skipping, point-max is
-;; used for forward skipping.
+(defun c-forward-comment-lc (count)
+  ;; Like `c-forward-comment', but treat line continuations as
+  ;; whitespace.
+  (catch 'done
+    (if (> count 0)
+	(while (if (c-forward-comment 1)
+		   (progn
+		     (setq count (1- count))
+		     (> count 0))
+		 (if (looking-at "\\\\$")
+		     (progn
+		       (forward-char)
+		       t)
+		   (throw 'done nil))))
+      (while (if (c-forward-comment -1)
+		 (progn
+		   (setq count (1+ count))
+		   (< count 0))
+	       (if (and (eolp) (eq (char-before) ?\\))
+		   (progn
+		     (backward-char)
+		     t)
+		 (throw 'done nil)))))
+    t))
 
 (defun c-forward-syntactic-ws (&optional lim)
-  ;; Forward skip of syntactic whitespace for Emacs 19.
-  (let* ((here (point-max))
-	 (hugenum (point-max)))
+  "Forward skip of syntactic whitespace.
+Syntactic whitespace is defined as whitespace characters, comments,
+and preprocessor directives.  However if point starts inside a comment
+or preprocessor directive, the content of it is not treated as
+whitespace.  LIM sets an upper limit of the forward movement, if
+specified."
+  (let ((here (point-max)))
+    (or lim (setq lim here))
     (while (/= here (point))
+      ;; If forward-comment in at least XEmacs 21 is given a large
+      ;; positive value, it'll loop all the way through if it hits eob.
+      (while (c-forward-comment 5))
       (setq here (point))
-      (c-forward-comment hugenum)
-      ;; skip preprocessor directives
-      (when (and (eq (char-after) ?#)
-		 (= (c-point 'boi) (point)))
-	(while (and (eq (char-before (c-point 'eol)) ?\\)
-		    (= (forward-line 1) 0)))
-	(end-of-line))
-      )
-    (if lim (goto-char (min (point) lim)))))
+      (cond
+       ;; Skip line continuations.
+       ((looking-at "\\\\$")
+	(forward-char))
+       ;; Skip preprocessor directives.
+       ((and (looking-at "#[ \t]*[a-zA-Z0-9!]")
+	     (progn (skip-chars-backward " \t")
+		    (bolp)))
+	(end-of-line)
+	(while (and (<= (point) lim)
+		    (eq (char-before) ?\\)
+			 (= (forward-line 1) 0))
+	  (end-of-line))
+	(when (> (point) lim)
+	  ;; Don't move past the macro if that'd take us past the limit.
+	  (goto-char here)))
+       ;; Skip in-comment line continuations (used for Pike refdoc).
+       ((and c-opt-in-comment-lc (looking-at c-opt-in-comment-lc))
+	(goto-char (match-end 0)))))
+    (goto-char (min (point) lim))))
 
 (defun c-backward-syntactic-ws (&optional lim)
-  ;; Backward skip over syntactic whitespace for Emacs 19.
-  (let* ((here (point-min))
-	 (hugenum (- (point-max))))
+  "Backward skip of syntactic whitespace.
+Syntactic whitespace is defined as whitespace characters, comments,
+and preprocessor directives.  However if point starts inside a comment
+or preprocessor directive, the content of it is not treated as
+whitespace.  LIM sets a lower limit of the backward movement, if
+specified."
+  (let ((start-line (c-point 'bol))
+	(here (point-min))
+	(line-cont 'maybe)
+	prev-pos)
+    (or lim (setq lim here))
     (while (/= here (point))
+      (setq prev-pos (point))
+      ;; If forward-comment in Emacs 19.34 is given a large negative
+      ;; value, it'll loop all the way through if it hits bob.
+      (while (c-forward-comment -5))
       (setq here (point))
-      (c-forward-comment hugenum)
-      (c-beginning-of-macro))
-    (if lim (goto-char (max (point) lim)))))
-
-
-;; Moving by tokens, where a token is defined as all symbols and
-;; identifiers which aren't syntactic whitespace (note that "->" is
-;; considered to be two tokens).  Point is always either left at the
-;; beginning of a token or not moved at all.  COUNT specifies the
-;; number of tokens to move; a negative COUNT moves in the opposite
-;; direction.  A COUNT of 0 moves to the next token beginning only if
-;; not already at one.  If BALANCED is true, move over balanced
-;; parens, otherwise move into them.  Also, if BALANCED is true, never
-;; move out of an enclosing paren.  LIM sets the limit for the
-;; movement and defaults to the point limit.  Returns the number of
-;; tokens left to move (positive or negative).  If 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.
+      (cond
+       ((and (eolp)
+	     (eq (char-before) ?\\)
+	     (if (<= prev-pos (c-point 'eonl))
+		 t
+	       ;; Passed a line continuation, but not from the line we
+	       ;; started on.
+	       (forward-char)
+	       (setq line-cont nil)))
+	(backward-char)
+	(setq line-cont t))
+       ((progn
+	  (when (eq line-cont 'maybe)
+	    (save-excursion
+	      (end-of-line)
+	      (setq line-cont (eq (char-before) ?\\))))
+	  (or line-cont
+	      (and (< (point) start-line)
+		   (c-beginning-of-macro))))
+	(if (< (point) lim)
+	    ;; Don't move past the macro if we began inside it or at
+	    ;; the end of the same line, or if the move would take us
+	    ;; past the limit.
+	    (goto-char here))
+	(setq line-cont nil))
+       ;; Skip in-comment line continuations (used for Pike refdoc).
+       ((and c-opt-in-comment-lc
+	     (save-excursion
+	       (and (c-safe (beginning-of-line)
+			    (backward-char 2)
+			    t)
+		    (looking-at c-opt-in-comment-lc)
+		    (eq (match-end 0) here))))
+	(goto-char (match-beginning 0)))))
+    (goto-char (max (point) lim))))
 
 (defun c-forward-token-1 (&optional count balanced lim)
+  "Move forward by tokens.
+A token is defined as all symbols and identifiers which aren't
+syntactic whitespace \(note that e.g. \"->\" is considered to be two
+tokens).  Point is always either left at the beginning of a token or
+not moved at all.  COUNT specifies the number of tokens to move; a
+negative COUNT moves in the opposite direction.  A COUNT of 0 moves to
+the next token beginning only if not already at one.  If BALANCED is
+true, move over balanced parens, otherwise move into them.  Also, if
+BALANCED is true, never move out of an enclosing paren.  LIM sets the
+limit for the movement and defaults to the point limit.
+
+Return the number of tokens left to move \(positive or negative).  If
+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."
   (or count (setq count 1))
   (if (< count 0)
       (- (c-backward-token-1 (- count) balanced lim))
@@ -371,7 +763,7 @@
 		(if (memq (char-syntax (char-after)) jump-syntax)
 		    (goto-char (scan-sexps (point) 1))
 		  (forward-char))
-		(c-forward-syntactic-ws lim)
+		(c-forward-syntactic-ws)
 		(setq count (1- count)))
 	    (error (goto-char last)))
 	  (when (eobp)
@@ -380,6 +772,8 @@
       count)))
 
 (defun c-backward-token-1 (&optional count balanced lim)
+  "Move backward by tokens.
+See `c-forward-token-1' for details."
   (or count (setq count 1))
   (if (< count 0)
       (- (c-forward-token-1 (- count) balanced lim))
@@ -391,7 +785,9 @@
 	       (or (and (memq (char-syntax (or (char-after) ? )) '(?w ?_))
 			(memq (char-syntax (or (char-before) ? )) '(?w ?_)))
 		   (/= (point)
-		       (save-excursion (c-forward-syntactic-ws) (point)))
+		       (save-excursion
+			 (c-forward-syntactic-ws (1+ lim))
+			 (point)))
 		   (eobp)))
 	  ;; If count is zero we should jump if in the middle of a
 	  ;; token or if there is whitespace between point and the
@@ -406,7 +802,7 @@
 		  (while (progn
 			   (setq last (point))
 			   (> count 0))
-		    (c-backward-syntactic-ws lim)
+		    (c-backward-syntactic-ws)
 		    (if (memq (char-syntax (char-before)) jump-syntax)
 			(goto-char (scan-sexps (point) -1))
 		      (backward-char))
@@ -415,16 +811,93 @@
 	      (if (bobp) (goto-char last)))))
       count)))
 
+(defun c-syntactic-re-search-forward (regexp &optional bound noerror count
+					     paren-level)
+  ;; Like `re-search-forward', but only report matches that are found
+  ;; in syntactically significant text.  I.e. matches that begins in
+  ;; comments, macros or string literals are ignored.  The start point
+  ;; is assumed to be outside any comment, macro or string literal, or
+  ;; else the content of that region is taken as syntactically
+  ;; significant text.  If PAREN-LEVEL is non-nil, an additional
+  ;; restriction is added to ignore matches in nested paren sexps, and
+  ;; the search will also not go outside the current paren sexp.
+  (or bound (setq bound (point-max)))
+  (or count (setq count 1))
+  (if paren-level (setq paren-level -1))
+  (let ((start (point))
+	(pos (point))
+	match-pos state)
+    (condition-case err
+	(while (and (> count 0)
+		    (re-search-forward regexp bound noerror))
+	  (setq match-pos (point)
+		state (parse-partial-sexp pos (match-beginning 0)
+					  paren-level nil state)
+		pos (point))
+	  (cond ((nth 3 state)
+		 ;; Match inside a string.  Skip to the end of it
+		 ;; before continuing.
+		 (let ((ender (make-string 1 (nth 3 state))))
+		   (while (progn
+			    (search-forward ender bound noerror)
+			    (setq state (parse-partial-sexp pos (point)
+							    nil nil state)
+				  pos (point))
+			    (nth 3 state)))))
+		((nth 7 state)
+		 ;; Match inside a line comment.  Skip to eol.  Use
+		 ;; re-search-forward for it to get the right bound
+		 ;; behavior.
+		 (re-search-forward "[\n\r]" bound noerror))
+		((nth 4 state)
+		 ;; Match inside a block comment.  Skip to the '*/'.
+		 (re-search-forward "\\*/" bound noerror))
+		((save-excursion (c-beginning-of-macro start))
+		 ;; Match inside a macro.  Skip to the end of it.
+		 (c-end-of-macro))
+		((and paren-level (/= (car state) 0))
+		 (if (> (car state) 0)
+		     ;; Match inside a nested paren sexp.  Skip out of it.
+		     (setq state (parse-partial-sexp pos bound 0 nil state)
+			   pos (point))
+		   ;; Have exited the current paren sexp.  The
+		   ;; parse-partial-sexp above has left us just after
+		   ;; the closing paren in this case.  Just make
+		   ;; re-search-forward above fail in the appropriate
+		   ;; way; we'll adjust the leave off point below if
+		   ;; necessary.
+		   (setq bound (point))))
+		(t
+		 ;; A real match.
+		 (setq count (1- count)))))
+      (error
+       (goto-char start)
+       (signal (car err) (cdr err))))
+    (if (= count 0)
+	(progn
+	  (goto-char match-pos)
+	  match-pos)
+      ;; Search failed.  Set point as appropriate.
+      (cond ((eq noerror t)
+	     (goto-char start))
+	    (paren-level
+	     (if (eq (car (parse-partial-sexp pos bound -1 nil state)) -1)
+		 (backward-char)))
+	    (t
+	     (goto-char bound)))
+      nil)))
+
 
-;; Return `c' if in a C-style comment, `c++' if in a C++ style
-;; comment, `string' if in a string literal, `pound' if on a
-;; preprocessor line, or nil if not in a comment at all.  Optional LIM
-;; is used as the backward limit of the search.  If omitted, or nil,
-;; `beginning-of-defun' is used."
+(defun c-in-literal (&optional lim detect-cpp)
+  "Return the type of literal point is in, if any.
+The return value is `c' if in a C-style comment, `c++' if in a C++
+style comment, `string' if in a string literal, `pound' if DETECT-CPP
+is non-nil and on a preprocessor line, or nil if somewhere else.
+Optional LIM is used as the backward limit of the search.  If omitted,
+or nil, `c-beginning-of-defun' is used.
 
-(defun c-in-literal (&optional lim)
-  ;; Determine if point is in a C++ literal. we cache the last point
-  ;; calculated if the cache is enabled
+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."
   (if (and (vectorp c-in-literal-cache)
 	   (= (point) (aref c-in-literal-cache 0)))
       (aref c-in-literal-cache 1)
@@ -434,7 +907,7 @@
 		   (cond
 		    ((nth 3 state) 'string)
 		    ((nth 4 state) (if (nth 7 state) 'c++ 'c))
-		    ((c-beginning-of-macro lim) 'pound)
+		    ((and detect-cpp (c-beginning-of-macro lim)) 'pound)
 		    (t nil))))))
       ;; cache this result if the cache is enabled
       (if (not c-in-literal-cache)
@@ -443,30 +916,30 @@
 
 ;; XEmacs has a built-in function that should make this much quicker.
 ;; I don't think we even need the cache, which makes our lives more
-;; complicated anyway.  In this case, lim is ignored.
-(defun c-fast-in-literal (&optional lim)
+;; complicated anyway.  In this case, lim is only used to detect
+;; cpp directives.
+(defun c-fast-in-literal (&optional lim detect-cpp)
   (let ((context (buffer-syntactic-context)))
     (cond
      ((eq context 'string) 'string)
      ((eq context 'comment) 'c++)
      ((eq context 'block-comment) 'c)
-     ((save-excursion (c-beginning-of-macro lim)) 'pound))))
+     ((and detect-cpp (save-excursion (c-beginning-of-macro lim))) 'pound))))
 
 (if (fboundp 'buffer-syntactic-context)
     (defalias 'c-in-literal 'c-fast-in-literal))
 
 (defun c-literal-limits (&optional lim near not-in-delimiter)
-  ;; Returns 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 [ \t] 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.
+  "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 [
+\t] 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."
   (save-excursion
     (let* ((pos (point))
 	   (lim (or lim (c-point 'bod)))
@@ -586,12 +1059,12 @@
     (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.
+  "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."
   (save-excursion
     (condition-case nil
 	(if (and (consp range) (progn
@@ -620,10 +1093,10 @@
       (error range))))
 
 (defun c-literal-type (range)
-  ;; Convenience function that given the result of c-literal-limits,
-  ;; 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.
+  "Convenience function that given the result of `c-literal-limits',
+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."
   (if (consp range)
       (save-excursion
 	(goto-char (car range))
@@ -635,215 +1108,301 @@
 
 
 ;; utilities for moving and querying around syntactic elements
-(defvar c-parsing-error nil)
+
+(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
+;; cached state was made very far back in the buffer.  The cache is
+;; most effective if `c-parse-state' is used on each line while moving
+;; forward.
+
+(defvar c-state-cache-start nil)
+;; This (point-min) when `c-state-cache' was calculated, to detect
+;; that the start point hasn't changed due to narrowing.
 
 (defun c-parse-state ()
-  ;; Finds and records all open parens between some important point
-  ;; earlier in the file and point.
+  ;; Finds and records 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.
   ;;
-  ;; if there's a state cache, return it
-  (if c-state-cache c-state-cache
-    (let* (at-bob
-	   (pos (save-excursion
+  ;; The returned value is a list of the noteworthy parens with the
+  ;; last one first.  If an element in the list is an integer, it's
+  ;; the position of an open paren which has not been closed before
+  ;; 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.
+  (save-restriction
+    (let* ((here (point))
+	   (c-macro-start (c-query-macro-start))
+	   (in-macro-start (or c-macro-start (point)))
+	   old-state last-pos pairs pos)
+      ;; Somewhat ugly use of c-check-state-cache to get rid of the
+      ;; part of the state cache that is after point.  Can't use
+      ;; c-whack-state-after for the same reasons as in that function.
+      (c-check-state-cache (point) nil nil)
+      ;; Get the latest position we know are directly inside the
+      ;; closest containing paren of the cached state.
+      (setq last-pos (and c-state-cache
+			  (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-check-state-cache (point) nil nil)
+	    ;; 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)
+		  ;; returned by beginning-of-defun (i.e. open paren in
+		  ;; column zero)
+		  (goto-char here)
 		  (let ((cnt 2))
-		    (while (not (or at-bob (zerop cnt)))
-		      (goto-char (c-point 'bod))
-		      (if (and
-			   (eq (char-after) ?\{)
-			   ;; The following catches an obscure special
-			   ;; case where the brace is preceded by an
-			   ;; open paren.  That can only legally occur
-			   ;; with blocks inside expressions and in
-			   ;; Pike special brace lists.  Even so, this
-			   ;; test is still bogus then, but hopefully
-			   ;; good enough.  (We don't want to use
-			   ;; up-list here since it might be slow.)
-			   (save-excursion
-			     (c-backward-syntactic-ws)
-			     (not (eq (char-before) ?\())))
-			  (setq cnt (1- cnt)))
-		      (if (bobp)
-			  (setq at-bob t))))
-		  (point)))
-	   (here (save-excursion
-		   ;;(skip-chars-forward " \t}")
-		   (point)))
-	   (last-bod here) (last-pos pos)
-	   placeholder state sexp-end)
-      ;; cache last bod position
-      (while (catch 'backup-bod
-	       (setq state nil)
-	       (while (and pos (< pos here))
-		 (setq last-pos pos)
-		 (if (and (setq pos (c-safe (scan-lists pos 1 -1)))
-			  (<= pos here))
-		     (progn
-		       (setq sexp-end (c-safe (scan-sexps (1- pos) 1)))
-		       (if (and sexp-end
-				(<= sexp-end here))
-			   ;; we want to record both the start and end
-			   ;; of this sexp, but we only want to record
-			   ;; the last-most of any of them before here
-			   (progn
-			     (if (eq (char-after (1- pos)) ?\{)
-				 (setq state (cons (cons (1- pos) sexp-end)
-						   (if (consp (car state))
-						       (cdr state)
-						     state))))
-			     (setq pos sexp-end))
-			 ;; we're contained in this sexp so put pos on
-			 ;; front of list
-			 (setq state (cons (1- pos) state))))
-		   ;; something bad happened. check to see if we
-		   ;; crossed an unbalanced close brace. if so, we
-		   ;; didn't really find the right `important bufpos'
-		   ;; so lets back up and try again
-		   (if (and (not pos) (not at-bob)
-			    (setq placeholder
-				  (c-safe (scan-lists last-pos 1 1)))
-			    ;;(char-after (1- placeholder))
-			    (<= placeholder here)
-			    (eq (char-after (1- placeholder)) ?\}))
-		       (while t
-			 (setq last-bod (c-safe (scan-lists last-pos -1 1)))
-			 (if (not last-bod)
-			     (save-excursion
-			       ;; bogus, but what can we do here?
-			       (goto-char placeholder)
-			       (beginning-of-line)
-			       (setq c-parsing-error
-				     (format "\
-Unbalanced close brace at line %d" (1+ (count-lines 1 (point)))))
-			       (throw 'backup-bod nil))
-			   (setq at-bob (= last-bod (point-min))
-				 pos last-bod)
-			   (if (= (char-after last-bod) ?\{)
-			       (throw 'backup-bod t)))
-			 ))		;end-if
-		   ))			;end-while
-	       nil))
-      state)))
+		    (while (not (or (bobp) (zerop cnt)))
+		      (c-beginning-of-defun-1)
+		      (if (eq (char-after) ?\{)
+			  (setq cnt (1- cnt)))))
+		  (point))))
+      (narrow-to-region (point-min) here)
+      (while pos
+	;; Find the balanced brace pairs.
+	(setq 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)))))
+	;; 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)))
+	  (setq c-state-cache (cons pairs c-state-cache)))
+	(if last-pos
+	    ;; Prepare to loop, but record the open paren only if it's
+	    ;; outside a macro or within the same macro as point.
+	    (progn
+	      (setq pos last-pos)
+	      (if (or (>= last-pos in-macro-start)
+		      (save-excursion
+			(goto-char last-pos)
+			(not (c-beginning-of-macro))))
+		  (setq c-state-cache (cons (1- pos) c-state-cache))))
+	  (if (setq last-pos (c-up-list-forward pos))
+	      ;; Found a close paren without a corresponding opening
+	      ;; one.  Maybe we didn't go back far enough, so try to
+	      ;; scan backward for the start paren and then start over.
+	      (progn
+		(setq pos (c-up-list-backward pos)
+		      c-state-cache nil)
+		(unless pos
+		  (setq pos last-pos
+			c-parsing-error
+			(format "Unbalanced close paren at line %d"
+				(1+ (count-lines (point-min)
+						 (c-point 'bol last-pos)))))))
+	    (setq pos nil))))
+      c-state-cache)))
 
-(defun c-whack-state (bufpos state)
-  ;; whack off any state information that appears on STATE which lies
-  ;; after the bounds of BUFPOS.
-  (let (newstate car)
-    (while state
-      (setq car (car state)
-	    state (cdr state))
-      (if (consp car)
-	  ;; just check the car, because in a balanced brace
-	  ;; expression, it must be impossible for the corresponding
-	  ;; close brace to be before point, but the open brace to be
-	  ;; after.
-	  (if (<= bufpos (car car))
-	      nil			; whack it off
-	    ;; its possible that the open brace is before bufpos, but
-	    ;; the close brace is after.  In that case, convert this
-	    ;; to a non-cons element.
-	    (if (<= bufpos (cdr car))
-		(setq newstate (append newstate (list (car car))))
-	      ;; we know that both the open and close braces are
-	      ;; before bufpos, so we also know that everything else
-	      ;; on state is before bufpos, so we can glom up the
-	      ;; whole thing and exit.
-	      (setq newstate (append newstate (list car) state)
-		    state nil)))
-	(if (<= bufpos car)
-	    nil				; whack it off
-	  ;; it's before bufpos, so everything else should too
-	  (setq newstate (append newstate (list car) state)
-		state nil))))
-    newstate))
+;; Debug tool to catch cache inconsistencies.
+(defvar c-debug-parse-state nil)
+(unless (fboundp 'c-real-parse-state)
+  (fset 'c-real-parse-state (symbol-function 'c-parse-state)))
+(cc-bytecomp-defun c-real-parse-state)
+(defun c-debug-parse-state ()
+  (let ((res1 (c-real-parse-state)) res2)
+    (let ((c-state-cache nil))
+      (setq res2 (c-real-parse-state)))
+    (unless (equal res1 res2)
+      (error "c-parse-state inconsistency: using cache: %s, from scratch: %s"
+	     res1 res2))
+    res1))
+(defun c-toggle-parse-state-debug (&optional arg)
+  (interactive "P")
+  (setq c-debug-parse-state (c-calculate-state arg c-debug-parse-state))
+  (fset 'c-parse-state (symbol-function (if c-debug-parse-state
+					    'c-debug-parse-state
+					  'c-real-parse-state)))
+  (c-keep-region-active))
+
+(defun c-check-state-cache (beg end old-length)
+  ;; Used on `after-change-functions' to adjust `c-state-cache'.
+  ;; Prefer speed to finesse here, since there will be many more calls
+  ;; to this function than times `c-state-cache' is used.
+  ;;
+  ;; 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.
+  (if (not (eq c-state-cache-start (point-min)))
+      (setq c-state-cache-start (point-min)
+	    c-state-cache nil)
+    (while (and c-state-cache
+		(let ((elem (car c-state-cache)))
+		  (if (consp elem)
+		      (or (<= beg (car elem))
+			  (< beg (cdr elem)))
+		    (<= beg elem))))
+      (setq c-state-cache (cdr c-state-cache)))))
 
-(defun c-hack-state (bufpos which state)
-  ;; Using BUFPOS buffer position, and WHICH (must be 'open or
-  ;; 'close), hack the c-parse-state STATE and return the results.
-  (if (eq which 'open)
-      (let ((car (car state)))
-	(if (or (null car)
-		(consp car)
-		(/= bufpos car))
-	    (cons bufpos state)
-	  state))
-    (if (not (eq which 'close))
-	(error "c-hack-state, bad argument: %s" which))
-    ;; 'close brace
-    (let ((car (car state))
-	  (cdr (cdr state)))
-      (if (consp car)
-	  (setq car (car cdr)
-		cdr (cdr cdr)))
-      ;; TBD: is this test relevant???
-      (if (consp car)
-	  state				;on error, don't change
-	;; watch out for balanced expr already on cdr of list
-	(cons (cons car bufpos)
-	      (if (consp (car cdr))
-		  (cdr cdr) cdr))
-	))))
+(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.
+  (let* ((newstate (list nil))
+	 (ptr newstate)
+	 car)
+    (while paren-state
+      (setq car (car paren-state)
+	    paren-state (cdr paren-state))
+      (if (< (if (consp car) (car car) car) bufpos)
+	  (setq paren-state nil)
+	(setcdr ptr (list car))
+	(setq ptr (cdr ptr))))
+    (cdr newstate)))
 
-(defun c-adjust-state (from to shift state)
-  ;; Adjust all points in state that lie in the region FROM..TO by
-  ;; SHIFT amount.
-  (mapcar
-   (function
-    (lambda (e)
-      (if (consp e)
-	  (let ((car (car e))
-		(cdr (cdr e)))
-	    (if (and (<= from car) (< car to))
-		(setcar e (+ shift car)))
-	    (if (and (<= from cdr) (< cdr to))
-		(setcdr e (+ shift cdr))))
-	(if (and (<= from e) (< e to))
-	    (setq e (+ shift e))))
-      e))
-   state))
+(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.
+  (catch 'done
+    (while paren-state
+      (let ((car (car paren-state)))
+	(if (consp car)
+	    ;; just check the car, because in a balanced brace
+	    ;; expression, it must be impossible for the corresponding
+	    ;; close brace to be before point, but the open brace to
+	    ;; be after.
+	    (if (<= bufpos (car car))
+		nil			; whack it off
+	      (if (< bufpos (cdr car))
+		  ;; its possible that the open brace is before
+		  ;; bufpos, but the close brace is after.  In that
+		  ;; case, convert this to a non-cons element.  The
+		  ;; rest of the state is before bufpos, so we're
+		  ;; done.
+		  (throw 'done (cons (car car) (cdr paren-state)))
+		;; we know that both the open and close braces are
+		;; before bufpos, so we also know that everything else
+		;; on state is before bufpos.
+		(throw 'done paren-state)))
+	  (if (<= bufpos car)
+	      nil			; whack it off
+	    ;; it's before bufpos, so everything else should too.
+	    (throw 'done paren-state)))
+	(setq paren-state (cdr paren-state)))
+      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 (c-point 'bod)))
-	 (placeholder (progn
-			(back-to-indentation)
-			(point)))
-	 (chr (char-after)))
-    (c-backward-syntactic-ws lim)
-    (while (and (> (point) lim)
-		(or (eq chr ?,)
-		    (memq (char-before) '(?, ?:)))
-		(progn
-		  (beginning-of-line)
-		  (setq placeholder (point))
-		  (skip-chars-forward " \t")
-		  (setq chr (char-after))
-		  (not (looking-at c-class-key))
-		  ))
-      (c-backward-syntactic-ws lim))
-    (goto-char placeholder)
-    (skip-chars-forward "^:" (c-point 'eol))))
+  (let* ((lim (or lim (c-point 'bod))))
+    (c-with-syntax-table c++-template-syntax-table
+      (c-backward-token-1 0 t lim)
+      (while (and (looking-at "[_a-zA-Z<,]")
+		  (= (c-backward-token-1 1 t lim) 0)))
+      (skip-chars-forward "^:"))))
 
 (defun c-in-method-def-p ()
   ;; Return nil if we aren't in a method definition, otherwise the
   ;; position of the initial [+-].
   (save-excursion
     (beginning-of-line)
-    (and c-method-key
-	 (looking-at c-method-key)
+    (and c-opt-method-key
+	 (looking-at c-opt-method-key)
 	 (point))
     ))
 
+;; Contributed by Kevin Ryde <user42@zip.com.au>.
+(defun c-in-gcc-asm-p ()
+  ;; Return non-nil if point is within a gcc \"asm\" block.
+  ;;
+  ;; This should be called with point inside an argument list.
+  ;;
+  ;; Only one level of enclosing parentheses is considered, so for
+  ;; instance `nil' is returned when in a function call within an asm
+  ;; operand.
+
+  (and c-opt-asm-stmt-key
+       (save-excursion
+	 (beginning-of-line)
+	 (backward-up-list 1)
+	 (c-beginning-of-statement-1 (point-min) nil t)
+	 (looking-at c-opt-asm-stmt-key))))
+
 (defun c-at-toplevel-p ()
   "Return a determination as to whether point is at the `top-level'.
 Being at the top-level means that point is either outside any
-enclosing block (such function definition), or inside a class
-definition, but outside any method blocks.
+enclosing block (such function definition), or inside a class,
+namespace or extern definition, but outside any method blocks.
 
 If point is not at the top-level (e.g. it is inside a method
 definition), then nil is returned.  Otherwise, if point is at a
@@ -852,25 +1411,42 @@
 buffer position of the start of the class declaration, and the first
 element is the buffer position of the enclosing class's opening
 brace."
-  (let ((state (c-parse-state)))
-    (or (not (c-most-enclosing-brace state))
-	(c-search-uplist-for-classkey state))))
+  (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 containing)
+(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\\)*"))
+	     (not (= (match-end 0) (c-point 'eol))))
+    (goto-char (match-end 0))))
+
+(defun c-just-after-func-arglist-p (&optional containing lim)
   ;; Return t 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.  Optional CONTAINING is position of containing s-exp open
-  ;; brace.  If not supplied, point is used as search start.
+  ;; brace.  If not supplied, point is used as search start.  LIM is
+  ;; used as bound for some backward buffer searches; the search might
+  ;; continue past it.
+  ;;
+  ;; Note: This test is easily fooled.  It only works reasonably well
+  ;; in the situations where `c-guess-basic-syntax' uses it.
   (save-excursion
-    (c-backward-syntactic-ws)
+    (c-backward-syntactic-ws lim)
     (let ((checkpoint (or containing (point))))
       (goto-char checkpoint)
       ;; could be looking at const specifier
       (if (and (eq (char-before) ?t)
 	       (forward-word -1)
-	       (looking-at "\\<const\\>"))
-	  (c-backward-syntactic-ws)
+	       (looking-at "\\<const\\>[^_]"))
+	  (c-backward-syntactic-ws lim)
 	;; otherwise, we could be looking at a hanging member init
 	;; colon
 	(goto-char checkpoint)
@@ -882,22 +1458,30 @@
 	  (if (eq (char-before) ?\))
 	      (c-backward-sexp 2)
 	    (c-backward-sexp 1))
-	  (c-backward-syntactic-ws))
+	  (c-backward-syntactic-ws lim))
 	(if (and (eq (char-before) ?:)
 		 (progn
 		   (forward-char -1)
-		   (c-backward-syntactic-ws)
-		   (looking-at "[ \t\n]*:\\([^:]+\\|$\\)")))
+		   (c-backward-syntactic-ws lim)
+		   (looking-at "\\([ \t\n]\\|\\\\\n\\)*:\\([^:]+\\|$\\)")))
 	    nil
 	  (goto-char checkpoint))
 	)
+      (setq checkpoint (point))
       (and (eq (char-before) ?\))
-	   ;; check if we are looking at a method def
-	   (or (not c-method-key)
+	   ;; 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 (not c-opt-method-key)
 	       (progn
+		 (goto-char checkpoint)
 		 (c-forward-sexp -1)
 		 (forward-char -1)
-		 (c-backward-syntactic-ws)
+		 (c-backward-syntactic-ws lim)
 		 (not (or (memq (char-before) '(?- ?+))
 			  ;; or a class category
 			  (progn
@@ -906,118 +1490,234 @@
 			  )))))
       )))
 
-;; defuns to look backwards for things
-(defun c-backward-to-start-of-do (&optional lim)
-  ;; Move to the start of the last "unbalanced" do expression.
-  ;; Optional LIM is the farthest back to search.  If none is found,
-  ;; nil is returned and point is left unchanged, otherwise t is returned.
-  (let ((do-level 1)
-	(case-fold-search nil)
-	(lim (or lim (c-point 'bod)))
-	(here (point))
-	foundp)
-    (while (not (zerop do-level))
-      ;; we protect this call because trying to execute this when the
-      ;; while is not associated with a do will throw an error
-      (condition-case nil
-	  (progn
-	    (c-backward-sexp 1)
-	    (cond
-	     ;; break infloop for illegal C code
-	     ((bobp) (setq do-level 0))
-	     ((memq (c-in-literal lim) '(c c++)))
-	     ((looking-at "while\\b[^_]")
-	      (setq do-level (1+ do-level)))
-	     ((looking-at "do\\b[^_]")
-	      (if (zerop (setq do-level (1- do-level)))
-		  (setq foundp t)))
-	     ((<= (point) lim)
-	      (setq do-level 0)
-	      (goto-char lim))))
-	(error
-	 (goto-char lim)
-	 (setq do-level 0))))
-    (if (not foundp)
-	(goto-char here))
-    foundp))
-
-(defun c-backward-to-start-of-if (&optional lim)
-  ;; Move to the start of the last "unbalanced" if and return t.  If
-  ;; none is found, and we are looking at an if clause, nil is
-  ;; returned.
-  (let ((if-level 1)
-	(here (c-point 'bol))
-	(case-fold-search nil)
-	(lim (or (and lim (>= (point) lim) lim)
-		 (c-point 'bod)))
-	(at-if (looking-at "if\\b[^_]")))
-    (catch 'orphan-if
-      (while (and (not (bobp))
-		  (not (zerop if-level)))
-	(c-backward-syntactic-ws)
-	(condition-case nil
-	    (c-backward-sexp 1)
-	  (error
-	   (unless at-if
-	     (goto-char here)
-	     (c-beginning-of-statement-1)
-	     (setq c-parsing-error
-		   (format "No matching `if' found for `else' on line %d"
-			   (1+ (count-lines (point-min) here))))
-	     (throw 'orphan-if nil))))
-	(cond
-	 ((looking-at "else\\b[^_]")
-	  (setq if-level (1+ if-level)))
-	 ((looking-at "if\\b[^_]")
-	  ;; check for else if... skip over
-	  (let ((here (point)))
-	    (c-safe (c-forward-sexp -1))
-	    (if (looking-at "\\<else\\>[ \t]+\\<if\\>[^_]")
-		nil
-	      (setq if-level (1- if-level))
-	      (goto-char here))))
-	 ((< (point) lim)
-	  (setq if-level 0)
-	  (goto-char lim))
-	 ))
-      t)))
+(defun c-in-knr-argdecl (&optional lim)
+  ;; Return the position of the first argument declaration if point is
+  ;; inside a K&R style argument declaration list, nil otherwise.
+  ;; `c-recognize-knr-p' is not checked.  If LIM is non-nil, it's a
+  ;; position that bounds the backward search for the argument list.
+  ;;
+  ;; Note: A declaration level context is assumed; the test can return
+  ;; false positives for statements and #define headers.  This test is
+  ;; even more easily fooled than `c-just-after-func-arglist-p'.
+  (save-excursion
+    (save-restriction
+      ;; Go back to the closest preceding normal parenthesis sexp.  We
+      ;; take that as the argument list in the function header.  Then
+      ;; check that it's followed by some symbol before the next ';'
+      ;; or '{'.  If it does, it's the header of the K&R argdecl we're
+      ;; in.
+      (if lim (narrow-to-region lim (point)))
+      (let (paren-end)
+	(and (c-safe (setq paren-end (c-down-list-backward (point))))
+	     (eq (char-after paren-end) ?\))
+	     (progn
+	       (goto-char (1+ paren-end))
+	       (c-forward-syntactic-ws)
+	       (looking-at "\\w\\|\\s_"))
+	     (c-safe (c-up-list-backward paren-end))
+	     (point))))))
 
 (defun c-skip-conditional ()
   ;; skip forward over conditional at point, including any predicate
   ;; statements in parentheses. No error checking is performed.
   (c-forward-sexp (cond
 		   ;; else if()
-		   ((looking-at "\\<else\\>[ \t]+\\<if\\>\\([^_]\\|$\\)") 3)
+		   ((looking-at (concat "\\<else"
+					"\\([ \t\n]\\|\\\\\n\\)+"
+					"if\\>\\([^_]\\|$\\)"))
+		    3)
 		   ;; do, else, try, finally
-		   ((looking-at
-		     "\\<\\(do\\|else\\|try\\|finally\\)\\>\\([^_]\\|$\\)")
+		   ((looking-at (concat "\\<\\("
+					"do\\|else\\|try\\|finally"
+					"\\)\\>\\([^_]\\|$\\)"))
 		    1)
 		   ;; for, if, while, switch, catch, synchronized, foreach
 		   (t 2))))
 
-(defun c-beginning-of-closest-statement (&optional lim)
-  ;; Go back to the closest preceding statement start.
+(defun c-after-conditional (&optional lim)
+  ;; If looking at the token after a conditional then return the
+  ;; position of its start, otherwise return nil.
+  (save-excursion
+    (and (= (c-backward-token-1 1 t lim) 0)
+	 (or (looking-at c-block-stmt-1-key)
+	     (and (eq (char-after) ?\()
+		  (= (c-backward-token-1 1 t lim) 0)
+		  (looking-at c-block-stmt-2-key)))
+	 (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.
+  (unless (= (point) (c-point 'boi))
+    (let ((start (c-after-conditional lim)))
+      (if start
+	  (goto-char start)))))
+
+(defun c-backward-to-decl-anchor (&optional lim)
+  ;; 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.
+  (unless (= (point) (c-point 'boi))
+    ;; What we have below is actually an extremely stripped variant of
+    ;; c-beginning-of-statement-1.
+    (let ((pos (point)))
+      ;; Switch syntax table to avoid stopping at line continuations.
+      (save-restriction
+	(if lim (narrow-to-region lim (point-max)))
+	(while (and (progn
+		      (c-backward-syntactic-ws)
+		      (c-safe (goto-char (scan-sexps (point) -1)) t))
+		    (not (c-crosses-statement-barrier-p (point) pos)))
+	  (setq pos (point)))
+	(goto-char pos)))))
+
+(defsubst c-search-decl-header-end ()
+  ;; Search forward for the end of the "header" of the current
+  ;; declaration.  That's the position where the definition body
+  ;; starts, or the first variable initializer, or the ending
+  ;; 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.
+  (c-with-syntax-table (if (c-major-mode-is 'c++-mode)
+			   c++-template-syntax-table
+			 (syntax-table))
+    (while (and (c-syntactic-re-search-forward "[;{=]" nil 'move 1 t)
+		;; In Pike it can be an operator identifier containing
+		;; '='.
+		(c-major-mode-is 'pike-mode)
+		(eq (char-before) ?=)
+		(c-on-identifier)))))
+
+(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
+  ;; 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
+  ;; KNR-POS is set to the start of the first such argument
+  ;; declaration, otherwise KNR-POS is nil.  If LIM is non-nil, it's a
+  ;; position that bounds the backward search.
+  ;;
+  ;; 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.
+  (catch 'return
+    (let* ((start (point))
+	 (last-stmt-start (point))
+	 (move (c-beginning-of-statement-1 lim nil t)))
+
+    (while (and (/= last-stmt-start (point))
+		(save-excursion
+		  (c-backward-syntactic-ws lim)
+		  (not (memq (char-before) '(?\; ?} ?: nil)))))
+      ;; `c-beginning-of-statement-1' stops at a block start, but we
+      ;; want to continue if the block doesn't begin a top level
+      ;; construct, i.e. if it isn't preceded by ';', '}', ':', or bob.
+      (setq last-stmt-start (point)
+	    move (c-beginning-of-statement-1 lim nil t)))
+
+    (when c-recognize-knr-p
+      (let ((fallback-pos (point)) knr-argdecl-start)
+	;; Handle K&R argdecls.  Back up after the "statement" jumped
+	;; over by `c-beginning-of-statement-1', unless it was the
+	;; function body, in which case we're sitting on the opening
+	;; brace now.  Then test if we're in a K&R argdecl region and
+	;; that we started at the other side of the first argdecl in
+	;; it.
+	(unless (eq (char-after) ?{)
+	  (goto-char last-stmt-start))
+	(if (and (setq knr-argdecl-start (c-in-knr-argdecl lim))
+		 (< knr-argdecl-start start)
+		 (progn
+		   (goto-char knr-argdecl-start)
+		   (not (eq (c-beginning-of-statement-1 lim nil t) 'macro))))
+	    (throw 'return
+		   (cons (if (eq (char-after fallback-pos) ?{)
+			     'previous
+			   'same)
+			 knr-argdecl-start))
+	  (goto-char fallback-pos))))
+
+    ;; `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
+    ;; not have moved over a declaration boundary though, so change it
+    ;; to 'same if we've moved past a '=' before '{', but not ';'.
+    ;; (This ought to be integrated into `c-beginning-of-statement-1',
+    ;; so we avoid this extra pass which potentially can search over a
+    ;; large amount of text.)
+    (if (and (eq move 'previous)
+	     (c-with-syntax-table (if (c-major-mode-is 'c++-mode)
+				      c++-template-syntax-table
+				    (syntax-table))
+	       (save-excursion
+		 (and (c-syntactic-re-search-forward "[;={]" start t 1 t)
+		      (eq (char-before) ?=)
+		      (c-syntactic-re-search-forward "[;{]" start t 1 t)
+		      (eq (char-before) ?{)
+		      (c-safe (goto-char (c-up-list-forward (point))) t)
+		      (not (c-syntactic-re-search-forward ";" start t 1 t))))))
+	(cons 'same nil)
+      (cons move nil)))))
+
+(defun c-end-of-decl-1 ()
+  ;; Assuming point is at the start of a declaration (as detected by
+  ;; e.g. `c-beginning-of-decl-1'), go to the end of it.  Unlike
+  ;; `c-beginning-of-decl-1', this function handles the case when a
+  ;; block is followed by identifiers in e.g. struct declarations in C
+  ;; or C++.  If a proper end was found then t is returned, otherwise
+  ;; 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.
   (let ((start (point))
-	(label-re (concat c-label-key "\\|"
-			  c-switch-label-key))
-	stmtbeg)
-    (if c-access-key
-	(setq label-re (concat label-re "\\|" c-access-key)))
-    (c-beginning-of-statement-1 lim)
-    (while (and (when (<= (point) start)
-		  (setq stmtbeg (point)))
-		(cond
-		 ((looking-at label-re)
-		  ;; Skip a label.
-		  (goto-char (match-end 0))
-		  t)
-		 ((looking-at c-conditional-key)
-		  ;; Skip a conditional statement.
-		  (c-safe (c-skip-conditional) t))
-		 (t nil)))
-      (c-forward-syntactic-ws start))
-    (if stmtbeg
-	(goto-char stmtbeg))))
+	(decl-syntax-table (if (c-major-mode-is 'c++-mode)
+			       c++-template-syntax-table
+			     (syntax-table))))
+    (catch 'return
+      (c-search-decl-header-end)
+
+      (when (and c-recognize-knr-p
+		 (eq (char-before) ?\;)
+		 (c-in-knr-argdecl start))
+	;; Stopped at the ';' in a K&R argdecl section which is
+	;; detected using the same criteria as in
+	;; `c-beginning-of-decl-1'.  Move to the following block
+	;; start.
+	(c-syntactic-re-search-forward "{" nil 'move 1 t))
+
+      (when (eq (char-before) ?{)
+	;; Encountered a block in the declaration.  Jump over it.
+	(condition-case nil
+	    (goto-char (c-up-list-forward (point)))
+	  (goto-char (point-max))
+	  (throw 'return nil))
+	(if (or (not c-opt-block-decls-with-vars-key)
+		(save-excursion
+		  (c-with-syntax-table decl-syntax-table
+		    (let ((lim (point)))
+		      (goto-char start)
+		      (not (and (c-syntactic-re-search-forward
+				 (concat "[;=\(\[{]\\|\\<\\("
+					 c-opt-block-decls-with-vars-key
+					 "\\)")
+				 lim t 1 t)
+				(match-beginning 1)
+				(not (eq (char-before) ?_))))))))
+	    ;; The declaration doesn't have any of the
+	    ;; `c-opt-block-decls-with-vars' keywords in the
+	    ;; beginning, so it ends here at the end of the block.
+	    (throw 'return t)))
+
+      (c-with-syntax-table decl-syntax-table
+	(while (progn
+		 (if (eq (char-before) ?\;)
+		     (throw 'return t))
+		 (c-syntactic-re-search-forward ";" nil 'move 1 t))))
+      nil)))
 
 (defun c-beginning-of-member-init-list (&optional limit)
   ;; Goes to the beginning of a member init list (i.e. just after the
@@ -1055,61 +1755,26 @@
   (and (< limit (point))
        (eq (char-before) ?:)))
 
-(defun c-skip-case-statement-forward (state &optional lim)
-  ;; skip forward over case/default bodies, with optional maximal
-  ;; limit. if no next case body is found, nil is returned and point
-  ;; is not moved
-  (let ((lim (or lim (point-max)))
-	(here (point))
-	donep foundp bufpos
-	(safepos (point))
-	(balanced (car state)))
-    ;; search until we've passed the limit, or we've found our match
-    (while (and (< (point) lim)
-		(not donep))
-      (setq safepos (point))
-      ;; see if we can find a case statement, not in a literal
-      (if (and (re-search-forward c-switch-label-key lim 'move)
-	       (setq bufpos (match-beginning 0))
-	       (not (c-in-literal safepos))
-	       (/= bufpos here))
-	  ;; if we crossed into a balanced sexp, we know the case is
-	  ;; not part of our switch statement, so just bound over the
-	  ;; sexp and keep looking.
-	  (if (and (consp balanced)
-		   (> bufpos (car balanced))
-		   (< bufpos (cdr balanced)))
-	      (goto-char (cdr balanced))
-	    (goto-char bufpos)
-	    (setq donep t
-		  foundp t))))
-    (if (not foundp)
-	(goto-char here))
-    foundp))
-
-(defun c-search-uplist-for-classkey (brace-state)
+(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 brace-state)
-      ;; no brace-state means we cannot be inside a class
+  (if (null paren-state)
+      ;; no paren-state means we cannot be inside a class
       nil
-    (let ((carcache (car brace-state))
+    (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 brace-state)
-		search-end (nth 1 brace-state))
+	  (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 brace-state)
-	      search-end (nth 0 brace-state)))
-      ;; search-end cannot be a cons cell
-      (and (consp search-end)
-	   (error "consp search-end: %s" search-end))
+	(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)
@@ -1132,22 +1797,18 @@
 	(save-excursion
 	  (save-restriction
 	    (goto-char search-start)
-	    (let ((search-key (concat c-class-key "\\|" c-extra-toplevel-key))
-		  foundp class match-end)
-	      (if c-inexpr-class-key
-		  (setq search-key (concat search-key "\\|"
-					   c-inexpr-class-key)))
+	    (let (foundp class match-end)
 	      (while (and (not foundp)
 			  (progn
-			    (c-forward-syntactic-ws)
+			    (c-forward-syntactic-ws search-end)
 			    (> search-end (point)))
-			  (re-search-forward search-key search-end t))
+			  (re-search-forward c-decl-block-key search-end t))
 		(setq class (match-beginning 0)
 		      match-end (match-end 0))
+		(goto-char class)
 		(if (c-in-literal search-start)
-		    nil			; its in a comment or string, ignore
-		  (goto-char class)
-		  (skip-chars-forward " \t\n")
+		    (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
@@ -1157,15 +1818,14 @@
 		    (goto-char match-end)
 		    (setq foundp nil))
 		   ;; make sure we're really looking at the start of a
-		   ;; class definition, and not a forward decl, return
-		   ;; arg, template arg list, or an ObjC or Java method.
-		   ((and c-method-key
-			 (re-search-forward c-method-key search-end t)
+		   ;; 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-inexpr-class-key
-			 (looking-at c-inexpr-class-key))
+		   ((and c-opt-inexpr-class-key
+			 (looking-at c-opt-inexpr-class-key))
 		    (while (and (= (c-forward-token-1 1 t) 0)
 				(looking-at "(\\|\\w\\|\\s_\\|\\.")))
 		    (if (eq (point) search-end)
@@ -1198,7 +1858,7 @@
 	      foundp))
 	  )))))
 
-(defun c-inside-bracelist-p (containing-sexp brace-state)
+(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
@@ -1215,10 +1875,10 @@
       (goto-char containing-sexp)
       (c-forward-sexp -1)
       (let (bracepos)
-	(if (and (or (looking-at "enum[\t\n ]+")
+	(if (and (or (looking-at "enum\\>[^_]")
 		     (progn (c-forward-sexp -1)
-			    (looking-at "enum[\t\n ]+")))
-		 (setq bracepos (c-safe (scan-lists (point) 1 -1)))
+			    (looking-at "enum\\>[^_]")))
+		 (setq bracepos (c-down-list-forward (point)))
 		 (not (c-crosses-statement-barrier-p (point)
 						     (- bracepos 2))))
 	    (point)))))
@@ -1228,24 +1888,28 @@
 	    ;; Pike can have class definitions anywhere, so we must
 	    ;; check for the class key here.
 	    (and (c-major-mode-is 'pike-mode)
-		 (concat c-class-key "\\|" c-extra-toplevel-key)))
-	   bufpos lim braceassignp)
+		 c-decl-block-key))
+	   bufpos braceassignp lim next-containing)
        (while (and (not bufpos)
 		   containing-sexp)
-	 (if (consp containing-sexp)
-	     (setq containing-sexp (car brace-state)
-		   brace-state (cdr brace-state))
+	   (when paren-state
+	     (if (consp (car paren-state))
+		 (setq lim (cdr (car paren-state))
+		       paren-state (cdr paren-state))
+	       (setq lim (car paren-state)))
+	     (when paren-state
+	       (setq next-containing (car paren-state)
+		     paren-state (cdr paren-state))))
 	   (goto-char containing-sexp)
-	   (if (c-looking-at-inexpr-block)
-	       ;; We're in an in-expression block of some kind.  Do
-	       ;; not check nesting.
+	   (if (c-looking-at-inexpr-block next-containing next-containing)
+	       ;; We're in an in-expression block of some kind.  Do not
+	       ;; check nesting.  We deliberately set the limit to the
+	       ;; containing sexp, so that c-looking-at-inexpr-block
+	       ;; doesn't check for an identifier before it.
 	       (setq containing-sexp nil)
 	     ;; see if the open brace is preceded by = or [...] in
 	     ;; this statement, but watch out for operator=
-	     (setq lim (if (consp (car brace-state))
-			   (cdr (car brace-state))
-			 (car brace-state))
-		   braceassignp 'dontknow)
+	     (setq braceassignp 'dontknow)
 	     (c-backward-token-1 1 t lim)
 	     ;; Checks to do only on the first sexp before the brace.
 	     (when (and (c-major-mode-is 'java-mode)
@@ -1280,7 +1944,7 @@
 			(setq braceassignp
 			      (cond
 			       ;; Check for operator =
-			       ((looking-at "operator\\>") nil)
+			       ((looking-at "operator\\>[^_]") nil)
 			       ;; Check for `<opchar>= in Pike.
 			       ((and (c-major-mode-is 'pike-mode)
 				     (or (eq (char-after) ?`)
@@ -1293,17 +1957,18 @@
 			       ((looking-at "\\s.") 'maybe)
 			       ;; make sure we're not in a C++ template
 			       ;; argument assignment
-			       ((and (c-major-mode-is 'c++-mode)
-				     (save-excursion
-				       (let ((here (point))
-					     (pos< (progn
-						     (skip-chars-backward "^<>")
-						     (point))))
-					 (and (eq (char-before) ?<)
-					      (not (c-crosses-statement-barrier-p
-						    pos< here))
-					      (not (c-in-literal))
-					      ))))
+			       ((and
+				 (c-major-mode-is 'c++-mode)
+				 (save-excursion
+				   (let ((here (point))
+					 (pos< (progn
+						 (skip-chars-backward "^<>")
+						 (point))))
+				     (and (eq (char-before) ?<)
+					  (not (c-crosses-statement-barrier-p
+						pos< here))
+					  (not (c-in-literal))
+					  ))))
 				nil)
 			       (t t))))))
 	       (if (and (eq braceassignp 'dontknow)
@@ -1313,15 +1978,15 @@
 		 (if (eq (char-after) ?\;)
 		     ;; Brace lists can't contain a semicolon, so we're done.
 		     (setq containing-sexp nil)
-		   ;; lets see if we're nested. find the most nested
-		   ;; containing brace
-		   (setq containing-sexp (car brace-state)
-			 brace-state (cdr brace-state)))
+		   ;; Go up one level.
+		   (setq containing-sexp next-containing
+			 lim nil
+			 next-containing nil))
 	       ;; we've hit the beginning of the aggregate list
 	       (c-beginning-of-statement-1
-		(c-most-enclosing-brace brace-state))
+		(c-most-enclosing-brace paren-state))
 	       (setq bufpos (point))))
-	   ))
+	   )
        bufpos))
    ))
 
@@ -1375,82 +2040,126 @@
 		    (cons (list beg) type)))))
 	(error nil))))
 
-(defun c-looking-at-bos ()
-  ;; Returns nil if inside a statement or declaration.
+(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)
+    (c-backward-syntactic-ws lim)
     (or (bobp)
-	(memq (char-before) '(?\; ?}))
+	;; 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 (&optional lim)
+(defun c-looking-at-inexpr-block (lim containing-sexp)
   ;; Returns 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.
+  ;; 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.
   (save-excursion
-    (or lim (setq lim (point-min)))
-    (let ((block-follows (eq (char-after) ?{)))
-      ;; Look at the character after point only as a last resort when
-      ;; we can't disambiguate.
-      (if (and block-follows
-	       (progn (c-backward-syntactic-ws) (> (point) lim))
-	       (eq (char-before) ?\()
-	       (not (and c-special-brace-lists
-			 (c-looking-at-special-brace-list))))
-	  (cons 'inexpr-statement (point))
-	(let (res)
-	  (while (and (not res)
-		      (= (c-backward-token-1 1 t lim) 0)
-		      (>= (point) lim)
-		      (looking-at "(\\|\\w\\|\\s_\\|\\."))
-	    (setq res
-		  (cond ((and block-follows
-			      c-inexpr-class-key
-			      (looking-at c-inexpr-class-key)
-			      (or (not (looking-at c-class-key))
-				  (let ((prev (point)))
-				    (while (and (= (c-backward-token-1 1 t lim)
-						   0)
-						(>= (point) lim)
-						(eq (char-syntax (char-after))
-						    ?w))
-				      (setq prev (point)))
-				    (goto-char prev)
-				    (not (c-looking-at-bos)))))
-			 (cons 'inexpr-class (point)))
-			((and c-inexpr-block-key
-			      (looking-at c-inexpr-block-key))
-			 (cons 'inexpr-statement (point)))
-			((and c-lambda-key
-			      (looking-at c-lambda-key))
-			 (cons 'inlambda (point))))))
-	  res)))))
+    (let ((res 'maybe) passed-bracket
+	  (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))))
+	(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-1 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)
+				       (= (c-forward-token-1 1 t) 0))
+				(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 (eq res 'maybe)
+	  (when (and block-follows
+		     containing-sexp
+		     (eq (char-after containing-sexp) ?\())
+	    (goto-char containing-sexp)
+	    (if (or (save-excursion
+		      (c-backward-syntactic-ws lim)
+		      (and (> (point) (or lim (point-min)))
+			   (c-on-identifier)))
+		    (and c-special-brace-lists
+			 (c-looking-at-special-brace-list)))
+		nil
+	      (cons 'inexpr-statement (point))))
+	res))))
 
-(defun c-looking-at-inexpr-block-backward (&optional lim)
+(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.
   (save-excursion
-    (let ((lim (or lim (c-point 'bod))))
-      (c-safe
-       (c-backward-syntactic-ws lim)
-       (if (eq (char-before) ?})	; Recognize only a block currently.
-	   (progn
-	     (c-forward-sexp -1)
-	     (if (>= (point) lim)
-		 (c-looking-at-inexpr-block lim))))))))
+    ;; We currently only recognize a block.
+    (let ((here (point))
+	  (elem (car-safe paren-state))
+	  containing-sexp)
+      (when (and (consp elem)
+		 (progn (goto-char (cdr elem))
+			(c-forward-syntactic-ws here)
+			(= (point) here)))
+	(goto-char (car elem))
+	(if (setq paren-state (cdr paren-state))
+	    (setq containing-sexp (car-safe paren-state)))
+	(c-looking-at-inexpr-block (c-safe-position containing-sexp
+						    paren-state)
+				   containing-sexp)))))
 
 (defun c-on-identifier ()
-  ;; Returns non-nil if we're on or directly after an identifier.
+  "Return non-nil if we're on or directly after an identifier.
+Keywords are recognized and not considered identifiers."
   (if (or (memq (char-syntax (or (char-after) ? )) '(?w ?_))
 	  (memq (char-syntax (or (char-before) ? )) '(?w ?_)))
       (save-excursion
 	(skip-syntax-backward "w_")
-	(not (looking-at c-keywords)))
+	(not (looking-at c-keywords-regexp)))
     (if (c-major-mode-is 'pike-mode)
 	;; Handle the `<operator> syntax in Pike.
 	(save-excursion
@@ -1467,49 +2176,73 @@
 	       (looking-at "[-!%&*+/<=>^|~]\\|()\\|\\[]"))))))
 
 
-(defun c-most-enclosing-brace (state)
-  ;; return the bufpos of the most enclosing brace that hasn't been
-  ;; narrowed out by any enclosing class, or nil if none was found
+(defun c-most-enclosing-brace (paren-state &optional bufpos)
+  ;; Return the bufpos of the innermost enclosing brace before bufpos
+  ;; that hasn't been narrowed out, or nil if none was found.
   (let (enclosingp)
-    (while (and state (not enclosingp))
-      (setq enclosingp (car state)
-	    state (cdr state))
-      (if (consp enclosingp)
+    (or bufpos (setq bufpos 134217727))
+    (while paren-state
+      (setq enclosingp (car paren-state)
+	    paren-state (cdr paren-state))
+      (if (or (consp enclosingp)
+	      (>= enclosingp bufpos))
 	  (setq enclosingp nil)
-	(if (> (point-min) enclosingp)
+	(if (< enclosingp (point-min))
 	    (setq enclosingp nil))
-	(setq state nil)))
+	(setq paren-state nil)))
     enclosingp))
 
-(defun c-least-enclosing-brace (state)
-  ;; return the bufpos of the least (highest) enclosing brace that
-  ;; hasn't been narrowed out by any enclosing class, or nil if none
-  ;; was found.
-  (c-most-enclosing-brace (nreverse state)))
+(defun c-least-enclosing-brace (paren-state &optional bufpos)
+  ;; Return the bufpos of the outermost enclosing brace before bufpos
+  ;; that hasn't been narrowed out, 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))))
+    pos))
 
-(defun c-safe-position (bufpos state)
-  ;; return the closest known safe position higher up than point
-  (let ((safepos nil))
-    (while state
-      (setq safepos
-	    (if (consp (car state))
-		(cdr (car state))
-	      (car state)))
-      (if (< safepos bufpos)
-	  (setq state nil)
-	(setq state (cdr state))))
-    safepos))
+(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.
+  (when bufpos
+    (let ((c-macro-start (c-query-macro-start)) safepos)
+      (if (and c-macro-start
+	       (< c-macro-start bufpos))
+	  ;; Make sure bufpos is outside the macro we might be in.
+	  (setq bufpos c-macro-start))
+      (catch 'done
+	(while paren-state
+	  (setq safepos
+		(if (consp (car paren-state))
+		    (cdr (car paren-state))
+		  (car paren-state)))
+	  (if (< safepos bufpos)
+	      (throw 'done safepos)
+	    (setq paren-state (cdr paren-state))))
+	(if (eq c-macro-start bufpos)
+	    ;; Backed up bufpos to the macro start and got outside the
+	    ;; state.  We know the macro is at the top level in this case,
+	    ;; so we can use the macro start as the safe position.
+	    c-macro-start)))))
 
-(defun c-narrow-out-enclosing-class (state lim)
-  ;; narrow the buffer so that the enclosing class is hidden
-  (setq state (c-whack-state (point) state))
+(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 state
-	 (setq inclass-p (c-search-uplist-for-classkey state))
+    (and paren-state
+	 (setq inclass-p (c-search-uplist-for-classkey paren-state))
 	 (narrow-to-region
 	  (progn
 	    (goto-char (1+ (aref inclass-p 1)))
-	    (skip-chars-forward " \t\n" lim)
+	    (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))
@@ -1525,24 +2258,305 @@
     inclass-p))
 
 
-;; This function implements the main decision tree for determining the
-;; syntactic analysis of the current line of code.  Yes, it's huge and
-;; bloated!
+;; c-guess-basic-syntax implements the main decision tree for
+;; determining the syntactic analysis of the current line of code.
+;; Yes, it's huge and bloated!
+
+;; It's useful to break out some parts of the decision tree to
+;; separate functions, which are all collected below.  Use dynamic
+;; binding to propagate back the syntax results from them.
+(defvar syntax)
+(defvar syntactic-relpos)
+
+(defun c-add-stmt-syntax (syntax-symbol
+			  stop-at-boi-only
+			  containing-sexp
+			  paren-state
+			  &optional at-block-start)
+  ;; Do the generic processing to anchor the given syntax symbol on
+  ;; the preceding statement: Skip over any labels and containing
+  ;; statements on the same line, and then search backward until we
+  ;; find a statement or block start that begins at boi without a
+  ;; label or comment.
+  ;;
+  ;; Point is assumed to be at the prospective anchor point for the
+  ;; given SYNTAX-SYMBOL.  More syntax entries are added if we need to
+  ;; skip past block opens and containing statement.  All the added
+  ;; syntax elements will get the same 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 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.
+  (if (= (point) (c-point 'boi))
+      ;; This is by far the most common case, so let's give it special
+      ;; treatment.
+      (c-add-syntax syntax-symbol (point))
+
+    (let* ((savepos (point))
+	   (syms (list syntax-symbol))
+	   (syms-tail syms)
+	   (boi (c-point 'boi))
+	   (prev-paren (if at-block-start ?{ (char-after)))
+	   step-type step-tmp at-comment add-inexpr-stmt)
+
+      ;; 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))
+
+      ;; Skip over any comments that stands between the statement and
+      ;; boi.  If stop-at-boi-only is nil and we're not at boi after
+      ;; this, then we're done.
+      (while (and (/= (setq savepos (point)) boi)
+		  (c-forward-comment -1))
+	(setq at-comment t
+	      boi (c-point 'boi)))
+      (goto-char savepos)
+
+      (when (or stop-at-boi-only
+		(= (point) boi))
+	(catch 'done
+	  ;; Loop if we have to back out of the containing block.
+	  (while
+	    (progn
+	      ;; Loop if we have to back up another statement.
+	      (while
+		  (progn
+		    ;; Always start by skipping over any comments that
+		    ;; stands between the statement and boi.
+		    (while (and (/= (setq savepos (point)) boi)
+				(c-forward-comment -1))
+		      (setq at-comment t
+			    boi (c-point 'boi)))
+		    (goto-char savepos)
+		    (and (or at-comment
+			     (eq step-type 'label)
+			     (/= savepos boi))
+			 (progn
+			   ;; Current position not good enough; skip
+			   ;; backward another statement.
+			   (setq stop-at-boi-only t
+				 step-type (c-beginning-of-statement-1
+					    containing-sexp))
+			   ;; 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))
+			     (setcdr syms-tail (list 'substatement))
+			     (setq syms-tail (cdr syms-tail)))
+			   (setq boi (c-point 'boi))
+			   (/= (point) savepos))))
+		(setq savepos (point)
+		      at-comment nil))
+	      (setq at-comment nil)
+
+	      (when (and (eq step-type 'same)
+			 containing-sexp)
+		(goto-char containing-sexp)
+		(setq paren-state (c-whack-state-after containing-sexp
+						       paren-state)
+		      containing-sexp (c-most-enclosing-brace paren-state))
+
+		(when (and (prog1
+			       (eq prev-paren ?{)
+			     (setq prev-paren (char-after)))
+			   (eq prev-paren ?\())
+		  (c-backward-syntactic-ws containing-sexp)
+		  (when (c-on-identifier)
+		    ;; Arrived at a function arglist start.  Exit with
+		    ;; the position of the first argument inside it.
+		    (goto-char savepos)
+		    (throw 'done t))
+		  ;; We're in an in-expression statement.  Remember
+		  ;; this.  We'll iterate below, but won't add any
+		  ;; syntax element.
+		  (setq add-inexpr-stmt t))
+
+		(setq savepos (point)
+		      boi (c-point 'boi)
+		      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 ?{)
+		    (setcdr syms-tail (list (if at-bod
+						'defun-block-intro
+					      'statement-block-intro)))
+		    (setq syms-tail (cdr syms-tail)))
+
+		  (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))
+		    (setq stop-at-boi-only t
+			  boi (c-point 'boi)))))
+	      ))))
+
+      (while syms
+	(c-add-syntax (car syms) (point))
+	(setq syms (cdr syms)))
+      (if add-inexpr-stmt
+	  (c-add-syntax 'inexpr-statement))
+      )))
+
+(defun c-add-class-syntax (symbol classkey 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)))
+
+(defun c-guess-continued-construct (indent-point
+				    char-after-ip
+				    beg-of-same-or-containing-stmt
+				    containing-sexp
+				    paren-state)
+  ;; 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.
+  (let (special-brace-list)
+    (goto-char indent-point)
+    (skip-chars-forward " \t")
+    (cond
+     ;; (CASE A removed.)
+     ;; CASE B: open braces for class or brace-lists
+     ((setq special-brace-list
+	    (or (and c-special-brace-lists
+		     (c-looking-at-special-brace-list))
+		(eq char-after-ip ?{)))
+      (cond
+       ;; CASE B.1: class-open
+       ((save-excursion
+	  (goto-char indent-point)
+	  (skip-chars-forward " \t{")
+	  (let ((decl (c-search-uplist-for-classkey (c-parse-state))))
+	    (and decl
+		 (setq beg-of-same-or-containing-stmt (aref decl 0)))
+	    ))
+	(c-add-syntax 'class-open beg-of-same-or-containing-stmt))
+       ;; CASE B.2: brace-list-open
+       ((or (consp special-brace-list)
+	    (save-excursion
+	      (goto-char beg-of-same-or-containing-stmt)
+	      (looking-at "enum\\>[^_]"))
+	    (save-excursion
+	      (goto-char indent-point)
+	      (while (and (> (point) beg-of-same-or-containing-stmt)
+			  (= (c-backward-token-1 1 t) 0)
+			  (/= (char-after) ?=)))
+	      (eq (char-after) ?=)))
+	;; The most semantically accurate symbol here is
+	;; brace-list-open, but we report it simply as a statement-cont.
+	;; The reason is that one normally adjusts brace-list-open for
+	;; brace lists as top-level constructs, and brace lists inside
+	;; statements is a completely different context.
+	(c-beginning-of-statement-1 containing-sexp)
+	(c-add-stmt-syntax 'statement-cont 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.  Might also trigger it with some macros followed
+       ;; by blocks, and this gives sane indentation then too.
+       ;; C.f. cases 16F and 17G.
+       ((progn
+	  (goto-char indent-point)
+	  (and (not (c-looking-at-bos))
+	       (eq (c-beginning-of-statement-1 containing-sexp nil nil t)
+		   'same)))
+	(c-add-stmt-syntax 'defun-open t containing-sexp paren-state))
+       ;; CASE B.4: Continued statement with block open.
+       (t
+	(goto-char beg-of-same-or-containing-stmt)
+	(c-add-stmt-syntax 'statement-cont nil containing-sexp paren-state)
+	(c-add-syntax 'block-open))
+       ))
+     ;; CASE C: iostream insertion or extraction operator
+     ((and (looking-at "<<\\|>>")
+	   (save-excursion
+	     (goto-char beg-of-same-or-containing-stmt)
+	     (while (and (re-search-forward "<<\\|>>" indent-point 'move)
+			 (c-in-literal beg-of-same-or-containing-stmt)))
+	     ;; if we ended up at indent-point, then the first streamop is on a
+	     ;; separate line. Indent the line like a statement-cont instead
+	     (when (/= (point) indent-point)
+	       (c-add-syntax 'stream-op (c-point 'boi))
+	       t))))
+     ;; CASE D: continued statement.
+     (t
+      (c-beginning-of-statement-1 containing-sexp)
+      (c-add-stmt-syntax 'statement-cont nil containing-sexp paren-state))
+     )))
 
 (defun c-guess-basic-syntax ()
+  "Return the syntactic context of the current line."
   (save-excursion
     (save-restriction
       (beginning-of-line)
       (let* ((indent-point (point))
 	     (case-fold-search nil)
-	     (fullstate (c-parse-state))
-	     (state fullstate)
+	     (paren-state (c-parse-state))
 	     literal containing-sexp char-before-ip char-after-ip lim
-	     syntax placeholder c-in-literal-cache inswitch-p
+	     syntax 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 state indent-point))
-	     inenclosing-p)
+	     (inclass-p (c-narrow-out-enclosing-class paren-state
+						      indent-point))
+	     ;; c-state-cache is shadowed here.  That means we must
+	     ;; not do any changes during the execution of this
+	     ;; function, since c-check-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.
+	     syntactic-relpos
+	     (c-stmt-delim-chars c-stmt-delim-chars))
 	;; check for meta top-level enclosing constructs, possible
 	;; extern language definitions, possibly (in C++) namespace
 	;; definitions.
@@ -1552,7 +2566,7 @@
 	    (if (and inclass-p
 		     (progn
 		       (goto-char (aref inclass-p 0))
-		       (looking-at (concat c-extra-toplevel-key "[^_]"))))
+		       (looking-at c-other-decl-block-key)))
 		(let ((enclosing (match-string 1)))
 		  (cond
 		   ((string-equal enclosing "extern")
@@ -1560,45 +2574,62 @@
 		   ((string-equal enclosing "namespace")
 		    (setq inenclosing-p 'namespace))
 		   )))))
-	;; get the buffer position of the most nested opening brace,
-	;; if there is one, and it hasn't been narrowed out
-	(save-excursion
-	  (goto-char indent-point)
-	  (skip-chars-forward " \t}")
-	  (skip-chars-backward " \t")
-	  (while (and state
-		      (not containing-sexp))
-	    (setq containing-sexp (car state)
-		  state (cdr state))
-	    (if (consp containing-sexp)
-		;; if cdr == point, then containing sexp is the brace
-		;; that opens the sexp we close
-		(if (= (cdr containing-sexp) (point))
-		    (setq containing-sexp (car containing-sexp))
-		  ;; otherwise, ignore this element
-		  (setq containing-sexp nil))
-	      ;; ignore the bufpos if its been narrowed out by the
-	      ;; containing class or does not contain the indent point
-	      (if (or (<= containing-sexp (point-min))
-		      (>= containing-sexp indent-point))
-		  (setq containing-sexp nil)))))
 
-	;; set the limit on the farthest back we need to search
-	(setq lim (or containing-sexp
-		      (if (consp (car fullstate))
-			  (cdr (car fullstate))
-			nil)
-		      (point-min)))
+	;; 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.
+	(if c-state-cache
+	    (progn
+	      (setq containing-sexp (car paren-state)
+		    paren-state (cdr paren-state))
+	      (if (consp containing-sexp)
+		  (progn
+		    (setq lim (cdr containing-sexp))
+		    (if (cdr c-state-cache)
+			;; Ignore balanced paren.  The next entry
+			;; can't be another one.
+			(setq containing-sexp (car (cdr c-state-cache))
+			      paren-state (cdr paren-state))
+		      ;; If there is no surrounding open paren then
+		      ;; put the last balanced pair back on paren-state.
+		      (setq paren-state (cons containing-sexp paren-state)
+			    containing-sexp nil)))
+		(setq lim (1+ containing-sexp))))
+	  (setq lim (point-min)))
+
+	;; If we're in a parenthesis list then ',' delimits the
+	;; "statements" rather than being an operator (with the
+	;; exception of the "for" clause).  This difference is
+	;; typically only noticeable when statements are used in macro
+	;; arglists.
+	(when (and containing-sexp
+		   (eq (char-after containing-sexp) ?\())
+	  (setq c-stmt-delim-chars c-stmt-delim-chars-with-comma))
 
 	;; cache char before and after indent point, and move point to
 	;; the most likely position to perform the majority of tests
 	(goto-char indent-point)
-	(skip-chars-forward " \t")
-	(setq char-after-ip (char-after))
 	(c-backward-syntactic-ws lim)
 	(setq char-before-ip (char-before))
 	(goto-char indent-point)
 	(skip-chars-forward " \t")
+	(setq char-after-ip (char-after))
 
 	;; are we in a literal?
 	(setq literal (c-in-literal lim))
@@ -1606,21 +2637,142 @@
 	;; now figure out syntactic qualities of the current line
 	(cond
 	 ;; CASE 1: in a string.
-	 ((memq literal '(string))
+	 ((eq literal 'string)
 	  (c-add-syntax 'string (c-point 'bopl)))
 	 ;; CASE 2: in a C or C++ style comment.
 	 ((memq literal '(c c++))
 	  (c-add-syntax literal (car (c-literal-limits lim))))
 	 ;; CASE 3: in a cpp preprocessor macro continuation.
-	 ((and (eq literal 'pound)
-	       (/= (save-excursion
-		     (c-beginning-of-macro lim)
-		     (setq placeholder (point)))
-		   (c-point 'boi)))
-	  (c-add-syntax 'cpp-macro-cont placeholder))
-	 ;; CASE 4: In-expression statement.
-	 ((and (or c-inexpr-class-key c-inexpr-block-key c-lambda-key)
-	       (setq placeholder (c-looking-at-inexpr-block)))
+	 ((and (save-excursion
+		 (when (c-beginning-of-macro)
+		   (setq macro-start (point))))
+	       (/= macro-start (c-point 'boi))
+	       (progn
+		 (setq tmpsymbol 'cpp-macro-cont)
+		 (or (not c-syntactic-indentation-in-macros)
+		     (save-excursion
+		       (goto-char macro-start)
+		       ;; If at the beginning of the body of a #define
+		       ;; directive then analyze as cpp-define-intro
+		       ;; only.  Go on with the syntactic analysis
+		       ;; otherwise.  in-macro-expr is set if we're in a
+		       ;; cpp expression, i.e. before the #define body
+		       ;; or anywhere in a non-#define directive.
+		       (if (c-forward-to-cpp-define-body)
+			   (let ((indent-boi (c-point 'boi indent-point)))
+			     (setq in-macro-expr (> (point) indent-boi)
+				   tmpsymbol 'cpp-define-intro)
+			     (= (point) indent-boi))
+			 (setq in-macro-expr t)
+			 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 t containing-sexp paren-state))
+	 ;; CASE 12: while closure of a do/while construct?
+	 ((and (looking-at "while\\>[^_]")
+	       (save-excursion
+		 (prog1 (eq (c-beginning-of-statement-1 containing-sexp)
+			    'beginning)
+		   (setq placeholder (point)))))
+	  (goto-char placeholder)
+	  (c-add-stmt-syntax 'do-while-closure 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.
+	 ((save-excursion
+	    (and (cond ((c-major-mode-is 'c++-mode)
+			(looking-at "catch\\>[^_]"))
+		       ((c-major-mode-is 'java-mode)
+			(looking-at "\\(catch\\|finally\\)\\>[^_]")))
+		 (and (c-safe (c-backward-syntactic-ws)
+			      (c-backward-sexp)
+			      t)
+		      (eq (char-after) ?{)
+		      (c-safe (c-backward-syntactic-ws)
+			      (c-backward-sexp)
+			      t)
+		      (if (eq (char-after) ?\()
+			  (c-safe (c-backward-sexp) t)
+			t))
+		 (looking-at "\\(try\\|catch\\)\\>[^_]")
+		 (setq placeholder (point))))
+	  (goto-char placeholder)
+	  (c-add-stmt-syntax 'catch-clause t containing-sexp paren-state))
+	 ;; CASE 18: A substatement we can recognize by keyword.
+	 ((save-excursion
+	    (and c-opt-block-stmt-key
+		 (not (eq char-before-ip ?\;))
+		 (not (memq char-after-ip '(?\) ?\] ?,)))
+		 (or (not (eq char-before-ip ?}))
+		     (c-looking-at-inexpr-block-backward c-state-cache))
+		 (> (point)
+		    (progn
+		      ;; Ought to cache the result from the
+		      ;; c-beginning-of-statement-1 calls here.
+		      (setq placeholder (point))
+		      (while (eq (setq step-type
+				       (c-beginning-of-statement-1 lim))
+				 'label))
+		      (if (eq step-type 'previous)
+			  (goto-char placeholder)
+			(setq placeholder (point))
+			(if (and (eq step-type 'same)
+				 (not (looking-at c-opt-block-stmt-key)))
+			    ;; Step up to the containing statement if we
+			    ;; stayed in the same one.
+			    (let (step)
+			      (while (eq
+				      (setq step
+					    (c-beginning-of-statement-1 lim))
+				      'label))
+			      (if (eq step 'up)
+				  (setq placeholder (point))
+				;; There was no containing statement afterall.
+				(goto-char placeholder)))))
+		      placeholder))
+		 (if (looking-at c-block-stmt-2-key)
+		     ;; Require a parenthesis after these keywords.
+		     ;; Necessary to catch e.g. synchronized in Java,
+		     ;; which can be used both as statement and
+		     ;; modifier.
+		     (and (= (c-forward-token-1 1 nil) 0)
+			  (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
+				     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
+				     containing-sexp paren-state))
+		 (t
+		  (c-add-stmt-syntax 'substatement nil
+				     containing-sexp paren-state))))
+	    ;; CASE 18B: Some other substatement.  This is shared
+	    ;; with case 10.
+	    (c-guess-continued-construct indent-point
+					 char-after-ip
+					 placeholder
+					 lim
+					 paren-state)))
+	 ;; 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 tmpsymbol (assq (car placeholder)
 				'((inexpr-class . class-open)
 				  (inexpr-statement . block-open))))
@@ -1635,7 +2787,9 @@
 			      'lambda-intro-cont)))
 	  (goto-char (cdr placeholder))
 	  (back-to-indentation)
-	  (c-add-syntax tmpsymbol (point))
+	  (c-add-stmt-syntax tmpsymbol t
+			     (c-most-enclosing-brace c-state-cache (point))
+			     (c-whack-state-after (point) paren-state))
 	  (unless (eq (point) (cdr placeholder))
 	    (c-add-syntax (car placeholder))))
 	 ;; CASE 5: Line is at top level.
@@ -1653,7 +2807,7 @@
 		(goto-char indent-point)
 		(skip-chars-forward " \t")
 		(and (c-safe (progn (c-backward-sexp 2) t))
-		     (looking-at (concat c-extra-toplevel-key "[^_]"))
+		     (looking-at c-other-decl-block-key)
 		     (setq keyword (match-string 1)
 			   placeholder (point))
 		     (or (and (string-equal keyword "namespace")
@@ -1671,25 +2825,15 @@
 	     ((save-excursion
 		(goto-char indent-point)
 		(skip-chars-forward " \t{")
-		;; TBD: watch out! there could be a bogus
-		;; c-state-cache in place when we get here.  we have
-		;; to go through much chicanery to ignore the cache.
-		;; But of course, there may not be!  BLECH!  BOGUS!
-		(let ((decl
-		       (let ((c-state-cache nil))
-			 (c-search-uplist-for-classkey (c-parse-state))
-			 )))
+		(let ((decl (c-search-uplist-for-classkey (c-parse-state))))
 		  (and decl
 		       (setq placeholder (aref decl 0)))
 		  ))
 	      (c-add-syntax 'class-open placeholder))
 	     ;; CASE 5A.3: brace list open
 	     ((save-excursion
-		(c-beginning-of-statement-1 lim)
-		;; c-b-o-s could have left us at point-min
-		(and (bobp)
-		     (c-forward-syntactic-ws indent-point))
-		(if (looking-at "typedef[^_]")
+		(c-beginning-of-statement-1 lim t)
+		(if (looking-at "typedef\\>[^_]")
 		    (progn (c-forward-sexp 1)
 			   (c-forward-syntactic-ws indent-point)))
 		(setq placeholder (c-point 'boi))
@@ -1704,7 +2848,7 @@
 					  (looking-at "new\\>[^_]"))
 				     (setq tmpsymbol 'topmost-intro-cont)))
 			       (eq (char-after) ?=))
-			     (looking-at "enum[ \t\n]+"))
+			     (looking-at "enum\\>[^_]"))
 			 (save-excursion
 			   (while (and (< (point) indent-point)
 				       (= (c-forward-token-1 1 t) 0)
@@ -1723,22 +2867,22 @@
 		  ;; case 10B.2.
 		  (progn
 		    (c-beginning-of-statement-1 lim)
-		    (c-forward-syntactic-ws)
 		    (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))
 	      (c-add-syntax 'inline-open)
-	      (c-add-class-syntax 'inclass inclass-p))
+	      (c-add-class-syntax 'inclass inclass-p paren-state))
 	     ;; CASE 5A.5: ordinary defun open
 	     (t
 	      (goto-char placeholder)
-	      (if inclass-p
+	      (if (or inclass-p 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)
+	   ((c-just-after-func-arglist-p nil lim)
 	    (cond
 	     ;; CASE 5B.1: a member init
 	     ((or (eq char-before-ip ?:)
@@ -1769,8 +2913,10 @@
 	      )
 	     ;; CASE 5B.2: K&R arg decl intro
 	     (c-recognize-knr-p
+	      (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)))
+	      (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)
@@ -1783,12 +2929,12 @@
 	      )))
 	   ;; CASE 5C: inheritance line. could be first inheritance
 	   ;; line, or continuation of a multiple inheritance
-	   ((or (and c-baseclass-key
+	   ((or (and (c-major-mode-is 'c++-mode)
 		     (progn
 		       (when (eq char-after-ip ?,)
 			 (skip-chars-forward " \t")
 			 (forward-char))
-		       (looking-at c-baseclass-key)))
+		       (looking-at c-opt-decl-spec-key)))
 		(and (or (eq char-before-ip ?:)
 			 ;; watch out for scope operator
 			 (save-excursion
@@ -1812,7 +2958,7 @@
 			   cont done)
 		       (save-excursion
 			 (while (not done)
-			   (cond ((looking-at c-Java-special-key)
+			   (cond ((looking-at c-opt-decl-spec-key)
 				  (setq injava-inher (cons cont (point))
 					done t))
 				 ((or (not (c-safe (c-forward-sexp -1) t))
@@ -1827,21 +2973,23 @@
 	    (cond
 	     ;; CASE 5C.1: non-hanging colon on an inher intro
 	     ((eq char-after-ip ?:)
-	      (c-backward-syntactic-ws lim)
+	      (c-beginning-of-statement-1 lim)
 	      (c-add-syntax 'inher-intro (c-point 'boi))
 	      ;; 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)))
+	      (if inclass-p
+		  (c-add-class-syntax 'inclass inclass-p paren-state)))
 	     ;; CASE 5C.3: in a Java implements/extends
 	     (injava-inher
 	      (let ((where (cdr injava-inher))
 		    (cont (car injava-inher)))
 		(goto-char where)
-		(cond ((looking-at "throws[ \t\n]")
+		(cond ((looking-at "throws\\>[^_]")
 		       (c-add-syntax 'func-decl-cont
 				     (progn (c-beginning-of-statement-1 lim)
 					    (c-point 'boi))))
@@ -1858,16 +3006,21 @@
 	      ;; don't add inclass symbol since relative point already
 	      ;; contains any class offset
 	      )))
-	   ;; CASE 5D: this could be a top-level compound statement, a
+	   ;; 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 (= (c-backward-token-1 1 t lim) 0)
-			    (not (looking-at "[;{<,]"))))
-		(eq (char-after) ?,)))
+			    (not (looking-at "[;<,=]"))))
+		(or (memq (char-after) '(?, ?=))
+		    (and (c-major-mode-is 'c++-mode)
+			 (= (c-backward-token-1 1 nil lim) 0)
+			 (eq (char-after) ?<)))))
 	    (goto-char indent-point)
 	    (c-beginning-of-member-init-list lim)
 	    (cond
@@ -1886,9 +3039,11 @@
 				 (parse-partial-sexp (point) placeholder)))
 			  0)
 		      (and
-		       (if c-access-key (not (looking-at c-access-key)) t)
+		       (if c-opt-access-key
+			   (not (looking-at c-opt-access-key)) t)
 		       (not (looking-at c-class-key))
-		       (if c-bitfield-key (not (looking-at c-bitfield-key)) t))
+		       (if c-opt-bitfield-key
+			   (not (looking-at c-opt-bitfield-key)) t))
 		      )))
 	      (goto-char placeholder)
 	      (c-forward-syntactic-ws)
@@ -1902,43 +3057,61 @@
 		(eq (char-after) ?:))
 	      (skip-chars-forward " \t:")
 	      (c-add-syntax 'member-init-cont (point)))
-	     ;; CASE 5D.3: perhaps a multiple inheritance line?
-	     ((save-excursion
-		(c-beginning-of-statement-1 lim)
-		(setq placeholder (point))
-		(looking-at c-inher-key))
+	     ;; 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)))
+			 (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)))
+	     ;; CASE 5D.4: perhaps a multiple inheritance line?
+	     ((and (c-major-mode-is 'c++-mode)
+		   (save-excursion
+		     (c-beginning-of-statement-1 lim)
+		     (setq placeholder (point))
+		     (if (looking-at "static\\>[^_]")
+			 (c-forward-token-1 1 nil indent-point))
+		     (and (looking-at c-class-key)
+			  (= (c-forward-token-1 2 nil indent-point) 0)
+			  (if (eq (char-after) ?<)
+			      (c-with-syntax-table c++-template-syntax-table
+				(= (c-forward-token-1 1 t indent-point) 0))
+			    t)
+			  (eq (char-after) ?:))))
 	      (goto-char placeholder)
 	      (c-add-syntax 'inher-cont (c-point 'boi)))
-	     ;; CASE 5D.4: perhaps a template list continuation?
-	     ((save-excursion
-		(goto-char indent-point)
-		(skip-chars-backward "^<" lim)
-		;; not sure if this is the right test, but it should
-		;; be fast and mostly accurate.
-		(setq placeholder (point))
-		(and (eq (char-before) ?<)
-		     (not (c-in-literal lim))))
-	      ;; we can probably indent it just like an arglist-cont
-	      (goto-char placeholder)
-	      (c-beginning-of-statement-1 lim)
-	      (c-add-syntax 'template-args-cont (c-point 'boi)))
-	     ;; CASE 5D.5: perhaps a top-level statement-cont
+	     ;; CASE 5D.5: Continuation of the "expression part" of a
+	     ;; top level construct.
 	     (t
-	      (c-beginning-of-statement-1 lim)
-	      ;; skip over any access-specifiers
-	      (and inclass-p c-access-key
-		   (while (looking-at c-access-key)
-		     (forward-line 1)))
-	      ;; skip over comments, whitespace
-	      (c-forward-syntactic-ws indent-point)
-	      (c-add-syntax 'statement-cont (c-point 'boi)))
+	      (while (and (eq (car (c-beginning-of-decl-1 containing-sexp))
+			      'same)
+			  (save-excursion
+			    (c-backward-syntactic-ws)
+			    (eq (char-before) ?}))))
+	      (c-add-stmt-syntax
+	       (if (eq char-before-ip ?,)
+		   ;; A preceding comma at the top level means that a
+		   ;; new variable declaration starts here.  Use
+		   ;; topmost-intro-cont for it, for consistency with
+		   ;; the first variable declaration.  C.f. case 5N.
+		   'topmost-intro-cont
+		 'statement-cont)
+	       nil containing-sexp paren-state))
 	     ))
 	   ;; CASE 5E: we are looking at a access specifier
 	   ((and inclass-p
-		 c-access-key
-		 (looking-at c-access-key))
-	    (c-add-syntax 'access-label (c-point 'bonl))
-	    (c-add-class-syntax 'inclass 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.
+	    (nconc syntax (list (cons 'access-label placeholder))))
 	   ;; CASE 5F: extern-lang-close or namespace-close?
 	   ((and inenclosing-p
 		 (eq char-after-ip ?}))
@@ -1957,66 +3130,72 @@
 		     (and (c-safe (progn (c-backward-sexp 1) t))
 			  (= (point) (aref inclass-p 1))
 			  ))))
-	    (c-add-class-syntax 'class-close inclass-p))
+	    (c-add-class-syntax 'class-close inclass-p paren-state))
 	   ;; CASE 5H: we could be looking at subsequent knr-argdecls
 	   ((and c-recognize-knr-p
-		 ;; here we essentially use the hack that is used in
-		 ;; Emacs' c-mode.el to limit how far back we should
-		 ;; look.  The assumption is made that argdecls are
-		 ;; indented at least one space and that function
-		 ;; headers are not indented.
-		 (let ((limit (save-excursion
-				(re-search-backward "^[^ \^L\t\n#]" nil 'move)
-				(point))))
-		   (save-excursion
-		     (c-backward-syntactic-ws limit)
-		     (setq placeholder (point))
-		     (while (and (memq (char-before) '(?\; ?,))
-				 (> (point) limit))
-		       (beginning-of-line)
-		       (setq placeholder (point))
-		       (c-backward-syntactic-ws limit))
-		     (and (eq (char-before) ?\))
-			  (or (not c-method-key)
-			      (progn
-				(c-forward-sexp -1)
-				(forward-char -1)
-				(c-backward-syntactic-ws)
-				(not (or (memq (char-before) '(?- ?+))
-					 ;; or a class category
-					 (progn
-					   (c-forward-sexp -2)
-					   (looking-at c-class-key))
-					 )))))
-		     ))
+		 (not (eq char-before-ip ?}))
 		 (save-excursion
-		   (c-beginning-of-statement-1)
-		   (not (looking-at "typedef[ \t\n]+"))))
+		   (setq placeholder (cdr (c-beginning-of-decl-1 lim)))
+		   (and placeholder
+			;; Do an extra check to avoid tripping up on
+			;; statements that occur in invalid contexts
+			;; (e.g. in macro bodies where we don't really
+			;; know the context of what we're looking at).
+			(not (and c-opt-block-stmt-key
+				  (looking-at c-opt-block-stmt-key)))))
+		 (< placeholder indent-point))
 	    (goto-char placeholder)
-	    (c-add-syntax 'knr-argdecl (c-point 'boi)))
+	    (c-add-syntax 'knr-argdecl (point)))
 	   ;; CASE 5I: ObjC method definition.
-	   ((and c-method-key
-		 (looking-at c-method-key))
+	   ((and c-opt-method-key
+		 (looking-at c-opt-method-key))
+	    (c-beginning-of-statement-1 lim)
 	    (c-add-syntax 'objc-method-intro (c-point 'boi)))
-	   ;; CASE 5J: we are at the topmost level, make sure we skip
-	   ;; back past any access specifiers
+	   ;; 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.
 	   ((progn
 	      (c-backward-syntactic-ws lim)
+	      (and (eq (char-before) ?})
+		   (save-excursion
+		     (let ((start (point)))
+		       (if paren-state
+			   ;; Speed up the backward search a bit.
+			   (goto-char (car (car paren-state))))
+		       (c-beginning-of-decl-1 containing-sexp)
+		       (setq placeholder (point))
+		       (if (= start (point))
+			   ;; The '}' is unbalanced.
+			   nil
+			 (c-end-of-decl-1)
+			 (> (point) indent-point))))))
+	    (goto-char placeholder)
+	    (c-add-stmt-syntax 'topmost-intro-cont nil
+			       containing-sexp paren-state))
+	   ;; CASE 5J: we are at the topmost level, make
+	   ;; sure we skip back past any access specifiers
+	   ((progn
 	      (while (and inclass-p
-			  c-access-key
+			  c-opt-access-key
 			  (not (bobp))
 			  (save-excursion
 			    (c-safe (progn (c-backward-sexp 1) t))
-			    (looking-at c-access-key)))
+			    (looking-at c-opt-access-key)))
 		(c-backward-sexp 1)
 		(c-backward-syntactic-ws lim))
 	      (or (bobp)
-		  (memq (char-before) '(?\; ?\}))))
+		  (memq (char-before) '(?\; ?}))
+		  (and (c-major-mode-is 'objc-mode)
+		       (progn
+			 (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))
@@ -2027,29 +3206,32 @@
 		      (c-add-syntax 'inextern-lang (c-point 'boi)))
 		     ((eq inenclosing-p 'namespace)
 		      (c-add-syntax 'innamespace (c-point 'boi)))
-		     (t (c-add-class-syntax 'inclass inclass-p)))
+		     (t (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))
 	      ))
-	   ;; CASE 5K: we are at an ObjC or Java method definition
+	   ;; CASE 5K: we are at an ObjC method definition
 	   ;; continuation line.
-	   ((and c-method-key
+	   ((and c-opt-method-key
 		 (progn
 		   (c-beginning-of-statement-1 lim)
 		   (beginning-of-line)
-		   (looking-at c-method-key)))
+		   (looking-at c-opt-method-key)))
 	    (c-add-syntax 'objc-method-args-cont (point)))
 	   ;; CASE 5L: we are at the first argument of a template
 	   ;; arglist that begins on the previous line.
 	   ((eq (char-before) ?<)
-	    (c-beginning-of-statement-1 lim)
-	    (c-forward-syntactic-ws)
+	    (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 lim)
-	    (c-forward-syntactic-ws)
+	    (c-beginning-of-statement-1 (c-safe-position (point) paren-state))
 	    (c-add-syntax 'topmost-intro-cont (c-point 'boi)))
-	   ))				; end CASE 5
+	   ))
 	 ;; (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
@@ -2059,14 +3241,9 @@
 			  (goto-char containing-sexp)
 			  (c-looking-at-special-brace-list)))
 		   (eq (char-after containing-sexp) ?{)))
-	  (c-backward-syntactic-ws containing-sexp)
 	  (cond
 	   ;; CASE 7A: we are looking at the arglist closing paren
-	   ((and (or (c-major-mode-is 'pike-mode)
-		     ;; Don't check this in Pike since it allows a
-		     ;; comma after the last arg.
-		     (not (eq char-before-ip ?,)))
-		 (memq char-after-ip '(?\) ?\])))
+	   ((memq char-after-ip '(?\) ?\]))
 	    (goto-char containing-sexp)
 	    (setq placeholder (c-point 'boi))
 	    (when (and (c-safe (backward-up-list 1) t)
@@ -2076,18 +3253,31 @@
 	      (setq placeholder (point)))
 	    (c-add-syntax 'arglist-close placeholder))
 	   ;; CASE 7B: Looking at the opening brace of an
-	   ;; in-expression block or brace list.
-	   ((eq char-after-ip ?{)
-	    (goto-char indent-point)
-	    (setq placeholder (c-point 'boi))
-	    (goto-char containing-sexp)
-	    (if (c-inside-bracelist-p placeholder
-				      (cons containing-sexp state))
-		(progn
-		  (c-add-syntax 'brace-list-open (c-point 'boi))
-		  (c-add-syntax 'inexpr-class))
-	      (c-add-syntax 'block-open (c-point 'boi))
-	      (c-add-syntax 'inexpr-statement)))
+	   ;; 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))
+		   (if placeholder
+		       (setq tmpsymbol '(brace-list-open . inexpr-class))
+		     (setq tmpsymbol '(block-open . inexpr-statement)
+			   placeholder
+			   (cdr-safe (c-looking-at-inexpr-block
+				      (c-safe-position containing-sexp
+						       paren-state)
+				      containing-sexp)))
+		     ;; placeholder is nil if it's a block directly in
+		     ;; a function arglist.  That makes us skip out of
+		     ;; this case.
+		     )))
+	    (goto-char placeholder)
+	    (back-to-indentation)
+	    (c-add-stmt-syntax (car tmpsymbol) t
+			       (c-most-enclosing-brace paren-state (point))
+			       (c-whack-state-after (point) 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.
@@ -2102,23 +3292,22 @@
 	    (c-add-syntax 'arglist-intro placeholder))
 	   ;; CASE 7D: we are inside a conditional test clause. treat
 	   ;; these things as statements
-	   ((save-excursion
+	   ((progn
 	      (goto-char containing-sexp)
 	      (and (c-safe (progn (c-forward-sexp -1) t))
 		   (looking-at "\\<for\\>[^_]")))
 	    (goto-char (1+ containing-sexp))
 	    (c-forward-syntactic-ws indent-point)
-	    (c-beginning-of-statement-1 containing-sexp)
 	    (if (eq char-before-ip ?\;)
 		(c-add-syntax 'statement (point))
 	      (c-add-syntax 'statement-cont (point))
 	      ))
-	   ;; CASE 7E: maybe a continued method call. This is the case
-	   ;; when we are inside a [] bracketed exp, and what precede
-	   ;; the opening bracket is not an identifier.
-	   ((and c-method-key
+	   ;; 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.
+	   ((and c-opt-method-key
 		 (eq (char-after containing-sexp) ?\[)
-		 (save-excursion
+		 (progn
 		   (goto-char (1- containing-sexp))
 		   (c-backward-syntactic-ws (c-point 'bod))
 		   (if (not (looking-at c-symbol-key))
@@ -2129,10 +3318,11 @@
 	   ;; opening paren.  This case includes multi-line
 	   ;; mathematical paren groupings, but we could be on a
 	   ;; for-list continuation line
-	   ((save-excursion
+	   ((progn
 	      (goto-char (1+ containing-sexp))
 	      (skip-chars-forward " \t")
-	      (not (eolp)))
+	      (and (not (eolp))
+		   (not (looking-at "\\\\$"))))
 	    (goto-char containing-sexp)
 	    (setq placeholder (c-point 'boi))
 	    (when (and (c-safe (backward-up-list 1) t)
@@ -2143,17 +3333,15 @@
 	    (c-add-syntax 'arglist-cont-nonempty placeholder))
 	   ;; CASE 7G: we are looking at just a normal arglist
 	   ;; continuation line
-	   (t (c-beginning-of-statement-1 containing-sexp)
-	      (forward-char 1)
-	      (c-forward-syntactic-ws indent-point)
+	   (t (c-forward-syntactic-ws indent-point)
 	      (c-add-syntax 'arglist-cont (c-point 'boi)))
 	   ))
 	 ;; CASE 8: func-local multi-inheritance line
-	 ((and c-baseclass-key
+	 ((and (c-major-mode-is 'c++-mode)
 	       (save-excursion
 		 (goto-char indent-point)
 		 (skip-chars-forward " \t")
-		 (looking-at c-baseclass-key)))
+		 (looking-at c-opt-decl-spec-key)))
 	  (goto-char indent-point)
 	  (skip-chars-forward " \t")
 	  (cond
@@ -2175,7 +3363,7 @@
 			 (save-excursion
 			   (goto-char containing-sexp)
 			   (c-looking-at-special-brace-list)))
-		    (c-inside-bracelist-p containing-sexp state)))
+		    (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)
@@ -2189,9 +3377,10 @@
 		     (assoc 'statement-cont
 			    (setq placeholder (c-guess-basic-syntax))))
 		(setq syntax placeholder)
-	      (c-beginning-of-statement-1 lim)
+	      (c-beginning-of-statement-1
+	       (c-safe-position (1- containing-sexp) paren-state))
 	      (c-forward-token-1 0)
-	      (if (looking-at "typedef\\>") (c-forward-token-1 1))
+	      (if (looking-at "typedef\\>[^_]") (c-forward-token-1 1))
 	      (c-add-syntax 'brace-list-open (c-point 'boi))))
 	   ;; CASE 9B: brace-list-close brace
 	   ((if (consp special-brace-list)
@@ -2211,11 +3400,15 @@
 			  (eq (1+ (point)) (cdr (car special-brace-list)))))))
 	      ;; Normal brace list check.
 	      (and (eq char-after-ip ?})
-		   (c-safe (progn (forward-char 1)
-				  (c-backward-sexp 1)
+		   (c-safe (progn (goto-char (c-up-list-backward (point)))
 				  t))
 		   (= (point) containing-sexp)))
-	    (c-add-syntax 'brace-list-close (c-point 'boi)))
+	    (if (eq (point) (c-point 'boi))
+		(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 t lim
+				 (c-whack-state-after (point) paren-state) t)))
 	   (t
 	    ;; Prepare for the rest of the cases below by going to the
 	    ;; token following the opening brace
@@ -2228,13 +3421,20 @@
 	    (let ((start (point)))
 	      (c-forward-syntactic-ws indent-point)
 	      (goto-char (max start (c-point 'bol))))
-	    (skip-chars-forward " \t\n\r" indent-point)
+	    (c-skip-ws-forward indent-point)
 	    (cond
 	     ;; CASE 9C: we're looking at the first line in a brace-list
 	     ((= (point) indent-point)
-	      (goto-char containing-sexp)
-	      (c-add-syntax 'brace-list-intro (c-point 'boi))
-	      )				; end CASE 9C
+	      (if (consp special-brace-list)
+		  (goto-char (car (car special-brace-list)))
+		(goto-char containing-sexp))
+	      (if (eq (point) (c-point 'boi))
+		  (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 t lim
+				   (c-whack-state-after (point) paren-state)
+				   t)))
 	     ;; CASE 9D: this is just a later brace-list-entry or
 	     ;; brace-entry-open
 	     (t (if (or (eq char-after-ip ?{)
@@ -2245,184 +3445,63 @@
 			       (c-looking-at-special-brace-list (point)))))
 		    (c-add-syntax 'brace-entry-open (point))
 		  (c-add-syntax 'brace-list-entry (point))
-		  ))			; end CASE 9D
-	     ))))			; end CASE 9
-	 ;; CASE 10: A continued statement
+		  ))
+	     ))))
+	 ;; CASE 10: A continued statement or top level construct.
 	 ((and (not (memq char-before-ip '(?\; ?:)))
 	       (or (not (eq char-before-ip ?}))
-		   (c-looking-at-inexpr-block-backward containing-sexp))
+		   (c-looking-at-inexpr-block-backward c-state-cache))
 	       (> (point)
 		  (save-excursion
 		    (c-beginning-of-statement-1 containing-sexp)
-		    (c-forward-syntactic-ws)
 		    (setq placeholder (point))))
 	       (/= placeholder containing-sexp))
-	  (goto-char indent-point)
-	  (skip-chars-forward " \t")
-	  (let ((after-cond-placeholder
-		 (save-excursion
-		   (goto-char placeholder)
-		   (if (and c-conditional-key (looking-at c-conditional-key))
-		       (progn
-			 (c-safe (c-skip-conditional))
-			 (c-forward-syntactic-ws)
-			 (if (eq (char-after) ?\;)
-			     (progn
-			       (forward-char 1)
-			       (c-forward-syntactic-ws)))
-			 (point))
-		     nil))))
-	    (cond
-	     ;; CASE 10A: substatement
-	     ((and after-cond-placeholder
-		   (>= after-cond-placeholder indent-point))
-	      (goto-char placeholder)
-	      (if (eq char-after-ip ?{)
-		  (c-add-syntax 'substatement-open (c-point 'boi))
-		(c-add-syntax 'substatement (c-point 'boi))))
-	     ;; CASE 10B: open braces for class or brace-lists
-	     ((setq special-brace-list
-		    (or (and c-special-brace-lists
-			     (c-looking-at-special-brace-list))
-			(eq char-after-ip ?{)))
-	      (cond
-	       ;; CASE 10B.1: class-open
-	       ((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)))
-		    ))
-		(c-add-syntax 'class-open placeholder))
-	       ;; CASE 10B.2: brace-list-open
-	       ((or (consp special-brace-list)
-		    (save-excursion
-		      (goto-char placeholder)
-		      (looking-at "\\<enum\\>"))
-		    (save-excursion
-		      (goto-char indent-point)
-		      (while (and (> (point) placeholder)
-				  (= (c-backward-token-1 1 t) 0)
-				  (/= (char-after) ?=)))
-		      (eq (char-after) ?=)))
-		;; The most semantically accurate symbol here is
-		;; brace-list-open, but we report it simply as a
-		;; statement-cont.  The reason is that one normally
-		;; adjusts brace-list-open for brace lists as
-		;; top-level constructs, and brace lists inside
-		;; statements is a completely different context.
-		(goto-char indent-point)
-		(c-beginning-of-closest-statement)
-		(c-add-syntax 'statement-cont (c-point 'boi)))
-	       ;; CASE 10B.3: The body of a function declared inside a
-	       ;; normal block.  This can only occur in Pike.
-	       ((and (c-major-mode-is 'pike-mode)
-		     (progn
-		       (goto-char indent-point)
-		       (not (c-looking-at-bos))))
-		(c-beginning-of-closest-statement)
-		(c-add-syntax 'defun-open (c-point 'boi)))
-	       ;; CASE 10B.4: catch-all for unknown construct.
-	       (t
-		;; Can and should I add an extensibility hook here?
-		;; Something like c-recognize-hook so support for
-		;; unknown constructs could be added.  It's probably a
-		;; losing proposition, so I dunno.
-		(goto-char placeholder)
-		(c-add-syntax 'statement-cont (c-point 'boi))
-		(c-add-syntax 'block-open))
-	       ))
-	     ;; CASE 10C: iostream insertion or extraction operator
-	     ((looking-at "<<\\|>>")
-	      (goto-char placeholder)
-	      (and after-cond-placeholder
-		   (goto-char after-cond-placeholder))
-	      (while (and (re-search-forward "<<\\|>>" indent-point 'move)
-			  (c-in-literal placeholder)))
-	      ;; if we ended up at indent-point, then the first
-	      ;; streamop is on a separate line. Indent the line like
-	      ;; a statement-cont instead
-	      (if (/= (point) indent-point)
-		  (c-add-syntax 'stream-op (c-point 'boi))
-		(c-backward-syntactic-ws lim)
-		(c-add-syntax 'statement-cont (c-point 'boi))))
-	     ;; CASE 10D: continued statement. find the accurate
-	     ;; beginning of statement or substatement
-	     (t
-	      (c-beginning-of-statement-1 after-cond-placeholder)
-	      ;; KLUDGE ALERT!  c-beginning-of-statement-1 can leave
-	      ;; us before the lim we're passing in.  It should be
-	      ;; fixed, but I'm worried about side-effects at this
-	      ;; late date.  Fix for v5.
-	      (goto-char (or (and after-cond-placeholder
-				  (max after-cond-placeholder (point)))
-			     (point)))
-	      (c-add-syntax 'statement-cont (point)))
-	     )))
-	 ;; CASE 11: an else clause?
-	 ((looking-at "\\<else\\>[^_]")
-	  (c-backward-to-start-of-if containing-sexp)
-	  (c-add-syntax 'else-clause (c-point 'boi)))
-	 ;; CASE 12: Statement. But what kind?  Lets see if its a
-	 ;; while closure of a do/while construct
-	 ((progn
-	    (goto-char indent-point)
-	    (skip-chars-forward " \t")
-	    (and (looking-at "while\\b[^_]")
-		 (save-excursion
-		   (c-backward-to-start-of-do containing-sexp)
-		   (setq placeholder (point))
-		   (looking-at "do\\b[^_]"))
-		 ))
-	  (goto-char placeholder)
-	  (c-add-syntax 'do-while-closure (c-point 'boi)))
-	 ;; 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.
-	 ((save-excursion
-	    (and (cond ((c-major-mode-is 'c++-mode)
-			(looking-at "\\<catch\\>[^_]"))
-		       ((c-major-mode-is 'java-mode)
-			(looking-at "\\<\\(catch\\|finally\\)\\>[^_]")))
-		 (c-safe (c-backward-sexp) t)
-		 (eq (char-after) ?{)
-		 (c-safe (c-backward-sexp) t)
-		 (if (eq (char-after) ?\()
-		     (c-safe (c-backward-sexp) t)
-		   t)
-		 (looking-at "\\<\\(try\\|catch\\)\\>[^_]")
-		 (setq placeholder (c-point 'boi))))
-	  (c-add-syntax 'catch-clause placeholder))
+	  ;; This is shared with case 18.
+	  (c-guess-continued-construct indent-point
+				       char-after-ip
+				       placeholder
+				       containing-sexp
+				       paren-state))
 	 ;; CASE 14: A case or default label
-	 ((looking-at c-switch-label-key)
+	 ((looking-at c-label-kwds-regexp)
 	  (goto-char containing-sexp)
-	  ;; check for hanging braces
-	  (if (/= (point) (c-point 'boi))
-	      (c-forward-sexp -1))
-	  (c-add-syntax 'case-label (c-point 'boi)))
+	  (setq lim (c-most-enclosing-brace c-state-cache containing-sexp))
+	  (c-backward-to-block-anchor lim)
+	  (c-add-stmt-syntax 'case-label t lim paren-state))
 	 ;; CASE 15: any other label
 	 ((looking-at c-label-key)
 	  (goto-char containing-sexp)
-	  ;; check for hanging braces
-	  (if (/= (point) (c-point 'boi))
-	      (c-forward-sexp -1))
-	  (c-add-syntax 'label (c-point 'boi)))
+	  (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 t lim paren-state))
 	 ;; CASE 16: block close brace, possibly closing the defun or
 	 ;; the class
 	 ((eq char-after-ip ?})
-	  (let* ((lim (c-safe-position containing-sexp fullstate))
-		 (relpos (save-excursion
-			   (goto-char containing-sexp)
-			   (if (/= (point) (c-point 'boi))
-			       (c-beginning-of-statement-1 lim))
-			   (c-point 'boi))))
+	  ;; From here on we have the next containing sexp in lim.
+	  (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 t lim paren-state))
 	     ;; CASE 16A: closing a lambda defun or an in-expression
-	     ;; block?
-	     ((save-excursion
-		(goto-char containing-sexp)
-		(setq placeholder (c-looking-at-inexpr-block)))
+	     ;; block?  C.f. cases 4, 7B and 17E.
+	     ((setq placeholder (c-looking-at-inexpr-block
+				 (c-safe-position containing-sexp paren-state)
+				 nil))
 	      (setq tmpsymbol (if (eq (car placeholder) 'inlambda)
 				  'inline-close
 				'block-close))
@@ -2432,32 +3511,56 @@
 		  (c-add-syntax tmpsymbol (point))
 		(goto-char (cdr placeholder))
 		(back-to-indentation)
-		(c-add-syntax tmpsymbol (point))
+		(c-add-stmt-syntax tmpsymbol t
+				   (c-most-enclosing-brace paren-state (point))
+				   (c-whack-state-after (point) paren-state))
 		(if (/= (point) (cdr placeholder))
 		    (c-add-syntax (car placeholder)))))
 	     ;; CASE 16B: does this close an inline or a function in
 	     ;; an extern block or namespace?
-	     ((progn
-		(goto-char containing-sexp)
-		(setq placeholder (c-search-uplist-for-classkey state)))
-	      (goto-char (aref placeholder 0))
-	      (if (looking-at (concat c-extra-toplevel-key "[^_]"))
-		  (c-add-syntax 'defun-close relpos)
-		(c-add-syntax 'inline-close relpos)))
+	     ((setq placeholder (c-search-uplist-for-classkey paren-state))
+	      (c-backward-to-decl-anchor lim)
+	      (back-to-indentation)
+	      (if (save-excursion
+		    (goto-char (aref placeholder 0))
+		    (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.  Might also trigger it with some macros
+	     ;; followed by blocks, and this gives sane indentation
+	     ;; then too.  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)))))
+	      (back-to-indentation)
+	      (if (/= (point) containing-sexp)
+		  (goto-char placeholder))
+	      (c-add-stmt-syntax 'defun-close t 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
-	     ((and (not inenclosing-p)
-		   (c-most-enclosing-brace state)
-		   (or (not (c-major-mode-is 'pike-mode))
-		       ;; In Pike it can be a defun-close of a
-		       ;; function declared in a statement block.  Let
-		       ;; it through to be handled below.
-		       (or (c-looking-at-bos)
-			   (progn
-			     (c-beginning-of-statement-1)
-			     (looking-at c-conditional-key)))))
-	      (c-add-syntax 'block-close relpos))
+	     ;; block-close.  C.f. case 17H.
+	     ((and (not inenclosing-p) 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
+	      ;; really fixes it better, but we do like this to keep
+	      ;; the indentation compatible with version 5.28 and
+	      ;; earlier.
+	      (while (and (/= (setq placeholder (point)) (c-point 'boi))
+			  (eq (c-beginning-of-statement-1 lim) 'label)))
+	      (goto-char placeholder)
+	      (if (looking-at c-label-kwds-regexp)
+		  (c-add-syntax 'block-close (point))
+		(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 t lim paren-state)))
 	     ;; CASE 16D: find out whether we're closing a top-level
 	     ;; class or a defun
 	     (t
@@ -2465,204 +3568,182 @@
 		(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)
-		    (c-add-syntax 'defun-close relpos)))))
-	     )))
-	 ;; CASE 17: statement catchall
+		      (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)))))
+	      )))
+	 ;; CASE 17: Statement or defun catchall.
 	 (t
-	  ;; we know its a statement, but we need to find out if it is
-	  ;; the first statement in a block
-	  (goto-char containing-sexp)
-	  (forward-char 1)
-	  (c-forward-syntactic-ws indent-point)
-	  ;; now skip forward past any case/default clauses we might find.
-	  (while (or (c-skip-case-statement-forward fullstate indent-point)
-		     (and (looking-at c-switch-label-key)
-			  (not inswitch-p)))
-	    (setq inswitch-p t))
-	  ;; we want to ignore non-case labels when skipping forward
-	  (while (and (looking-at c-label-key)
-		      (goto-char (match-end 0)))
-	    (c-forward-syntactic-ws indent-point))
+	  (goto-char indent-point)
+	  ;; Back up statements until we find one that starts at boi.
+	  (while (let* ((prev-point (point))
+			(last-step-type (c-beginning-of-statement-1
+					 containing-sexp)))
+		   (if (= (point) prev-point)
+		       (progn
+			 (setq step-type (or step-type last-step-type))
+			 nil)
+		     (setq step-type last-step-type)
+		     (/= (point) (c-point 'boi)))))
 	  (cond
-	   ;; CASE 17A: we are inside a case/default clause inside a
-	   ;; switch statement.  find out if we are at the statement
-	   ;; just after the case/default label.
-	   ((and inswitch-p
-		 (progn
-		   (goto-char indent-point)
-		   (c-beginning-of-statement-1 containing-sexp)
-		   (setq placeholder (point))
-		   (beginning-of-line)
-		   (when (re-search-forward c-switch-label-key
-					    (max placeholder (c-point 'eol)) t)
-		     (setq placeholder (match-beginning 0)))))
-	    (goto-char indent-point)
-	    (skip-chars-forward " \t")
-	    (if (eq (char-after) ?{)
-		(c-add-syntax 'statement-case-open placeholder)
-	      (c-add-syntax 'statement-case-intro placeholder)))
 	   ;; CASE 17B: continued statement
-	   ((eq char-before-ip ?,)
-	    (goto-char indent-point)
-	    (c-beginning-of-closest-statement)
-	    (c-add-syntax 'statement-cont (c-point 'boi)))
-	   ;; CASE 17C: a question/colon construct?  But make sure
-	   ;; what came before was not a label, and what comes after
-	   ;; is not a globally scoped function call!
-	   ((or (and (memq char-before-ip '(?: ??))
-		     (save-excursion
-		       (goto-char indent-point)
-		       (c-backward-syntactic-ws lim)
-		       (back-to-indentation)
-		       (not (looking-at c-label-key))))
-		(and (memq char-after-ip '(?: ??))
-		     (save-excursion
-		       (goto-char indent-point)
-		       (skip-chars-forward " \t")
-		       ;; watch out for scope operator
-		       (not (looking-at "::")))))
-	    (goto-char indent-point)
-	    (c-beginning-of-closest-statement)
-	    (c-add-syntax 'statement-cont (c-point 'boi)))
+	   ((and (eq step-type 'same)
+		 (/= (point) indent-point))
+	    (c-add-stmt-syntax 'statement-cont nil
+			       containing-sexp paren-state))
+	   ;; CASE 17A: After a case/default label?
+	   ((progn
+	      (while (and (eq step-type 'label)
+			  (not (looking-at c-label-kwds-regexp)))
+		(setq step-type
+		      (c-beginning-of-statement-1 containing-sexp)))
+	      (eq step-type 'label))
+	    (c-add-stmt-syntax (if (eq char-after-ip ?{)
+				   'statement-case-open
+				 'statement-case-intro)
+			       t containing-sexp paren-state))
 	   ;; CASE 17D: any old statement
-	   ((< (point) indent-point)
-	    (let ((safepos (c-most-enclosing-brace fullstate))
-		  relpos done)
-	      (goto-char indent-point)
-	      (c-beginning-of-statement-1 safepos)
-	      ;; It is possible we're on the brace that opens a nested
-	      ;; function.
-	      (if (and (eq (char-after) ?{)
-		       (save-excursion
-			 (c-backward-syntactic-ws safepos)
-			 (not (eq (char-before) ?\;))))
-		  (c-beginning-of-statement-1 safepos))
-	      (if (and inswitch-p
-		       (looking-at c-switch-label-key))
-		  (progn
-		    (goto-char (match-end 0))
-		    (c-forward-syntactic-ws)))
-	      (setq relpos (c-point 'boi))
-	      (while (and (not done)
-			  (<= safepos (point))
-			  (/= relpos (point)))
-		(c-beginning-of-statement-1 safepos)
-		(if (= relpos (c-point 'boi))
-		    (setq done t))
-		(setq relpos (c-point 'boi)))
-	      (c-add-syntax 'statement relpos)
-	      (if (eq char-after-ip ?{)
-		  (c-add-syntax 'block-open))))
-	   ;; CASE 17E: first statement in an in-expression block
-	   ((setq placeholder
-		  (save-excursion
-		    (goto-char containing-sexp)
-		    (c-looking-at-inexpr-block)))
-	    (goto-char containing-sexp)
+	   ((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 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.
+	      (goto-char containing-sexp)
+	      ;; From here on we have the next containing sexp in lim.
+	      (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 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
+			       (c-safe-position containing-sexp paren-state)
+			       nil))
+	    (setq tmpsymbol (if (eq (car placeholder) 'inlambda)
+				'defun-block-intro
+			      'statement-block-intro))
 	    (back-to-indentation)
-	    (let ((block-intro (if (eq (car placeholder) 'inlambda)
-				   'defun-block-intro
-				 'statement-block-intro)))
-	      (if (= containing-sexp (point))
-		  (c-add-syntax block-intro (point))
-		(goto-char (cdr placeholder))
-		(back-to-indentation)
-		(c-add-syntax block-intro (point))
-		(if (/= (point) (cdr placeholder))
-		    (c-add-syntax (car placeholder)))))
+	    (if (= containing-sexp (point))
+		(c-add-syntax tmpsymbol (point))
+	      (goto-char (cdr placeholder))
+	      (back-to-indentation)
+	      (c-add-stmt-syntax tmpsymbol t
+				 (c-most-enclosing-brace c-state-cache (point))
+				 (c-whack-state-after (point) 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!)
+	   ;; narrowed out by a class (i.e. don't use bod here).
+	   ;; However, we first check for statements that we can
+	   ;; recognize by keywords.  That increases the robustness in
+	   ;; cases where statements are used on the top level,
+	   ;; e.g. in macro definitions.
 	   ((save-excursion
 	      (save-restriction
 		(widen)
-		(goto-char containing-sexp)
-		(c-narrow-out-enclosing-class state containing-sexp)
-		(not (c-most-enclosing-brace state))))
-	    (goto-char containing-sexp)
-	    ;; if not at boi, then defun-opening braces are hung on
-	    ;; right side, so we need a different relpos
-	    (if (/= (point) (c-point 'boi))
-		(progn
-		  (c-backward-syntactic-ws)
-		  (c-safe (c-forward-sexp (if (eq (char-before) ?\))
-					      -1 -2)))
-		  ;; looking at a Java throws clause following a
-		  ;; method's parameter list
-		  (c-beginning-of-statement-1)
-		  ))
-	    (c-add-syntax 'defun-block-intro (c-point 'boi)))
+		(c-narrow-out-enclosing-class paren-state containing-sexp)
+		(not (c-most-enclosing-brace paren-state))))
+	    (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 only occur in Pike.
-	   ((and (c-major-mode-is 'pike-mode)
-		 (progn
-		   (goto-char containing-sexp)
-		   (and (not (c-looking-at-bos))
-			(progn
-			  (c-beginning-of-statement-1)
-			  (not (looking-at c-conditional-key))))))
-	    (c-add-syntax 'defun-block-intro (c-point 'boi)))
-	   ;; CASE 17H: first statement in a block
-	   (t (goto-char containing-sexp)
-	      (if (/= (point) (c-point 'boi))
-		  (c-beginning-of-statement-1
-		   (if (= (point) lim)
-		       (c-safe-position (point) state) lim)))
-	      (c-add-syntax 'statement-block-intro (c-point 'boi))
-	      (if (eq char-after-ip ?{)
-		  (c-add-syntax 'block-open)))
+	   ;; a normal block.  This can occur in Pike and with
+	   ;; e.g. the gcc extensions.  Might also trigger it with
+	   ;; some macros followed by blocks, and this gives sane
+	   ;; indentation then too.  C.f. cases B.3 and 16F.
+	   ((save-excursion
+	      (and (not (c-looking-at-bos))
+		   (eq (c-beginning-of-statement-1 lim nil nil t) 'same)
+		   (setq placeholder (point))))
+	    (back-to-indentation)
+	    (if (/= (point) containing-sexp)
+		(goto-char placeholder))
+	    (c-add-stmt-syntax 'defun-block-intro t lim paren-state))
+	   ;; CASE 17H: First statement in a block.  C.f. case 16C.
+	   (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.
+	    (while (and (/= (setq placeholder (point)) (c-point 'boi))
+			(eq (c-beginning-of-statement-1 lim) 'label)))
+	    (goto-char placeholder)
+	    (if (looking-at c-label-kwds-regexp)
+		(c-add-syntax 'statement-block-intro (point))
+	      (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 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")
-	(cond
-	 ;; are we looking at a comment only line?
-	 ((and (looking-at c-comment-start-regexp)
-	       (/= (c-forward-token-1 0 nil (c-point 'eol)) 0))
+	;; are we looking at a comment only line?
+	(when (and (looking-at c-comment-start-regexp)
+		   (/= (c-forward-token-1 0 nil (c-point 'eol)) 0))
 	  (c-add-syntax 'comment-intro))
-	 ;; we might want to give additional offset to friends (in C++).
-	 ((and (c-major-mode-is 'c++-mode)
-	       (looking-at c-C++-friend-key))
+	;; we might want to give additional offset to friends (in C++).
+	(when (and c-opt-friend-key
+		   (looking-at c-opt-friend-key))
 	  (c-add-syntax 'friend))
-	 ;; Start of a preprocessor directive?
-	 ((and (eq literal 'pound)
-	       (= (save-excursion
-		    (c-beginning-of-macro lim)
-		    (setq placeholder (point)))
-		  (c-point 'boi))
-	       (not (and (c-major-mode-is 'pike-mode)
-			 (eq (char-after (1+ placeholder)) ?\"))))
-	  (c-add-syntax 'cpp-macro)))
+	;; Start of or a continuation of a preprocessor directive?
+	(if (and macro-start
+		 (eq macro-start (c-point 'boi))
+		 (not (and (c-major-mode-is 'pike-mode)
+			   (eq (char-after (1+ macro-start)) ?\"))))
+	    (c-add-syntax 'cpp-macro)
+	  (when (and c-syntactic-indentation-in-macros macro-start)
+	    (if in-macro-expr
+		(when (or (< syntactic-relpos macro-start)
+			  (not (or (assq 'arglist-intro syntax)
+				   (assq 'arglist-cont syntax)
+				   (assq 'arglist-cont-nonempty syntax)
+				   (assq 'arglist-close syntax))))
+		  ;; If inside a cpp expression, i.e. anywhere in a
+		  ;; cpp directive except a #define body, we only let
+		  ;; through the syntactic analysis that is internal
+		  ;; in the expression.  That means the arglist
+		  ;; elements, if they are anchored inside the cpp
+		  ;; expression.
+		  (setq syntax `((cpp-macro-cont . ,macro-start))))
+	      (when (and (eq macro-start syntactic-relpos)
+			 (not (assq 'cpp-define-intro syntax))
+			 (save-excursion
+			   (goto-char macro-start)
+			   (or (not (c-forward-to-cpp-define-body))
+			       (<= (point) (c-point 'boi indent-point)))))
+		;; Inside a #define body and the syntactic analysis is
+		;; anchored on the start of the #define.  In this case
+		;; we add cpp-define-intro to get the extra
+		;; indentation of the #define body.
+		(c-add-syntax 'cpp-define-intro)))))
 	;; return the syntax
 	syntax))))
 
 
 (defun c-echo-parsing-error (&optional quiet)
-  (when (and c-parsing-error (not quiet))
-    (message "%s" c-parsing-error)
-    (ding))
+  (when (and c-report-syntactic-errors c-parsing-error (not quiet))
+    (c-benign-error "%s" c-parsing-error))
   c-parsing-error)
 
-(defun c-shift-line-indentation (shift-amt)
-  (let ((pos (- (point-max) (point)))
-	(col (current-indentation)))
-    (if (zerop shift-amt)
-	nil
-      (delete-region (c-point 'bol) (c-point 'boi))
-      (beginning-of-line)
-      (indent-to (+ col shift-amt)))
-    (if (< (point) (c-point 'boi))
-	(back-to-indentation)
-      ;; If initial point was within line's indentation, position after
-      ;; the indentation.  Else stay at same point in text.
-      (if (> (- (point-max) pos) (point))
-	  (goto-char (- (point-max) pos))))))
-
 (defun c-evaluate-offset (offset langelem symbol)
   ;; offset can be a number, a function, a variable, a list, or one of
   ;; the symbols + or -
@@ -2683,113 +3764,59 @@
       (while (and (not done) offset)
 	(setq done (c-evaluate-offset (car offset) langelem symbol)
 	      offset (cdr offset)))
-      (if (not done)
-	  (if c-strict-syntax-p
-	      (error "No offset found for syntactic symbol %s" symbol))
-	done)))
+      (if (and c-strict-syntax-p (not done))
+	  (c-benign-error "No offset found for syntactic symbol %s" symbol))
+      done))
    (t (symbol-value offset))
    ))
 
 (defun c-get-offset (langelem)
-  ;; Get offset from LANGELEM which is a cons cell of the form:
-  ;; (SYMBOL . RELPOS).  The symbol is matched against
-  ;; c-offsets-alist and the offset found there is either returned,
-  ;; or added to the indentation at RELPOS.  If RELPOS is nil, then
-  ;; the offset is simply returned.
+  "Get offset from LANGELEM which is a cons cell of the form:
+\(SYMBOL . RELPOS).  The symbol is matched against `c-offsets-alist'
+and the offset found there is returned."
   (let* ((symbol (car langelem))
-	 (relpos (cdr langelem))
 	 (match  (assq symbol c-offsets-alist))
 	 (offset (cdr-safe match)))
-    (if (not match)
-	(if c-strict-syntax-p
-	    (error "No offset found for syntactic symbol %s" symbol)
-	  (setq offset 0
-		relpos 0))
-      (setq offset (c-evaluate-offset offset langelem symbol)))
+    (if match
+	(setq offset (c-evaluate-offset offset langelem symbol))
+      (if c-strict-syntax-p
+	  (c-benign-error "No offset found for syntactic symbol %s" symbol))
+      (setq offset 0))
     (if (vectorp offset)
 	offset
-      (+ (if (and relpos
-		  (< relpos (c-point 'bol)))
-	     (save-excursion
-	       (goto-char relpos)
-	       (current-column))
-	   0)
-	 (or (and (numberp offset) offset)
-	     (and (symbolp offset) (symbol-value offset))
-	     0)))
+      (or (and (numberp offset) offset)
+	  (and (symbolp offset) (symbol-value offset))
+	  0))
     ))
 
 (defun c-get-syntactic-indentation (langelems)
-  ;; Apply c-get-offset to a list of langelem cells to get the total
-  ;; syntactic indentation.  Special treatment is needed for vectors
-  ;; containing absolute columns.
-  (let ((indent 0))
+  "Apply `c-get-offset' to a list of langelem cells to get the total
+syntactic indentation.  The anchor position, whose column is used as a
+base for all the collected offsets, is taken from the first element
+with a relpos."
+  ;; Note that topmost-intro always has a relpos 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.
+  (let ((indent 0) anchor)
     (catch 'done
       (while langelems
 	(let ((res (c-get-offset (car langelems))))
 	  (if (vectorp res)
 	      (throw 'done (elt res 0))
+	    (unless anchor
+	      (let ((relpos (cdr (car langelems))))
+		(if relpos
+		    (setq anchor relpos))))
 	    (setq indent (+ indent res)
 		  langelems (cdr langelems)))))
-      indent)))
-
-(defun c-indent-line (&optional syntax quiet)
-  ;; Indent the current line according to the syntactic context, if
-  ;; c-syntactic-indentation is non-nil.  Optional SYNTAX is the
-  ;; syntactic information for the current line.  Be silent about
-  ;; syntactic errors if the optional argument QUIET is non-nil.
-  ;; Returns the amount of indentation change (in columns).
-  (let (shift-amt)
-    (if c-syntactic-indentation
-	(setq c-parsing-error
-	      (or (let* ((c-parsing-error nil)
-			 (c-syntactic-context (or syntax
-						  c-syntactic-context
-						  (c-guess-basic-syntax)))
-			 (indent (c-get-syntactic-indentation c-syntactic-context)))
-		    (and (not (c-echo-parsing-error quiet))
-			 c-echo-syntactic-information-p
-			 (message "syntax: %s, indent: %d"
-				  c-syntactic-context indent))
-		    (setq shift-amt (- indent (current-indentation)))
-		    (c-shift-line-indentation shift-amt)
-		    (run-hooks 'c-special-indent-hook)
-		    c-parsing-error)
-		  c-parsing-error))
-      (let ((indent 0))
-	(save-excursion
-	  (while (and (= (forward-line -1) 0)
-		      (if (looking-at "\\s-*$")
-			  t
-			(back-to-indentation)
-			(setq indent (current-indentation))
-			nil))))
-	(setq shift-amt (- indent (current-indentation)))
-	(c-shift-line-indentation shift-amt)))
-    shift-amt))
-
-(defun c-show-syntactic-information (arg)
-  "Show syntactic information for current line.
-With universal argument, inserts the analysis as a comment on that line."
-  (interactive "P")
-  (let ((syntax (c-guess-basic-syntax)))
-    (if (not (consp arg))
-	(message "syntactic analysis: %s" syntax)
-      (indent-for-comment)
-      (insert (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."
-  (interactive "*r")
-  (save-excursion
-    (save-restriction
-      (narrow-to-region from to)
-      (goto-char (point-min))
-      (while (not (eobp))
-	(c-show-syntactic-information '(0))
-	(forward-line)))))
+      (+ indent
+	 (if anchor
+	     (save-excursion
+	       (goto-char anchor)
+	       (current-column))
+	   0)))))
 
 
 (cc-provide 'cc-engine)