]> 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 be0f86ddd7e78a17be96f2baaac55dc8aab0da62..2aa04cb2b0b14dc54084dccff83107594f690bfa 100644 (file)
               (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,
@@ -226,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.
@@ -248,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.
@@ -268,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 ()
@@ -1182,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)
@@ -1624,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
@@ -1779,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.
@@ -1817,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
@@ -2002,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
@@ -2089,6 +2155,18 @@ 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 either
   ;;     (STATE TYPE (BEG . END))     if TO is in a literal; or
@@ -2129,47 +2207,93 @@ comment at the start of cc-engine.el for more info."
     (widen)
     (save-excursion
       (let ((c c-state-nonlit-pos-cache)
-           pos npos lit macro-beg)
+           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
-           ;; Add an element to `c-state-nonlit-pos-cache' each iteration.
-           (and
-            (<= (setq npos (+ pos c-state-nonlit-pos-interval)) here)
-            (progn
-              (setq lit (car (cddr (c-state-pp-to-literal pos npos))))
-              (cond
-               ((null lit)
-                (setq pos npos)
-                t)
-               ((<= (cdr lit) here)
-                (setq pos (cdr lit))
-                t)
-               (t
-                (setq pos (car lit))
-                nil))))
+       (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)
 
-         (goto-char pos)
-         (when (and (c-beginning-of-macro) (/= (point) pos))
-             (setq macro-beg (point))
-             (c-syntactic-end-of-macro)
-             (or (eobp) (forward-char))
-             (setq pos (if (<= (point) here)
-                           (point)
-                         macro-beg)))
+              ;; 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))
        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
@@ -2490,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.
@@ -2515,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
@@ -2552,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)
@@ -2941,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
@@ -2984,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
@@ -3126,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
@@ -3199,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
@@ -4229,7 +4384,7 @@ Note that this function might do hidden buffer changes.  See the
 comment at the start of cc-engine.el for more info."
   (save-restriction
     (widen)
-    (let* ((safe-place (c-state-safe-place (point)))
+    (let* ((safe-place (c-state-semi-safe-place (point)))
           (lit (c-state-pp-to-literal safe-place (point))))
       (or (cadr lit)
          (and detect-cpp
@@ -4253,7 +4408,7 @@ comment at the start of cc-engine.el for more info."
 
   (save-excursion
     (let* ((pos (point))
-          (lim (or lim (c-state-safe-place pos)))
+          (lim (or lim (c-state-semi-safe-place pos)))
           (pp-to-lit (save-restriction
                        (widen)
                        (c-state-pp-to-literal lim pos)))
@@ -4371,7 +4526,7 @@ comment at the start of cc-engine.el for more info."
   ;; 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-safe-place pos))
+        (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)
@@ -4439,6 +4594,38 @@ comment at the start of cc-engine.el for more info."
        (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.
 
@@ -5227,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.
@@ -5238,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 <...>
@@ -7546,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)))
@@ -8511,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
@@ -8542,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.
 
@@ -9083,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
@@ -9392,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)
@@ -9447,7 +9638,8 @@ 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
 
@@ -9655,7 +9847,7 @@ comment at the start of cc-engine.el for more info."
           ;; 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)
@@ -9758,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.