]> code.delx.au - gnu-emacs/blobdiff - lisp/progmodes/cc-engine.el
Fix shell handling of unbalanced quotes and parens in output.
[gnu-emacs] / lisp / progmodes / cc-engine.el
index ea0a8f2d3b3490e6f3bc064a3a30eb485dd4a1df..2aa04cb2b0b14dc54084dccff83107594f690bfa 100644 (file)
@@ -1,6 +1,6 @@
 ;;; cc-engine.el --- core syntax guessing engine for CC mode
 
-;; Copyright (C) 1985, 1987, 1992-2011  Free Software Foundation, Inc.
+;; Copyright (C) 1985, 1987, 1992-2012  Free Software Foundation, Inc.
 
 ;; Authors:    2001- Alan Mackenzie
 ;;             1998- Martin Stjernholm
       (not prevstate)
     (> arg 0)))
 
-;; Dynamically bound cache for `c-in-literal'.
-(defvar c-in-literal-cache t)
-
 \f
 ;; Basic handling of preprocessor directives.
 
               (point))))
     c-macro-start))
 
+;; One element macro cache to cope with continual movement within very large
+;; CPP macros.
+(defvar c-macro-cache nil)
+(make-variable-buffer-local 'c-macro-cache)
+;; Nil or cons of the bounds of the most recent CPP form probed by
+;; `c-beginning-of-macro', `c-end-of-macro' or `c-syntactic-end-of-macro'.
+;; The cdr will be nil if we know only the start of the CPP form.
+(defvar c-macro-cache-start-pos nil)
+(make-variable-buffer-local 'c-macro-cache-start-pos)
+;; The starting position from where we determined `c-macro-cache'.
+(defvar c-macro-cache-syntactic nil)
+(make-variable-buffer-local 'c-macro-cache-syntactic)
+;; non-nil iff `c-macro-cache' has both elements set AND the cdr is at a
+;; syntactic end of macro, not merely an apparent one.
+
+(defun c-invalidate-macro-cache (beg end)
+  ;; Called from a before-change function.  If the change region is before or
+  ;; in the macro characterized by `c-macro-cache' etc., nullify it
+  ;; appropriately.  BEG and END are the standard before-change-functions
+  ;; parameters.  END isn't used.
+  (cond
+   ((null c-macro-cache))
+   ((< beg (car c-macro-cache))
+    (setq c-macro-cache nil
+         c-macro-cache-start-pos nil
+         c-macro-cache-syntactic nil))
+   ((and (cdr c-macro-cache)
+        (< beg (cdr c-macro-cache)))
+    (setcdr c-macro-cache nil)
+    (setq c-macro-cache-start-pos beg
+         c-macro-cache-syntactic nil))))
+
 (defun c-beginning-of-macro (&optional lim)
   "Go to the beginning of a preprocessor directive.
 Leave point at the beginning of the directive and return t if in one,
@@ -229,19 +258,36 @@ otherwise return nil and leave point unchanged.
 
 Note that this function might do hidden buffer changes.  See the
 comment at the start of cc-engine.el for more info."
-  (when c-opt-cpp-prefix
-    (let ((here (point)))
-      (save-restriction
-       (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 c-opt-cpp-start))
-           t
-         (goto-char here)
-         nil)))))
+  (let ((here (point)))
+    (when c-opt-cpp-prefix
+      (if (and (car c-macro-cache)
+              (>= (point) (car c-macro-cache))
+              (or (and (cdr c-macro-cache)
+                       (<= (point) (cdr c-macro-cache)))
+                  (<= (point) c-macro-cache-start-pos)))
+         (unless (< (car c-macro-cache) (or lim (point-min)))
+           (progn (goto-char (max (or lim (point-min)) (car c-macro-cache)))
+                  (setq c-macro-cache-start-pos
+                        (max c-macro-cache-start-pos here))
+                  t))
+       (setq c-macro-cache nil
+             c-macro-cache-start-pos nil
+             c-macro-cache-syntactic nil)
+
+       (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 c-opt-cpp-start))
+             (progn
+               (setq c-macro-cache (cons (point) nil)
+                     c-macro-cache-start-pos here)
+               t)
+           (goto-char here)
+           nil))))))
 
 (defun c-end-of-macro ()
   "Go to the end of a preprocessor directive.
@@ -251,12 +297,24 @@ done that the point is inside a cpp directive to begin with.
 
 Note that this function might do hidden buffer changes.  See the
 comment at the start of cc-engine.el for more info."
-  (while (progn
-          (end-of-line)
-          (when (and (eq (char-before) ?\\)
-                     (not (eobp)))
-            (forward-char)
-            t))))
+   (if (and (cdr c-macro-cache)
+           (<= (point) (cdr c-macro-cache))
+           (>= (point) (car c-macro-cache)))
+       (goto-char (cdr c-macro-cache))
+     (unless (and (car c-macro-cache)
+                 (<= (point) c-macro-cache-start-pos)
+                 (>= (point) (car c-macro-cache)))
+       (setq c-macro-cache nil
+            c-macro-cache-start-pos nil
+            c-macro-cache-syntactic nil))
+     (while (progn
+             (end-of-line)
+             (when (and (eq (char-before) ?\\)
+                        (not (eobp)))
+               (forward-char)
+               t)))
+     (when (car c-macro-cache)
+       (setcdr c-macro-cache (point)))))
 
 (defun c-syntactic-end-of-macro ()
   ;; Go to the end of a CPP directive, or a "safe" pos just before.
@@ -271,12 +329,15 @@ comment at the start of cc-engine.el for more info."
   ;; at the start of cc-engine.el for more info.
   (let* ((here (point))
         (there (progn (c-end-of-macro) (point)))
-        (s (parse-partial-sexp here there)))
-    (while (and (or (nth 3 s)   ; in a string
-                   (nth 4 s))   ; in a comment (maybe at end of line comment)
-               (> there here))  ; No infinite loops, please.
-      (setq there (1- (nth 8 s)))
-      (setq s (parse-partial-sexp here there)))
+        s)
+    (unless c-macro-cache-syntactic
+      (setq s (parse-partial-sexp here there))
+      (while (and (or (nth 3 s)         ; in a string
+                     (nth 4 s)) ; in a comment (maybe at end of line comment)
+                 (> there here))       ; No infinite loops, please.
+       (setq there (1- (nth 8 s)))
+       (setq s (parse-partial-sexp here there)))
+      (setq c-macro-cache-syntactic (car c-macro-cache)))
     (point)))
 
 (defun c-forward-over-cpp-define-id ()
@@ -893,7 +954,7 @@ comment at the start of cc-engine.el for more info."
                          ((eq sym 'while)
                           ;; Is this a real while, or a do-while?
                           ;; The next `when' triggers unless we are SURE that
-                          ;; the `while' is not the tailend of a `do-while'.
+                          ;; the `while' is not the tail end of a `do-while'.
                           (when (or (not pptok)
                                     (memq (char-after pptok) delims)
                                     ;; The following kludge is to prevent
@@ -988,7 +1049,7 @@ comment at the start of cc-engine.el for more info."
                         ;; Just gone back over an ordinary symbol of some sort?
                         (t (c-crosses-statement-barrier-p
                             (point) maybe-after-boundary-pos))))
-       
+
                  (when boundary-pos
                    (setq pptok ptok
                          ptok tok
@@ -1065,7 +1126,7 @@ comment at the start of cc-engine.el for more info."
                    pos tok) ; always non-nil
              )              ; end of (catch loop ....)
          )                  ; end of sexp-at-a-time (while ....)
-       
+
        ;; If the stack isn't empty there might be errors to report.
        (while stack
          (if (and (vectorp saved-pos) (eq (length saved-pos) 3))
@@ -1185,7 +1246,7 @@ comment at the start of cc-engine.el for more info."
                       (c-at-vsemi-p))))
              (throw 'done vsemi-pos))
             ;; In a string/comment?
-            ((setq lit-range (c-literal-limits))
+            ((setq lit-range (c-literal-limits from))
              (goto-char (cdr lit-range)))
             ((eq (char-after) ?:)
              (forward-char)
@@ -1627,6 +1688,7 @@ comment at the start of cc-engine.el for more info."
        ;; high as possible.
        (setq rung-pos (point)))
 
+      (with-silent-modifications
       (while
          (progn
            (while
@@ -1782,7 +1844,7 @@ comment at the start of cc-engine.el for more info."
                (1- last-put-in-sws-pos))
               (c-remove-is-and-in-sws (1- last-put-in-sws-pos)
                                       last-put-in-sws-pos))))
-      )))
+      ))))
 
 (defun c-backward-sws ()
   ;; Used by `c-backward-syntactic-ws' to implement the unbounded search.
@@ -1795,7 +1857,7 @@ comment at the start of cc-engine.el for more info."
        rung-is-marked simple-ws-beg cmt-skip-pos)
 
     ;; Skip simple horizontal ws and do a quick check on the preceding
-    ;; character to see if it's anying that can't end syntactic ws, so we can
+    ;; character to see if it's anything that can't end syntactic ws, so we can
     ;; bail out early in the majority of cases when there just are a few ws
     ;; chars.  Newlines are complicated in the backward direction, so we can't
     ;; skip over them.
@@ -1820,6 +1882,7 @@ comment at the start of cc-engine.el for more info."
          (goto-char (setq rung-pos rung-is-marked))
        (goto-char simple-ws-beg))
 
+      (with-silent-modifications
       (while
          (progn
            (while
@@ -2005,7 +2068,7 @@ comment at the start of cc-engine.el for more info."
                last-put-in-sws-pos)
               (c-remove-is-and-in-sws last-put-in-sws-pos
                                       (1+ last-put-in-sws-pos)))))
-      )))
+      ))))
 
 \f
 ;; Other whitespace tools
@@ -2032,7 +2095,7 @@ comment at the start of cc-engine.el for more info."
 (defconst c-state-cache-too-far 5000)
 ;; A maximum comfortable scanning distance, e.g. between
 ;; `c-state-cache-good-pos' and "HERE" (where we call c-parse-state).  When
-;; this distance is exceeded, we take "emergency meausures", e.g. by clearing
+;; this distance is exceeded, we take "emergency measures", e.g. by clearing
 ;; the cache and starting again from point-min or a beginning of defun.  This
 ;; value can be tuned for efficiency or set to a lower value for testing.
 
@@ -2077,7 +2140,7 @@ comment at the start of cc-engine.el for more info."
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; We maintain a simple cache of positions which aren't in a literal, so as to
 ;; speed up testing for non-literality.
-(defconst c-state-nonlit-pos-interval 10000)
+(defconst c-state-nonlit-pos-interval 3000)
 ;; The approximate interval between entries in `c-state-nonlit-pos-cache'.
 
 (defvar c-state-nonlit-pos-cache nil)
@@ -2092,29 +2155,48 @@ comment at the start of cc-engine.el for more info."
 ;; reduced by buffer changes, and increased by invocations of
 ;; `c-state-literal-at'.
 
+(defvar c-state-semi-nonlit-pos-cache nil)
+(make-variable-buffer-local 'c-state-semi-nonlit-pos-cache)
+;; A list of buffer positions which are known not to be in a literal.  This is
+;; ordered with higher positions at the front of the list.  Only those which
+;; are less than `c-state-semi-nonlit-pos-cache-limit' are valid.
+
+(defvar c-state-semi-nonlit-pos-cache-limit 1)
+(make-variable-buffer-local 'c-state-semi-nonlit-pos-cache-limit)
+;; An upper limit on valid entries in `c-state-semi-nonlit-pos-cache'.  This is
+;; reduced by buffer changes, and increased by invocations of
+;; `c-state-literal-at'.  FIXME!!!
+
 (defsubst c-state-pp-to-literal (from to)
-  ;; Do a parse-partial-sexp from FROM to TO, returning the bounds of any
-  ;; literal at TO as a cons, otherwise NIL.
-  ;; FROM must not be in a literal, and the buffer should already be wide
-  ;; enough.
+  ;; Do a parse-partial-sexp from FROM to TO, returning either
+  ;;     (STATE TYPE (BEG . END))     if TO is in a literal; or
+  ;;     (STATE)                      otherwise,
+  ;; where STATE is the parsing state at TO, TYPE is the type of the literal
+  ;; (one of 'c, 'c++, 'string) and (BEG . END) is the boundaries of the literal.
+  ;;
+  ;; Only elements 3 (in a string), 4 (in a comment), 5 (following a quote),
+  ;; 7 (comment type) and 8 (start of comment/string) (and possibly 9) of
+  ;; STATE are valid.
   (save-excursion
-    (let ((s (parse-partial-sexp from to)))
+    (let ((s (parse-partial-sexp from to))
+         ty)
       (when (or (nth 3 s) (nth 4 s))   ; in a string or comment
+       (setq ty (cond
+                 ((nth 3 s) 'string)
+                 ((eq (nth 7 s) t) 'c++)
+                 (t 'c)))
        (parse-partial-sexp (point) (point-max)
                            nil                  ; TARGETDEPTH
                            nil                  ; STOPBEFORE
                            s                    ; OLDSTATE
-                           'syntax-table)       ; stop at end of literal
-       (cons (nth 8 s) (point))))))
+                           'syntax-table))      ; stop at end of literal
+      (if ty
+         `(,s ,ty (,(nth 8 s) . ,(point)))
+       `(,s)))))
 
-(defun c-state-literal-at (here)
-  ;; If position HERE is inside a literal, return (START . END), the
-  ;; boundaries of the literal (which may be outside the accessible bit of the
-  ;; buffer).  Otherwise, return nil.
-  ;;
-  ;; This function is almost the same as `c-literal-limits'.  It differs in
-  ;; that it is a lower level function, and that it rigourously follows the
-  ;; syntax from BOB, whereas `c-literal-limits' uses a "local" safe position.
+(defun c-state-safe-place (here)
+  ;; Return a buffer position before HERE which is "safe", i.e. outside any
+  ;; string, comment, or macro.
   ;;
   ;; NOTE: This function manipulates `c-state-nonlit-pos-cache'.  This cache
   ;; MAY NOT contain any positions within macros, since macros are frequently
@@ -2125,32 +2207,107 @@ comment at the start of cc-engine.el for more info."
     (widen)
     (save-excursion
       (let ((c c-state-nonlit-pos-cache)
-           pos npos lit)
+           pos npos high-pos lit macro-beg macro-end)
        ;; Trim the cache to take account of buffer changes.
        (while (and c (> (car c) c-state-nonlit-pos-cache-limit))
          (setq c (cdr c)))
        (setq c-state-nonlit-pos-cache c)
 
        (while (and c (> (car c) here))
+         (setq high-pos (car c))
          (setq c (cdr c)))
        (setq pos (or (car c) (point-min)))
 
-       (while (<= (setq npos (+ pos c-state-nonlit-pos-interval))
-                  here)
-         (setq lit (c-state-pp-to-literal pos npos))
-         (setq pos (or (cdr lit) npos)) ; end of literal containing npos.
-         (goto-char pos)
-         (when (and (c-beginning-of-macro) (/= (point) pos))
-           (c-syntactic-end-of-macro)
-           (or (eobp) (forward-char))
-           (setq pos (point)))
-         (setq c-state-nonlit-pos-cache (cons pos c-state-nonlit-pos-cache)))
+       (unless high-pos
+         (while
+             ;; Add an element to `c-state-nonlit-pos-cache' each iteration.
+             (and
+              (<= (setq npos (+ pos c-state-nonlit-pos-interval)) here)
+
+              ;; Test for being in a literal.  If so, go to after it.
+              (progn
+                (setq lit (car (cddr (c-state-pp-to-literal pos npos))))
+                (or (null lit)
+                    (prog1 (<= (cdr lit) here)
+                      (setq npos (cdr lit)))))
+
+              ;; Test for being in a macro.  If so, go to after it.
+              (progn
+                (goto-char npos)
+                (setq macro-beg
+                      (and (c-beginning-of-macro) (/= (point) npos) (point)))
+                (when macro-beg
+                  (c-syntactic-end-of-macro)
+                  (or (eobp) (forward-char))
+                  (setq macro-end (point)))
+                (or (null macro-beg)
+                    (prog1 (<= macro-end here)
+                      (setq npos macro-end)))))
+
+           (setq pos npos)
+           (setq c-state-nonlit-pos-cache (cons pos c-state-nonlit-pos-cache)))
+         ;; Add one extra element above HERE so as to to avoid the previous
+         ;; expensive calculation when the next call is close to the current
+         ;; one.  This is especially useful when inside a large macro.
+         (setq c-state-nonlit-pos-cache (cons npos c-state-nonlit-pos-cache)))
 
        (if (> pos c-state-nonlit-pos-cache-limit)
            (setq c-state-nonlit-pos-cache-limit pos))
-       (if (< pos here)
-           (setq lit (c-state-pp-to-literal pos here)))
-       lit))))
+       pos))))
+
+(defun c-state-semi-safe-place (here)
+  ;; Return a buffer position before HERE which is "safe", i.e. outside any
+  ;; string or comment.  It may be in a macro.
+  (save-restriction
+    (widen)
+    (save-excursion
+      (let ((c c-state-semi-nonlit-pos-cache)
+           pos npos high-pos lit macro-beg macro-end)
+       ;; Trim the cache to take account of buffer changes.
+       (while (and c (> (car c) c-state-semi-nonlit-pos-cache-limit))
+         (setq c (cdr c)))
+       (setq c-state-semi-nonlit-pos-cache c)
+       
+       (while (and c (> (car c) here))
+         (setq high-pos (car c))
+         (setq c (cdr c)))
+       (setq pos (or (car c) (point-min)))
+       
+       (unless high-pos
+         (while
+             ;; Add an element to `c-state-semi-nonlit-pos-cache' each iteration.
+             (and
+              (<= (setq npos (+ pos c-state-nonlit-pos-interval)) here)
+              
+              ;; Test for being in a literal.  If so, go to after it.
+              (progn
+                (setq lit (car (cddr (c-state-pp-to-literal pos npos))))
+                (or (null lit)
+                    (prog1 (<= (cdr lit) here)
+                      (setq npos (cdr lit))))))
+              
+           (setq pos npos)
+           (setq c-state-semi-nonlit-pos-cache
+                 (cons pos c-state-semi-nonlit-pos-cache))))
+
+       (if (> pos c-state-semi-nonlit-pos-cache-limit)
+           (setq c-state-semi-nonlit-pos-cache-limit pos))
+       pos))))
+
+(defun c-state-literal-at (here)
+  ;; If position HERE is inside a literal, return (START . END), the
+  ;; boundaries of the literal (which may be outside the accessible bit of the
+  ;; buffer).  Otherwise, return nil.
+  ;;
+  ;; This function is almost the same as `c-literal-limits'.  Previously, it
+  ;; differed in that it was a lower level function, and that it rigorously
+  ;; followed the syntax from BOB.  `c-literal-limits' is now (2011-12)
+  ;; virtually identical to this function.
+  (save-restriction
+    (widen)
+    (save-excursion
+      (let ((pos (c-state-safe-place here)))
+           (car (cddr (c-state-pp-to-literal pos here)))))))
 
 (defsubst c-state-lit-beg (pos)
   ;; Return the start of the literal containing POS, or POS itself.
@@ -2302,7 +2459,7 @@ comment at the start of cc-engine.el for more info."
 ;; `c-parse-state', or nil.
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Defuns which analyse the buffer, yet don't change `c-state-cache'.
+;; Defuns which analyze the buffer, yet don't change `c-state-cache'.
 (defun c-get-fallback-scan-pos (here)
   ;; Return a start position for building `c-state-cache' from
   ;; scratch.  This will be at the top level, 2 defuns back.
@@ -2331,7 +2488,7 @@ comment at the start of cc-engine.el for more info."
   ;;
   ;; If there aren't enough opening paren/brace/brackets, return the position
   ;; of the outermost one found, or HERE- if there are none.  If there are no
-  ;; closeing p/b/bs between HERE+ and TOP, return HERE-.  HERE-/+ and TOP
+  ;; closing p/b/bs between HERE+ and TOP, return HERE-.  HERE-/+ and TOP
   ;; must not be inside literals.  Only the accessible portion of the buffer
   ;; will be scanned.
 
@@ -2364,7 +2521,7 @@ comment at the start of cc-engine.el for more info."
 
 (defun c-parse-state-get-strategy (here good-pos)
   ;; Determine the scanning strategy for adjusting `c-parse-state', attempting
-  ;; to minimise the amount of scanning.  HERE is the pertinent position in
+  ;; to minimize the amount of scanning.  HERE is the pertinent position in
   ;; the buffer, GOOD-POS is a position where `c-state-cache' (possibly with
   ;; its head trimmed) is known to be good, or nil if there is no such
   ;; position.
@@ -2457,13 +2614,24 @@ comment at the start of cc-engine.el for more info."
   (setq c-state-point-min (point-min)))
 
 (defun c-append-lower-brace-pair-to-state-cache (from &optional upper-lim)
-  ;; If there is a brace pair preceding FROM in the buffer (not necessarily
-  ;; immediately preceding), push a cons onto `c-state-cache' to represent it.
-  ;; FROM must not be inside a literal.  If UPPER-LIM is non-nil, we append
-  ;; the highest brace pair whose "}" is below UPPER-LIM.
+  ;; If there is a brace pair preceding FROM in the buffer, at the same level
+  ;; of nesting (not necessarily immediately preceding), push a cons onto
+  ;; `c-state-cache' to represent it.  FROM must not be inside a literal.  If
+  ;; UPPER-LIM is non-nil, we append the highest brace pair whose "}" is below
+  ;; UPPER-LIM.
   ;;
   ;; Return non-nil when this has been done.
   ;;
+  ;; The situation it copes with is this transformation:
+  ;;
+  ;; OLD:   {                       (.)    {...........}
+  ;;                                       ^             ^
+  ;;                                     FROM          HERE
+  ;;                                     
+  ;; NEW:   {             {....}    (.)    {.........
+  ;;                         ^           ^           ^
+  ;;                LOWER BRACE PAIR   HERE   or   HERE
+  ;;                                       
   ;; This routine should be fast.  Since it can get called a LOT, we maintain
   ;; `c-state-brace-pair-desert', a small cache of "failures", such that we
   ;; reduce the time wasted in repeated fruitless searches in brace deserts.
@@ -2482,10 +2650,25 @@ comment at the start of cc-engine.el for more info."
        (unless (and c-state-brace-pair-desert
                     (eq cache-pos (car c-state-brace-pair-desert))
                     (<= from (cdr c-state-brace-pair-desert)))
-         ;; Only search what we absolutely need to:
-         (if (and c-state-brace-pair-desert
-                  (eq cache-pos (car c-state-brace-pair-desert)))
-             (narrow-to-region (cdr c-state-brace-pair-desert) (point-max)))
+         ;; DESERT-LIM.  Only search what we absolutely need to,
+         (let ((desert-lim
+                (and c-state-brace-pair-desert
+                     (eq cache-pos (car c-state-brace-pair-desert))
+                     (cdr c-state-brace-pair-desert)))
+               ;; CACHE-LIM.  This limit will be necessary when an opening
+               ;; paren at `cache-pos' has just had its matching close paren
+               ;; inserted.  `cache-pos' continues to be a search bound, even
+               ;; though the algorithm below would skip over the new paren
+               ;; pair.
+               (cache-lim (and cache-pos (< cache-pos from) cache-pos)))
+           (narrow-to-region
+               (cond
+                ((and desert-lim cache-lim)
+                 (max desert-lim cache-lim))
+                (desert-lim)
+                (cache-lim)
+                ((point-min)))
+               (point-max)))
 
          ;; In the next pair of nested loops, the inner one moves back past a
          ;; pair of (mis-)matching parens or brackets; the outer one moves
@@ -2519,7 +2702,7 @@ comment at the start of cc-engine.el for more info."
                          (cons new-cons (cdr c-state-cache))))
                 (t (setq c-state-cache (cons new-cons c-state-cache)))))
 
-           ;; We haven't found a brace pair.  Record this.
+           ;; We haven't found a brace pair.  Record this in the cache.
            (setq c-state-brace-pair-desert (cons cache-pos from))))))))
 
 (defsubst c-state-push-any-brace-pair (bra+1 macro-start-or-here)
@@ -2548,7 +2731,7 @@ comment at the start of cc-engine.el for more info."
                        c-state-cache)))
        ;; N.B.  This defsubst codes one method for the simple, normal case,
        ;; and a more sophisticated, slower way for the general case.  Don't
-       ;; eliminate this defsubst - it's a speed optimisation.
+       ;; eliminate this defsubst - it's a speed optimization.
        (c-append-lower-brace-pair-to-state-cache (1- bra+1)))))
 
 (defun c-append-to-state-cache (from)
@@ -2577,7 +2760,7 @@ comment at the start of cc-engine.el for more info."
        mstart)               ; start of a macro.
 
     (save-excursion
-      ;; Each time round the following loop, we enter a succesively deeper
+      ;; Each time round the following loop, we enter a successively deeper
       ;; level of brace/paren nesting.  (Except sometimes we "continue at
       ;; the existing level".)  `pa+1' is a pos inside an opening
       ;; brace/paren/bracket, usually just after it.
@@ -2788,7 +2971,7 @@ comment at the start of cc-engine.el for more info."
   ;;
   ;; This function must only be called only when (> `c-state-cache-good-pos'
   ;; HERE).  Usually the gap between CACHE-POS and HERE is large.  It is thus
-  ;; optimised to eliminate (or minimise) scanning between these two
+  ;; optimized to eliminate (or minimize) scanning between these two
   ;; positions.
   ;;
   ;; Return a three element list (GOOD-POS SCAN-BACK-POS FWD-FLAG), where:
@@ -2820,7 +3003,7 @@ comment at the start of cc-engine.el for more info."
                                        ; or `here' itself.
        here- here+                  ; start/end of macro around HERE, or HERE
        (here-bol (c-point 'bol here))
-       (too-far-back (max (- here c-state-cache-too-far) 1)))
+       (too-far-back (max (- here c-state-cache-too-far) (point-min))))
 
     ;; Remove completely irrelevant entries from `c-state-cache'.
     (while (and c-state-cache
@@ -2908,6 +3091,8 @@ comment at the start of cc-engine.el for more info."
        c-state-cache-good-pos 1
        c-state-nonlit-pos-cache nil
        c-state-nonlit-pos-cache-limit 1
+       c-state-semi-nonlit-pos-cache nil
+       c-state-semi-nonlit-pos-cache-limit 1
        c-state-brace-pair-desert nil
        c-state-point-min 1
        c-state-point-min-lit-type nil
@@ -2951,9 +3136,11 @@ comment at the start of cc-engine.el for more info."
   ;;
   ;; This function is called from c-after-change.
 
-  ;; The cache of non-literals:
+  ;; The caches of non-literals:
   (if (< here c-state-nonlit-pos-cache-limit)
       (setq c-state-nonlit-pos-cache-limit here))
+  (if (< here c-state-semi-nonlit-pos-cache-limit)
+      (setq c-state-semi-nonlit-pos-cache-limit here))
 
   ;; `c-state-cache':
   ;; Case 1: if `here' is in a literal containing point-min, everything
@@ -2964,9 +3151,9 @@ comment at the start of cc-engine.el for more info."
            c-state-cache-good-pos nil
            c-state-min-scan-pos nil)
 
-;;; Truncate `c-state-cache' and set `c-state-cache-good-pos' to a value below
-;;; `here'.  To maintain its consistency, we may need to insert a new brace
-;;; pair.
+    ;; Truncate `c-state-cache' and set `c-state-cache-good-pos' to a value
+    ;; below `here'.  To maintain its consistency, we may need to insert a new
+    ;; brace pair.
     (let ((here-bol (c-point 'bol here))
          too-high-pa             ; recorded {/(/[ next above here, or nil.
          dropped-cons            ; was the last removed element a brace pair?
@@ -3093,8 +3280,7 @@ comment at the start of cc-engine.el for more info."
              (if scan-forward-p
                  (progn (narrow-to-region (point-min) here)
                         (c-append-to-state-cache good-pos))
-
-               (c-get-cache-scan-pos good-pos))))
+               good-pos)))
 
        (t ; (eq strategy 'IN-LIT)
        (setq c-state-cache nil
@@ -3166,6 +3352,8 @@ comment at the start of cc-engine.el for more info."
           c-state-cache-good-pos
           c-state-nonlit-pos-cache
           c-state-nonlit-pos-cache-limit
+          c-state-semi-nonlit-pos-cache
+          c-state-semi-nonlit-pos-cache-limit
           c-state-brace-pair-desert
           c-state-point-min
           c-state-point-min-lit-type
@@ -4051,7 +4239,7 @@ comment at the start of cc-engine.el for more info."
                     ;; a relevant match.
                     (goto-char pos)
                     nil))))))
-            
+
          (> (point)
             (progn
               ;; Skip syntactic ws afterwards so that we don't stop at the
@@ -4181,7 +4369,7 @@ comment at the start of cc-engine.el for more info."
 \f
 ;; Tools for handling comments and string literals.
 
-(defun c-slow-in-literal (&optional lim detect-cpp)
+(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
@@ -4194,67 +4382,14 @@ The last point calculated is cached if the cache is enabled, i.e. if
 
 Note that this function might do hidden buffer changes.  See the
 comment at the start of cc-engine.el for more info."
-
-  (if (and (vectorp c-in-literal-cache)
-          (= (point) (aref c-in-literal-cache 0)))
-      (aref c-in-literal-cache 1)
-    (let ((rtn (save-excursion
-                (let* ((pos (point))
-                       (lim (or lim (progn
-                                      (c-beginning-of-syntax)
-                                      (point))))
-                       (state (parse-partial-sexp lim pos)))
-                  (cond
-                   ((elt state 3) 'string)
-                   ((elt state 4) (if (elt state 7) 'c++ 'c))
-                   ((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)
-         (setq c-in-literal-cache (vector (point) rtn)))
-      rtn)))
-
-;; 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 only used to detect
-;; cpp directives.
-;;
-;; Note that there is a bug in Xemacs's buffer-syntactic-context when used in
-;; conjunction with syntax-table-properties.  The bug is present in, e.g.,
-;; Xemacs 21.4.4.  It manifested itself thus:
-;;
-;; Starting with an empty AWK Mode buffer, type
-;; /regexp/ {<C-j>
-;; Point gets wrongly left at column 0, rather than being indented to tab-width.
-;;
-;; AWK Mode is designed such that when the first / is typed, it gets the
-;; syntax-table property "string fence".  When the second / is typed, BOTH /s
-;; are given the s-t property "string".  However, buffer-syntactic-context
-;; fails to take account of the change of the s-t property on the opening / to
-;; "string", and reports that the { is within a string started by the second /.
-;;
-;; The workaround for this is for the AWK Mode initialisation to switch the
-;; defalias for c-in-literal to c-slow-in-literal.  This will slow down other
-;; cc-modes in Xemacs whenever an awk-buffer has been initialised.
-;;
-;; (Alan Mackenzie, 2003/4/30).
-
-(defun c-fast-in-literal (&optional lim detect-cpp)
-  ;; This function might do hidden buffer changes.
-  (let ((context (buffer-syntactic-context)))
-    (cond
-     ((eq context 'string) 'string)
-     ((eq context 'comment) 'c++)
-     ((eq context 'block-comment) 'c)
-     ((and detect-cpp (save-excursion (c-beginning-of-macro lim))) 'pound))))
-
-(defalias 'c-in-literal
-  (if (fboundp 'buffer-syntactic-context)
-    'c-fast-in-literal                  ; XEmacs
-    'c-slow-in-literal))                ; GNU Emacs
-
-;; The defalias above isn't enough to shut up the byte compiler.
-(cc-bytecomp-defun c-in-literal)
+  (save-restriction
+    (widen)
+    (let* ((safe-place (c-state-semi-safe-place (point)))
+          (lit (c-state-pp-to-literal safe-place (point))))
+      (or (cadr lit)
+         (and detect-cpp
+              (save-excursion (c-beginning-of-macro))
+              'pound)))))
 
 (defun c-literal-limits (&optional lim near not-in-delimiter)
   "Return a cons of the beginning and end positions of the comment or
@@ -4273,64 +4408,57 @@ comment at the start of cc-engine.el for more info."
 
   (save-excursion
     (let* ((pos (point))
-          (lim (or lim (progn
-                         (c-beginning-of-syntax)
-                         (point))))
-          (state (parse-partial-sexp lim pos)))
-
-      (cond ((elt state 3)             ; String.
-            (goto-char (elt state 8))
-            (cons (point) (or (c-safe (c-forward-sexp 1) (point))
-                              (point-max))))
-
-           ((elt state 4)              ; Comment.
-            (goto-char (elt state 8))
-            (cons (point) (progn (c-forward-single-comment) (point))))
-
-           ((and (not not-in-delimiter)
-                 (not (elt state 5))
-                 (eq (char-before) ?/)
-                 (looking-at "[/*]"))
-            ;; We're standing in a comment starter.
-            (backward-char 1)
-            (cons (point) (progn (c-forward-single-comment) (point))))
-
-           (near
-            (goto-char pos)
-
-            ;; Search forward for a literal.
-            (skip-chars-forward " \t")
+          (lim (or lim (c-state-semi-safe-place pos)))
+          (pp-to-lit (save-restriction
+                       (widen)
+                       (c-state-pp-to-literal lim pos)))
+          (state (car pp-to-lit))
+          (lit-limits (car (cddr pp-to-lit))))
 
-            (cond
-             ((looking-at c-string-limit-regexp) ; String.
-              (cons (point) (or (c-safe (c-forward-sexp 1) (point))
-                                (point-max))))
+      (cond
+       (lit-limits)
+       ((and (not not-in-delimiter)
+            (not (elt state 5))
+            (eq (char-before) ?/)
+            (looking-at "[/*]")) ; FIXME!!! use c-line/block-comment-starter.  2008-09-28.
+       ;; We're standing in a comment starter.
+       (backward-char 1)
+       (cons (point) (progn (c-forward-single-comment) (point))))
+
+       (near
+       (goto-char pos)
+       ;; Search forward for a literal.
+       (skip-chars-forward " \t")
+       (cond
+        ((looking-at c-string-limit-regexp) ; String.
+         (cons (point) (or (c-safe (c-forward-sexp 1) (point))
+                           (point-max))))
 
-             ((looking-at c-comment-start-regexp) ; Line or block comment.
-              (cons (point) (progn (c-forward-single-comment) (point))))
+        ((looking-at c-comment-start-regexp) ; Line or block comment.
+         (cons (point) (progn (c-forward-single-comment) (point))))
 
-             (t
-              ;; Search backward.
-              (skip-chars-backward " \t")
+        (t
+         ;; Search backward.
+         (skip-chars-backward " \t")
 
-              (let ((end (point)) beg)
-                (cond
-                 ((save-excursion
-                    (< (skip-syntax-backward c-string-syntax) 0)) ; String.
-                  (setq beg (c-safe (c-backward-sexp 1) (point))))
-
-                 ((and (c-safe (forward-char -2) t)
-                       (looking-at "*/"))
-                  ;; Block comment.  Due to the nature of line
-                  ;; comments, they will always be covered by the
-                  ;; normal case above.
-                  (goto-char end)
-                  (c-backward-single-comment)
-                  ;; If LIM is bogus, beg will be bogus.
-                  (setq beg (point))))
-
-                (if beg (cons beg end))))))
-           ))))
+         (let ((end (point)) beg)
+           (cond
+            ((save-excursion
+               (< (skip-syntax-backward c-string-syntax) 0)) ; String.
+             (setq beg (c-safe (c-backward-sexp 1) (point))))
+
+            ((and (c-safe (forward-char -2) t)
+                  (looking-at "*/"))
+             ;; Block comment.  Due to the nature of line
+             ;; comments, they will always be covered by the
+             ;; normal case above.
+             (goto-char end)
+             (c-backward-single-comment)
+             ;; If LIM is bogus, beg will be bogus.
+             (setq beg (point))))
+
+           (if beg (cons beg end))))))
+       ))))
 
 ;; In case external callers use this; it did have a docstring.
 (defalias 'c-literal-limits-fast 'c-literal-limits)
@@ -4394,6 +4522,110 @@ comment at the start of cc-engine.el for more info."
              (t 'c)))                  ; Assuming the range is valid.
     range))
 
+(defsubst c-determine-limit-get-base (start try-size)
+  ;; Get a "safe place" approximately TRY-SIZE characters before START.
+  ;; This doesn't preserve point.
+  (let* ((pos (max (- start try-size) (point-min)))
+        (base (c-state-semi-safe-place pos))
+        (s (parse-partial-sexp base pos)))
+    (if (or (nth 4 s) (nth 3 s))       ; comment or string
+       (nth 8 s)
+      (point))))
+
+(defun c-determine-limit (how-far-back &optional start try-size)
+  ;; Return a buffer position HOW-FAR-BACK non-literal characters from START
+  ;; (default point).  This is done by going back further in the buffer then
+  ;; searching forward for literals.  The position found won't be in a
+  ;; literal.  We start searching for the sought position TRY-SIZE (default
+  ;; twice HOW-FAR-BACK) bytes back from START.  This function must be fast.
+  ;; :-)
+  (save-excursion
+    (let* ((start (or start (point)))
+          (try-size (or try-size (* 2 how-far-back)))
+          (base (c-determine-limit-get-base start try-size))
+          (pos base)
+
+          (s (parse-partial-sexp pos pos)) ; null state.
+          stack elt size
+          (count 0))
+      (while (< pos start)
+       ;; Move forward one literal each time round this loop.
+       ;; Move forward to the start of a comment or string.
+       (setq s (parse-partial-sexp
+                pos
+                start
+                nil                    ; target-depth
+                nil                    ; stop-before
+                s                      ; state
+                'syntax-table))        ; stop-comment
+
+       ;; Gather details of the non-literal-bit - starting pos and size.
+       (setq size (- (if (or (nth 4 s) (nth 3 s))
+                         (nth 8 s)
+                       (point))
+                     pos))
+       (if (> size 0)
+           (setq stack (cons (cons pos size) stack)))
+
+       ;; Move forward to the end of the comment/string.
+       (if (or (nth 4 s) (nth 3 s))
+           (setq s (parse-partial-sexp
+                    (point)
+                    start
+                    nil                ; target-depth
+                    nil                ; stop-before
+                    s                  ; state
+                    'syntax-table)))   ; stop-comment
+       (setq pos (point)))
+    
+      ;; Now try and find enough non-literal characters recorded on the stack.
+      ;; Go back one recorded literal each time round this loop.
+      (while (and (< count how-far-back)
+                 stack)
+       (setq elt (car stack)
+             stack (cdr stack))
+       (setq count (+ count (cdr elt))))
+
+      ;; Have we found enough yet?
+      (cond
+       ((>= count how-far-back)
+       (+ (car elt) (- count how-far-back)))
+       ((eq base (point-min))
+       (point-min))
+       (t
+       (c-determine-limit (- how-far-back count) base try-size))))))
+
+(defun c-determine-+ve-limit (how-far &optional start-pos)
+  ;; Return a buffer position about HOW-FAR non-literal characters forward
+  ;; from START-POS (default point), which must not be inside a literal.
+  (save-excursion
+    (let ((pos (or start-pos (point)))
+         (count how-far)
+         (s (parse-partial-sexp (point) (point)))) ; null state
+      (while (and (not (eobp))
+                 (> count 0))
+       ;; Scan over counted characters.
+       (setq s (parse-partial-sexp
+                pos
+                (min (+ pos count) (point-max))
+                nil                    ; target-depth
+                nil                    ; stop-before
+                s                      ; state
+                'syntax-table))        ; stop-comment
+       (setq count (- count (- (point) pos) 1)
+             pos (point))
+       ;; Scan over literal characters.
+       (if (nth 8 s)
+           (setq s (parse-partial-sexp
+                    pos
+                    (point-max)
+                    nil                ; target-depth
+                    nil                ; stop-before
+                    s                  ; state
+                    'syntax-table)     ; stop-comment
+                 pos (point))))
+      (point))))
+
 \f
 ;; `c-find-decl-spots' and accompanying stuff.
 
@@ -4530,13 +4762,14 @@ comment at the start of cc-engine.el for more info."
   ;; Call CFD-FUN for each possible spot for a declaration, cast or
   ;; label from the point to CFD-LIMIT.
   ;;
-  ;; CFD-FUN is called with point at the start of the spot.  It's
-  ;; passed two arguments: The first is the end position of the token
-  ;; preceding the spot, or 0 for the implicit match at bob.  The
-  ;; second is a flag that is t when the match is inside a macro.  If
-  ;; CFD-FUN adds `c-decl-end' properties somewhere below the current
-  ;; spot, it should return non-nil to ensure that the next search
-  ;; will find them.
+  ;; CFD-FUN is called with point at the start of the spot.  It's passed two
+  ;; arguments: The first is the end position of the token preceding the spot,
+  ;; or 0 for the implicit match at bob.  The second is a flag that is t when
+  ;; the match is inside a macro.  Point should be moved forward by at least
+  ;; one token.
+  ;;
+  ;; If CFD-FUN adds `c-decl-end' properties somewhere below the current spot,
+  ;; it should return non-nil to ensure that the next search will find them.
   ;;
   ;; Such a spot is:
   ;; o  The first token after bob.
@@ -4904,13 +5137,14 @@ comment at the start of cc-engine.el for more info."
            (setq cfd-prop-match nil))
 
        (when (/= cfd-macro-end 0)
-         ;; Restore limits if we did macro narrowment above.
+         ;; Restore limits if we did macro narrowing above.
          (narrow-to-region (point-min) cfd-buffer-end)))
 
       (goto-char cfd-continue-pos)
       (if (= cfd-continue-pos cfd-limit)
          (setq cfd-match-pos cfd-limit)
-       (c-find-decl-prefix-search)))))
+       (c-find-decl-prefix-search))))) ; Moves point, sets cfd-continue-pos,
+                                       ; cfd-match-pos, etc.
 
 \f
 ;; A cache for found types.
@@ -5052,7 +5286,7 @@ comment at the start of cc-engine.el for more info."
 ;; The strategy now (2010-01) adopted is to mark and unmark < and
 ;; > IN MATCHING PAIRS ONLY.  [Previously, they were marked
 ;; individually when their context so indicated.  This gave rise to
-;; intractible problems when one of a matching pair was deleted, or
+;; intractable problems when one of a matching pair was deleted, or
 ;; pulled into a literal.]
 ;;
 ;; At each buffer change, the syntax-table properties are removed in a
@@ -5180,7 +5414,7 @@ comment at the start of cc-engine.el for more info."
          new-beg new-end need-new-beg need-new-end)
       ;; Locate the barrier before the changed region
       (goto-char  (if beg-lit-limits (car beg-lit-limits) beg))
-      (c-syntactic-skip-backward "^;{}" (max (- beg 2048) (point-min)))
+      (c-syntactic-skip-backward "^;{}" (c-determine-limit 512))
       (setq new-beg (point))
 
       ;; Remove the syntax-table properties from each pertinent <...> pair.
@@ -5191,8 +5425,7 @@ comment at the start of cc-engine.el for more info."
 
       ;; Locate the barrier after END.
       (goto-char (if end-lit-limits (cdr end-lit-limits) end))
-      (c-syntactic-re-search-forward "[;{}]"
-                                    (min (+ end 2048) (point-max)) 'end)
+      (c-syntactic-re-search-forward "[;{}]" (c-determine-+ve-limit 512) 'end)
       (setq new-end (point))
 
       ;; Remove syntax-table properties from the remaining pertinent <...>
@@ -5965,7 +6198,7 @@ comment at the start of cc-engine.el for more info."
   ;;     `*-font-lock-extra-types');
   ;;   o - 'prefix if it's a known prefix of a type;
   ;;   o - 'found if it's a type that matches one in `c-found-types';
-  ;;   o - 'maybe if it's an identfier that might be a type; or
+  ;;   o - 'maybe if it's an identifier that might be a type; or
   ;;   o -  nil if it can't be a type (the point isn't moved then).
   ;;
   ;; The point is assumed to be at the beginning of a token.
@@ -6277,7 +6510,7 @@ comment at the start of cc-engine.el for more info."
   ;;      car ^                                     ^ point
   ;;     Foo::Foo (int b) : Base (b) {}
   ;; car ^                ^ point
-  ;; 
+  ;;
   ;;   The cdr of the return value is non-nil when a
   ;;   `c-typedef-decl-kwds' specifier is found in the declaration.
   ;;   Specifically it is a dotted pair (A . B) where B is t when a
@@ -6285,7 +6518,7 @@ comment at the start of cc-engine.el for more info."
   ;;   other `c-typedef-decl-kwds' (e.g. class, struct, enum)
   ;;   specifier is present.  I.e., (some of) the declared
   ;;   identifier(s) are types.
-  ;; 
+  ;;
   ;; If a cast is parsed:
   ;;
   ;;   The point is left at the first token after the closing paren of
@@ -6467,7 +6700,7 @@ comment at the start of cc-engine.el for more info."
                    (when (c-keyword-member kwd-sym 'c-typeless-decl-kwds)
                      (setq maybe-typeless t))
 
-                   ;; Haven't matched a type so it's an umambiguous
+                   ;; Haven't matched a type so it's an unambiguous
                    ;; specifier keyword and we know we're in a
                    ;; declaration.
                    (setq at-decl-or-cast t)
@@ -6832,7 +7065,7 @@ comment at the start of cc-engine.el for more info."
                       got-suffix-after-parens
                       (eq (char-after got-suffix-after-parens) ?\())
              ;; Got a type, no declarator but a paren suffix. I.e. it's a
-             ;; normal function call afterall (or perhaps a C++ style object
+             ;; normal function call after all (or perhaps a C++ style object
              ;; instantiation expression).
              (throw 'at-decl-or-cast nil))))
 
@@ -7100,7 +7333,7 @@ comment at the start of cc-engine.el for more info."
   ;;   colon).  Currently (2006-03), this applies only to Objective C's
   ;;   keywords "@private", "@protected", and "@public".  Returns t.
   ;;
-  ;; One of the things which will NOT be recognised as a label is a bit-field
+  ;; One of the things which will NOT be recognized as a label is a bit-field
   ;; element of a struct, something like "int foo:5".
   ;;
   ;; The end of the label is taken to be just after the colon, or the end of
@@ -7349,6 +7582,7 @@ comment at the start of cc-engine.el for more info."
     (let ((start (point))
          start-char
          (c-promote-possible-types t)
+         lim
          ;; Turn off recognition of angle bracket arglists while parsing
          ;; types here since the protocol reference list might then be
          ;; considered part of the preceding name or superclass-name.
@@ -7376,6 +7610,7 @@ comment at the start of cc-engine.el for more info."
 ;            (c-forward-token-2) ; 2006/1/13 This doesn't move if the token's
 ;            at EOB.
              (goto-char (match-end 0))
+             (setq lim (point))
              (c-skip-ws-forward)
              (c-forward-type))
 
@@ -7400,7 +7635,7 @@ comment at the start of cc-engine.el for more info."
                t))))
 
          (progn
-           (c-backward-syntactic-ws)
+           (c-backward-syntactic-ws lim)
            (c-clear-c-type-property start (1- (point)) 'c-decl-end)
            (c-put-c-type-property (1- (point)) 'c-decl-end)
            t)
@@ -7497,8 +7732,8 @@ comment at the start of cc-engine.el for more info."
     (and
      (eq (c-beginning-of-statement-1 lim) 'same)
 
-     (not (or (c-major-mode-is 'objc-mode)
-             (c-forward-objc-directive)))
+     (not (and (c-major-mode-is 'objc-mode)
+              (c-forward-objc-directive)))
 
      (setq id-start
           (car-safe (c-forward-decl-or-cast-1 (c-point 'bosws) nil nil)))
@@ -7543,14 +7778,17 @@ comment at the start of cc-engine.el for more info."
     (save-restriction
       ;; If we're in a macro, our search range is restricted to it.  Narrow to
       ;; the searchable range.
-      (let* ((macro-start (c-query-macro-start))
-            (lim (max (or lim (point-min)) (or macro-start (point-min))))
+      (let* ((macro-start (save-excursion (and (c-beginning-of-macro) (point))))
+            (macro-end (save-excursion (and macro-start (c-end-of-macro) (point))))
+            (low-lim (max (or lim (point-min))   (or macro-start (point-min))))
             before-lparen after-rparen
-            (pp-count-out 20)) ; Max number of paren/brace constructs before we give up
-       (narrow-to-region lim (c-point 'eol))
+            (pp-count-out 20)) ; Max number of paren/brace constructs before
+                               ; we give up
+       (narrow-to-region low-lim (or macro-end (point-max)))
 
        ;; Search backwards for the defun's argument list.  We give up if we
-       ;; encounter a "}" (end of a previous defun) or BOB.
+       ;; encounter a "}" (end of a previous defun) an "=" (which can't be in
+       ;; a knr region) or BOB.
        ;;
        ;; The criterion for a paren structure being the arg list is:
        ;; o - there is non-WS stuff after it but before any "{"; AND
@@ -7570,12 +7808,13 @@ comment at the start of cc-engine.el for more info."
        (catch 'knr
          (while (> pp-count-out 0) ; go back one paren/bracket pair each time.
            (setq pp-count-out (1- pp-count-out))
-           (c-syntactic-skip-backward "^)]}")
+           (c-syntactic-skip-backward "^)]}=")
            (cond ((eq (char-before) ?\))
                   (setq after-rparen (point)))
                  ((eq (char-before) ?\])
                   (setq after-rparen nil))
-                 (t ; either } (hit previous defun) or no more parens/brackets
+                 (t ; either } (hit previous defun) or = or no more
+                    ; parens/brackets.
                   (throw 'knr nil)))
 
            (if after-rparen
@@ -7591,18 +7830,18 @@ comment at the start of cc-engine.el for more info."
                   ;; It can't be the arg list if next token is ; or {
                   (progn (goto-char after-rparen)
                          (c-forward-syntactic-ws)
-                         (not (memq (char-after) '(?\; ?\{))))
+                         (not (memq (char-after) '(?\; ?\{ ?\=))))
 
                   ;; Is the thing preceding the list an identifier (the
                   ;; function name), or a macro expansion?
                   (progn
                     (goto-char before-lparen)
                     (eq (c-backward-token-2) 0)
-                    (or (c-on-identifier)
+                    (or (eq (c-on-identifier) (point))
                         (and (eq (char-after) ?\))
                              (c-go-up-list-backward)
                              (eq (c-backward-token-2) 0)
-                             (c-on-identifier))))
+                             (eq (c-on-identifier) (point)))))
 
                   ;; Have we got a non-empty list of comma-separated
                   ;; identifiers?
@@ -8090,6 +8329,23 @@ comment at the start of cc-engine.el for more info."
            next-open-brace (c-pull-open-brace paren-state)))
     open-brace))
 
+(defun c-cheap-inside-bracelist-p (paren-state)
+  ;; Return the position of the L-brace if point is inside a brace list
+  ;; initialization of an array, etc.  This is an approximate function,
+  ;; designed for speed over accuracy.  It will not find every bracelist, but
+  ;; a non-nil result is reliable.  We simply search for "= {" (naturally with
+  ;; syntactic whitespace allowed).  PAREN-STATE is the normal thing that it
+  ;; is everywhere else.
+  (let (b-pos)
+    (save-excursion
+      (while
+         (and (setq b-pos (c-pull-open-brace paren-state))
+              (progn (goto-char b-pos)
+                     (c-backward-sws)
+                     (c-backward-token-2)
+                     (not (looking-at "=")))))
+      b-pos)))
+
 (defun c-inside-bracelist-p (containing-sexp paren-state)
   ;; return the buffer position of the beginning of the brace list
   ;; statement if we're inside a brace list, otherwise return nil.
@@ -8441,7 +8697,6 @@ comment at the start of cc-engine.el for more info."
        (setq pos (point)))
       (and
        c-macro-with-semi-re
-       (not (c-in-literal))
        (eq (skip-chars-backward " \t") 0)
 
        ;; Check we've got nothing after this except comments and empty lines
@@ -8461,7 +8716,7 @@ comment at the start of cc-engine.el for more info."
                nil)
               (t nil))))
         (eolp))
-            
+
        (goto-char pos)
        (progn (c-backward-syntactic-ws)
              (eq (point) pos))
@@ -8472,7 +8727,9 @@ comment at the start of cc-engine.el for more info."
             (c-backward-syntactic-ws)
             t))
        (c-simple-skip-symbol-backward)
-       (looking-at c-macro-with-semi-re)))))
+       (looking-at c-macro-with-semi-re)
+       (goto-char pos)
+       (not (c-in-literal))))))                ; The most expensive check last. 
 
 (defun c-macro-vsemi-status-unknown-p () t) ; See cc-defs.el.
 
@@ -8832,7 +9089,7 @@ comment at the start of cc-engine.el for more info."
        ;; CASE B.4: Continued statement with block open.  The most
        ;; accurate analysis is perhaps `statement-cont' together with
        ;; `block-open' but we play DWIM and use `substatement-open'
-       ;; instead.  The rationaly is that this typically is a macro
+       ;; instead.  The rationale is that this typically is a macro
        ;; followed by a block which makes it very similar to a
        ;; statement with a substatement block.
        (t
@@ -8922,7 +9179,7 @@ comment at the start of cc-engine.el for more info."
       ;; FIXME: Should use c-add-stmt-syntax, but it's not yet
       ;; template aware.
       (c-add-syntax 'template-args-cont (point) placeholder))
-     
+
      ;; CASE D: continued statement.
      (t
       (c-beginning-of-statement-1 containing-sexp)
@@ -9013,6 +9270,10 @@ comment at the start of cc-engine.el for more info."
                          containing-sexp nil)))
              (setq lim (1+ containing-sexp))))
        (setq lim (point-min)))
+      (when (c-beginning-of-macro)
+       (goto-char indent-point)
+       (let ((lim1 (c-determine-limit 2000)))
+         (setq lim (max lim lim1))))
 
       ;; If we're in a parenthesis list then ',' delimits the
       ;; "statements" rather than being an operator (with the
@@ -9151,7 +9412,7 @@ comment at the start of cc-engine.el for more info."
                                    'label))
                            (if (eq step 'up)
                                (setq placeholder (point))
-                             ;; There was no containing statement afterall.
+                             ;; There was no containing statement after all.
                              (goto-char placeholder)))))
                    placeholder))
               (if (looking-at c-block-stmt-2-key)
@@ -9322,12 +9583,12 @@ comment at the start of cc-engine.el for more info."
                             (setq tmpsymbol nil)
                             (while (and (> (point) placeholder)
                                         (zerop (c-backward-token-2 1 t))
-                                        (/= (char-after) ?=))
+                                        (not (looking-at "=\\([^=]\\|$\\)")))
                               (and c-opt-inexpr-brace-list-key
                                    (not tmpsymbol)
                                    (looking-at c-opt-inexpr-brace-list-key)
                                    (setq tmpsymbol 'topmost-intro-cont)))
-                            (eq (char-after) ?=))
+                            (looking-at "=\\([^=]\\|$\\)"))
                           (looking-at c-brace-list-key))
                       (save-excursion
                         (while (and (< (point) indent-point)
@@ -9377,13 +9638,14 @@ comment at the start of cc-engine.el for more info."
         ;; CASE 5B: After a function header but before the body (or
         ;; the ending semicolon if there's no body).
         ((save-excursion
-           (when (setq placeholder (c-just-after-func-arglist-p lim))
+           (when (setq placeholder (c-just-after-func-arglist-p
+                                    (max lim (c-determine-limit 500))))
              (setq tmp-pos (point))))
          (cond
 
           ;; CASE 5B.1: Member init list.
           ((eq (char-after tmp-pos) ?:)
-           (if (or (> tmp-pos indent-point)
+           (if (or (>= tmp-pos indent-point)
                    (= (c-point 'bosws) (1+ tmp-pos)))
                (progn
                  ;; There is no preceding member init clause.
@@ -9582,10 +9844,10 @@ comment at the start of cc-engine.el for more info."
            (c-add-syntax 'inher-cont (c-point 'boi)))
 
           ;; CASE 5D.5: Continuation of the "expression part" of a
-          ;; top level construct.  Or, perhaps, an unrecognised construct.
+          ;; top level construct.  Or, perhaps, an unrecognized construct.
           (t
            (while (and (setq placeholder (point))
-                       (eq (car (c-beginning-of-decl-1 containing-sexp))
+                       (eq (car (c-beginning-of-decl-1 containing-sexp)) ; Can't use `lim' here.
                            'same)
                        (save-excursion
                          (c-backward-syntactic-ws)
@@ -9593,7 +9855,7 @@ comment at the start of cc-engine.el for more info."
                        (< (point) placeholder)))
            (c-add-stmt-syntax
             (cond
-             ((eq (point) placeholder) 'statement) ; unrecognised construct
+             ((eq (point) placeholder) 'statement) ; unrecognized construct
              ;; A preceding comma at the top level means that a
              ;; new variable declaration starts here.  Use
              ;; topmost-intro-cont for it, for consistency with
@@ -9688,7 +9950,7 @@ comment at the start of cc-engine.el for more info."
                              (eq (cdar c-state-cache) (point)))
                         ;; Speed up the backward search a bit.
                         (goto-char (caar c-state-cache)))
-                    (c-beginning-of-decl-1 containing-sexp)
+                    (c-beginning-of-decl-1 containing-sexp) ; Can't use `lim' here.
                     (setq placeholder (point))
                     (if (= start (point))
                         ;; The '}' is unbalanced.
@@ -9784,7 +10046,7 @@ comment at the start of cc-engine.el for more info."
          (c-beginning-of-statement-1 containing-sexp)
          (c-add-stmt-syntax 'statement nil t containing-sexp paren-state))
 
-        ;;CASE 5N: We are at a tompmost continuation line and the only
+        ;;CASE 5N: We are at a topmost continuation line and the only
         ;;preceding items are annotations.
         ((and (c-major-mode-is 'java-mode)
               (setq placeholder (point))