.
[emacs.git] / lisp / progmodes / cc-engine.el
blob58d61eb218218ab427cc0b745213b23a5446c531
1 ;;; cc-engine.el --- core syntax guessing engine for CC mode
3 ;; Copyright (C) 1985,1987,1992-2001 Free Software Foundation, Inc.
5 ;; Authors: 2000- Martin Stjernholm
6 ;; 1998-1999 Barry A. Warsaw and Martin Stjernholm
7 ;; 1992-1997 Barry A. Warsaw
8 ;; 1987 Dave Detlefs and Stewart Clamen
9 ;; 1985 Richard M. Stallman
10 ;; Maintainer: bug-cc-mode@gnu.org
11 ;; Created: 22-Apr-1997 (split from cc-mode.el)
12 ;; Version: See cc-mode.el
13 ;; Keywords: c languages oop
15 ;; This file is part of GNU Emacs.
17 ;; GNU Emacs is free software; you can redistribute it and/or modify
18 ;; it under the terms of the GNU General Public License as published by
19 ;; the Free Software Foundation; either version 2, or (at your option)
20 ;; any later version.
22 ;; GNU Emacs is distributed in the hope that it will be useful,
23 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
24 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 ;; GNU General Public License for more details.
27 ;; You should have received a copy of the GNU General Public License
28 ;; along with GNU Emacs; see the file COPYING. If not, write to
29 ;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
30 ;; Boston, MA 02111-1307, USA.
32 ;;; Commentary:
34 ;; The functions which have docstring documentation can be considered
35 ;; part of an API which other packages can use in CC Mode buffers.
36 ;; Otoh, undocumented functions and functions with the documentation
37 ;; in comments are considered purely internal and can change semantics
38 ;; or even disappear in the future.
40 ;; (This policy applies to CC Mode as a whole, not just this file. It
41 ;; probably also applies to many other Emacs packages, but here it's
42 ;; clearly spelled out.)
44 ;;; Code:
46 (eval-when-compile
47 (let ((load-path
48 (if (and (boundp 'byte-compile-dest-file)
49 (stringp byte-compile-dest-file))
50 (cons (file-name-directory byte-compile-dest-file) load-path)
51 load-path)))
52 (require 'cc-bytecomp)))
54 (cc-require 'cc-defs)
55 (cc-require 'cc-vars)
56 (cc-require 'cc-langs)
58 ;; Silence the compiler.
59 (cc-bytecomp-defun buffer-syntactic-context) ; XEmacs
62 (defun c-calculate-state (arg prevstate)
63 ;; Calculate the new state of PREVSTATE, t or nil, based on arg. If
64 ;; arg is nil or zero, toggle the state. If arg is negative, turn
65 ;; the state off, and if arg is positive, turn the state on
66 (if (or (not arg)
67 (zerop (setq arg (prefix-numeric-value arg))))
68 (not prevstate)
69 (> arg 0)))
72 (defvar c-in-literal-cache t)
73 (defvar c-parsing-error nil)
75 ;; KLUDGE ALERT: c-maybe-labelp is used to pass information between
76 ;; c-crosses-statement-barrier-p and c-beginning-of-statement-1. A
77 ;; better way should be implemented, but this will at least shut up
78 ;; the byte compiler.
79 (defvar c-maybe-labelp nil)
81 ;; Macros used internally in c-beginning-of-statement-1 for the
82 ;; automaton actions.
83 (defmacro c-bos-push-state ()
84 '(setq stack (cons (cons state saved-pos)
85 stack)))
86 (defmacro c-bos-pop-state (&optional do-if-done)
87 `(if (setq state (car (car stack))
88 saved-pos (cdr (car stack))
89 stack (cdr stack))
91 ,do-if-done
92 (throw 'loop nil)))
93 (defmacro c-bos-pop-state-and-retry ()
94 '(throw 'loop (setq state (car (car stack))
95 saved-pos (cdr (car stack))
96 ;; Throw nil if stack is empty, else throw non-nil.
97 stack (cdr stack))))
98 (defmacro c-bos-save-pos ()
99 '(setq saved-pos (vector pos tok ptok pptok)))
100 (defmacro c-bos-restore-pos ()
101 '(unless (eq (elt saved-pos 0) start)
102 (setq pos (elt saved-pos 0)
103 tok (elt saved-pos 1)
104 ptok (elt saved-pos 2)
105 pptok (elt saved-pos 3))
106 (goto-char pos)
107 (setq sym nil)))
108 (defmacro c-bos-save-error-info (missing got)
109 `(setq saved-pos (vector pos ,missing ,got)))
110 (defmacro c-bos-report-error ()
111 '(unless noerror
112 (setq c-parsing-error
113 (format "No matching `%s' found for `%s' on line %d"
114 (elt saved-pos 1)
115 (elt saved-pos 2)
116 (1+ (count-lines (point-min)
117 (c-point 'bol (elt saved-pos 0))))))))
119 (defun c-beginning-of-statement-1 (&optional lim ignore-labels
120 noerror comma-delim)
121 "Move to the start of the current statement or declaration, or to
122 the previous one if already at the beginning of one. Only
123 statements/declarations on the same level are considered, i.e. don't
124 move into or out of sexps (not even normal expression parentheses).
126 Stop at statement continuations like \"else\", \"catch\", \"finally\"
127 and the \"while\" in \"do ... while\" if the start point is within
128 them. If starting at such a continuation, move to the corresponding
129 statement start. If at the beginning of a statement, move to the
130 closest containing statement if there is any. This might also stop at
131 a continuation clause.
133 Labels are treated as separate statements if IGNORE-LABELS is non-nil.
134 The function is not overly intelligent in telling labels from other
135 uses of colons; if used outside a statement context it might trip up
136 on e.g. inherit colons, so IGNORE-LABELS should be used then. There
137 should be no such mistakes in a statement context, however.
139 Macros are ignored unless point is within one, in which case the
140 content of the macro is treated as normal code. Aside from any normal
141 statement starts found in it, stop at the first token of the content
142 in the macro, i.e. the expression of an \"#if\" or the start of the
143 definition in a \"#define\". Also stop at start of macros before
144 leaving them.
146 Return 'label if stopped at a label, 'same if stopped at the beginning
147 of the current statement, 'up if stepped to a containing statement,
148 'previous if stepped to a preceding statement, 'beginning if stepped
149 from a statement continuation clause to its start clause, or 'macro if
150 stepped to a macro start. Note that 'same and not 'label is returned
151 if stopped at the same label without crossing the colon character.
153 LIM may be given to limit the search. If the search hits the limit,
154 point will be left at the closest following token, or at the start
155 position if that is less ('same is returned in this case).
157 NOERROR turns off error logging to `c-parsing-error'.
159 Normally only ';' is considered to delimit statements, but if
160 COMMA-DELIM is non-nil then ',' is treated likewise."
162 ;; The bulk of this function is a pushdown automaton that looks at
163 ;; statement boundaries and the tokens in c-opt-block-stmt-key.
165 ;; Note: The position of a boundary is the following token.
167 ;; Begin with current token, stop when stack is empty and the
168 ;; position has been moved.
170 ;; Common state:
171 ;; "else": Push state, goto state `else':
172 ;; boundary: Goto state `else-boundary':
173 ;; "if": Pop state.
174 ;; boundary: Error, pop state.
175 ;; other: See common state.
176 ;; other: Error, pop state, retry token.
177 ;; "while": Push state, goto state `while':
178 ;; boundary: Save position, goto state `while-boundary':
179 ;; "do": Pop state.
180 ;; boundary: Restore position if it's not at start, pop state.
181 ;; other: See common state.
182 ;; other: Pop state, retry token.
183 ;; "catch" or "finally": Push state, goto state `catch':
184 ;; boundary: Goto state `catch-boundary':
185 ;; "try": Pop state.
186 ;; "catch": Goto state `catch'.
187 ;; boundary: Error, pop state.
188 ;; other: See common state.
189 ;; other: Error, pop state, retry token.
190 ;; other: Do nothing special.
192 ;; In addition to the above there is some special handling of labels
193 ;; and macros.
195 (let ((case-fold-search nil)
196 (start (point))
197 macro-start
198 (delims (if comma-delim '(?\; ?,) '(?\;)))
199 (c-stmt-delim-chars (if comma-delim
200 c-stmt-delim-chars-with-comma
201 c-stmt-delim-chars))
202 pos ; Current position.
203 boundary-pos ; Position of last boundary.
204 after-labels-pos ; Value of tok after first found colon.
205 last-label-pos ; Value of tok after last found colon.
206 sym ; Current symbol in the alphabet.
207 state ; Current state in the automaton.
208 saved-pos ; Current saved positions.
209 stack ; Stack of conses (state . saved-pos).
210 (cond-key (or c-opt-block-stmt-key
211 "\\<\\>")) ; Matches nothing.
212 (ret 'same)
213 tok ptok pptok ; Pos of last three sexps or bounds.
214 c-in-literal-cache c-maybe-labelp saved)
216 (save-restriction
217 (if lim (narrow-to-region lim (point-max)))
219 (if (save-excursion
220 (and (c-beginning-of-macro)
221 (/= (point) start)))
222 (setq macro-start (point)))
224 ;; Try to skip over unary operator characters, to register
225 ;; that we've moved.
226 (while (progn
227 (setq pos (point))
228 (c-backward-syntactic-ws)
229 (/= (skip-chars-backward "-+!*&~@`#") 0)))
231 ;; First check for bare semicolon. Later on we ignore the
232 ;; boundaries for statements that doesn't contain any sexp.
233 ;; The only thing that is affected is that the error checking
234 ;; is a little less strict, and we really don't bother.
235 (if (and (memq (char-before) delims)
236 (progn (forward-char -1)
237 (setq saved (point))
238 (c-backward-syntactic-ws)
239 (or (memq (char-before) delims)
240 (memq (char-before) '(?: nil))
241 (eq (char-syntax (char-before)) ?\())))
242 (setq ret 'previous
243 pos saved)
245 ;; Begin at start and not pos to detect macros if we stand
246 ;; directly after the #.
247 (goto-char start)
248 (if (looking-at "\\<\\|\\W")
249 ;; Record this as the first token if not starting inside it.
250 (setq tok start))
252 (while
253 (catch 'loop ;; Throw nil to break, non-nil to continue.
254 (cond
255 ;; Check for macro start.
256 ((save-excursion
257 (and macro-start
258 (looking-at "[ \t]*[a-zA-Z0-9!]")
259 (progn (skip-chars-backward " \t")
260 (eq (char-before) ?#))
261 (progn (setq saved (1- (point)))
262 (beginning-of-line)
263 (not (eq (char-before (1- (point))) ?\\)))
264 (progn (skip-chars-forward " \t")
265 (eq (point) saved))))
266 (goto-char saved)
267 (if (and (c-forward-to-cpp-define-body)
268 (progn (c-forward-syntactic-ws start)
269 (< (point) start)))
270 ;; Stop at the first token in the content of the macro.
271 (setq pos (point)
272 ignore-labels t) ; Avoid the label check on exit.
273 (setq pos saved
274 ret 'macro
275 ignore-labels t))
276 (throw 'loop nil))
278 ;; Do a round through the automaton if we found a
279 ;; boundary or if looking at a statement keyword.
280 ((or sym
281 (and (looking-at cond-key)
282 (setq sym (intern (match-string 1)))))
284 (when (and (< pos start) (null stack))
285 (throw 'loop nil))
287 ;; The state handling. Continue in the common state for
288 ;; unhandled cases.
289 (or (cond
290 ((eq state 'else)
291 (if (eq sym 'boundary)
292 (setq state 'else-boundary)
293 (c-bos-report-error)
294 (c-bos-pop-state-and-retry)))
296 ((eq state 'else-boundary)
297 (cond ((eq sym 'if)
298 (c-bos-pop-state (setq ret 'beginning)))
299 ((eq sym 'boundary)
300 (c-bos-report-error)
301 (c-bos-pop-state))))
303 ((eq state 'while)
304 (if (and (eq sym 'boundary)
305 ;; Since this can cause backtracking we do a
306 ;; little more careful analysis to avoid it:
307 ;; If there's a label in front of the while
308 ;; it can't be part of a do-while.
309 (not after-labels-pos))
310 (progn (c-bos-save-pos)
311 (setq state 'while-boundary))
312 (c-bos-pop-state-and-retry)))
314 ((eq state 'while-boundary)
315 (cond ((eq sym 'do)
316 (c-bos-pop-state (setq ret 'beginning)))
317 ((eq sym 'boundary)
318 (c-bos-restore-pos)
319 (c-bos-pop-state))))
321 ((eq state 'catch)
322 (if (eq sym 'boundary)
323 (setq state 'catch-boundary)
324 (c-bos-report-error)
325 (c-bos-pop-state-and-retry)))
327 ((eq state 'catch-boundary)
328 (cond
329 ((eq sym 'try)
330 (c-bos-pop-state (setq ret 'beginning)))
331 ((eq sym 'catch)
332 (setq state 'catch))
333 ((eq sym 'boundary)
334 (c-bos-report-error)
335 (c-bos-pop-state)))))
337 ;; This is state common.
338 (cond ((eq sym 'boundary)
339 (if (< pos start)
340 (c-bos-pop-state)
341 (c-bos-push-state)))
342 ((eq sym 'else)
343 (c-bos-push-state)
344 (c-bos-save-error-info 'if 'else)
345 (setq state 'else))
346 ((eq sym 'while)
347 (when (or (not pptok)
348 (memq (char-after pptok) delims))
349 ;; Since this can cause backtracking we do a
350 ;; little more careful analysis to avoid it: If
351 ;; the while isn't followed by a semicolon it
352 ;; can't be a do-while.
353 (c-bos-push-state)
354 (setq state 'while)))
355 ((memq sym '(catch finally))
356 (c-bos-push-state)
357 (c-bos-save-error-info 'try sym)
358 (setq state 'catch))))
360 (when c-maybe-labelp
361 ;; We're either past a statement boundary or at the
362 ;; start of a statement, so throw away any label data
363 ;; for the previous one.
364 (setq after-labels-pos nil
365 last-label-pos nil
366 c-maybe-labelp nil))))
368 ;; Step to next sexp, but not if we crossed a boundary, since
369 ;; that doesn't consume a sexp.
370 (if (eq sym 'boundary)
371 (setq ret 'previous)
372 (while
373 (progn
374 (or (c-safe (goto-char (scan-sexps (point) -1)) t)
375 (throw 'loop nil))
376 (cond ((looking-at "\\\\$")
377 ;; Step again if we hit a line continuation.
379 (macro-start
380 ;; If we started inside a macro then this
381 ;; sexp is always interesting.
382 nil)
384 ;; Otherwise check that we didn't step
385 ;; into a macro from the end.
386 (let ((macro-start
387 (save-excursion
388 (and (c-beginning-of-macro)
389 (point)))))
390 (when macro-start
391 (goto-char macro-start)
392 t))))))
394 ;; Check for statement boundary.
395 (when (save-excursion
396 (if (if (eq (char-after) ?{)
397 (c-looking-at-inexpr-block lim nil)
398 (eq (char-syntax (char-after)) ?\())
399 ;; Need to move over parens and
400 ;; in-expression blocks to get a good start
401 ;; position for the boundary check.
402 (c-forward-sexp 1))
403 (setq boundary-pos (c-crosses-statement-barrier-p
404 (point) pos)))
405 (setq pptok ptok
406 ptok tok
407 tok boundary-pos
408 sym 'boundary)
409 (throw 'loop t)))
411 (when (and (numberp c-maybe-labelp) (not ignore-labels))
412 ;; c-crosses-statement-barrier-p has found a colon, so
413 ;; we might be in a label now.
414 (if (not after-labels-pos)
415 (setq after-labels-pos tok))
416 (setq last-label-pos tok
417 c-maybe-labelp t))
419 ;; ObjC method def?
420 (when (and c-opt-method-key
421 (setq saved (c-in-method-def-p)))
422 (setq pos saved
423 ignore-labels t) ; Avoid the label check on exit.
424 (throw 'loop nil))
426 (setq sym nil
427 pptok ptok
428 ptok tok
429 tok (point)
430 pos tok))) ; Not nil.
432 ;; If the stack isn't empty there might be errors to report.
433 (while stack
434 (if (and (vectorp saved-pos) (eq (length saved-pos) 3))
435 (c-bos-report-error))
436 (setq saved-pos (cdr (car stack))
437 stack (cdr stack)))
439 (when (and (eq ret 'same)
440 (not (memq sym '(boundary ignore nil))))
441 ;; Need to investigate closer whether we've crossed
442 ;; between a substatement and its containing statement.
443 (if (setq saved (if (looking-at c-block-stmt-1-key)
444 ptok
445 pptok))
446 (cond ((> start saved) (setq pos saved))
447 ((= start saved) (setq ret 'up)))))
449 (when (and c-maybe-labelp (not ignore-labels) after-labels-pos)
450 ;; We're in a label. Maybe we should step to the statement
451 ;; after it.
452 (if (< after-labels-pos start)
453 (setq pos after-labels-pos)
454 (setq ret 'label)
455 (if (< last-label-pos start)
456 (setq pos last-label-pos)))))
458 ;; Skip over the unary operators that can start the statement.
459 (goto-char pos)
460 (while (progn
461 (c-backward-syntactic-ws)
462 (/= (skip-chars-backward "-+!*&~@`#") 0))
463 (setq pos (point)))
464 (goto-char pos)
465 ret)))
467 (defun c-crosses-statement-barrier-p (from to)
468 "Return non-nil if buffer positions FROM to TO cross one or more
469 statement or declaration boundaries. The returned value is actually
470 the position of the earliest boundary char.
472 The variable `c-maybe-labelp' is set to the position of the first `:' that
473 might start a label (i.e. not part of `::' and not preceded by `?'). If a
474 single `?' is found, then `c-maybe-labelp' is cleared."
475 (let ((skip-chars c-stmt-delim-chars)
476 lit-range)
477 (save-excursion
478 (catch 'done
479 (goto-char from)
480 (while (progn (skip-chars-forward skip-chars to)
481 (< (point) to))
482 (if (setq lit-range (c-literal-limits from))
483 (goto-char (setq from (cdr lit-range)))
484 (cond ((eq (char-after) ?:)
485 (forward-char)
486 (if (and (eq (char-after) ?:)
487 (< (point) to))
488 ;; Ignore scope operators.
489 (forward-char)
490 (setq c-maybe-labelp (1- (point)))))
491 ((eq (char-after) ??)
492 ;; A question mark. Can't be a label, so stop
493 ;; looking for more : and ?.
494 (setq c-maybe-labelp nil
495 skip-chars (substring c-stmt-delim-chars 0 -2)))
496 (t (throw 'done (point))))))
497 nil))))
500 ;; This is a dynamically bound cache used together with
501 ;; c-query-macro-start and c-query-and-set-macro-start. It only works
502 ;; as long as point doesn't cross a macro boundary.
503 (defvar c-macro-start 'unknown)
505 (defsubst c-query-and-set-macro-start ()
506 (if (symbolp c-macro-start)
507 (setq c-macro-start (save-excursion
508 (and (c-beginning-of-macro)
509 (point))))
510 c-macro-start))
512 (defsubst c-query-macro-start ()
513 (if (symbolp c-macro-start)
514 (save-excursion
515 (and (c-beginning-of-macro)
516 (point)))
517 c-macro-start))
519 (defun c-beginning-of-macro (&optional lim)
520 "Go to the beginning of a cpp macro definition.
521 Leave point at the beginning of the macro and return t if in a cpp
522 macro definition, otherwise return nil and leave point unchanged."
523 (let ((here (point)))
524 (save-restriction
525 (if lim (narrow-to-region lim (point-max)))
526 (beginning-of-line)
527 (while (eq (char-before (1- (point))) ?\\)
528 (forward-line -1))
529 (back-to-indentation)
530 (if (and (<= (point) here)
531 (looking-at "#[ \t]*[a-zA-Z0-9!]"))
533 (goto-char here)
534 nil))))
536 (defun c-end-of-macro ()
537 "Go to the end of a cpp macro definition.
538 More accurately, move point to the end of the closest following line
539 that doesn't end with a line continuation backslash."
540 (while (progn
541 (end-of-line)
542 (when (and (eq (char-before) ?\\)
543 (not (eobp)))
544 (forward-char)
545 t))))
547 (defun c-forward-comment (count)
548 ;; Insulation from various idiosyncrasies in implementations of
549 ;; `forward-comment'.
551 ;; Note: Some emacsen considers incorrectly that any line comment
552 ;; ending with a backslash continues to the next line. I can't
553 ;; think of any way to work around that in a reliable way without
554 ;; changing the buffer, though. Suggestions welcome. ;) (No,
555 ;; temporarily changing the syntax for backslash doesn't work since
556 ;; we must treat escapes in string literals correctly.)
558 ;; Another note: When moving backwards over a block comment, there's
559 ;; a bug in forward-comment that can make it stop at "/*" inside a
560 ;; line comment. Haven't yet found a reasonably cheap way to kludge
561 ;; around that one either. :\
562 (let ((here (point)))
563 (if (>= count 0)
564 (when (forward-comment count)
565 (if (eobp)
566 ;; Some emacsen (e.g. XEmacs 21) return t when moving
567 ;; forwards at eob.
569 ;; Emacs includes the ending newline in a b-style (c++)
570 ;; comment, but XEmacs doesn't. We depend on the Emacs
571 ;; behavior (which also is symmetric).
572 (if (and (eolp) (nth 7 (parse-partial-sexp here (point))))
573 (condition-case nil (forward-char 1)))
575 ;; When we got newline terminated comments,
576 ;; forward-comment in all supported emacsen so far will
577 ;; stop at eol of each line not ending with a comment when
578 ;; moving backwards. The following corrects for it when
579 ;; count is -1. The other common case, when count is
580 ;; large and negative, works regardless. It's too much
581 ;; work to correct for the rest of the cases.
582 (skip-chars-backward " \t\n\r\f")
583 (if (bobp)
584 ;; Some emacsen return t when moving backwards at bob.
586 (re-search-forward "[\n\r]" here t)
587 (let* ((res (if (forward-comment count)
588 (if (eolp) (forward-comment -1) t)))
589 (savepos (point)))
590 ;; XEmacs treats line continuations as whitespace (but only
591 ;; in the backward direction).
592 (while (and (progn (end-of-line) (< (point) here))
593 (eq (char-before) ?\\))
594 (setq res nil
595 savepos (point))
596 (forward-line))
597 (goto-char savepos)
598 res)))))
600 (defun c-forward-comment-lc (count)
601 ;; Like `c-forward-comment', but treat line continuations as
602 ;; whitespace.
603 (catch 'done
604 (if (> count 0)
605 (while (if (c-forward-comment 1)
606 (progn
607 (setq count (1- count))
608 (> count 0))
609 (if (looking-at "\\\\$")
610 (progn
611 (forward-char)
613 (throw 'done nil))))
614 (while (if (c-forward-comment -1)
615 (progn
616 (setq count (1+ count))
617 (< count 0))
618 (if (and (eolp) (eq (char-before) ?\\))
619 (progn
620 (backward-char)
622 (throw 'done nil)))))
625 (defun c-forward-syntactic-ws (&optional lim)
626 "Forward skip of syntactic whitespace.
627 Syntactic whitespace is defined as whitespace characters, comments,
628 and preprocessor directives. However if point starts inside a comment
629 or preprocessor directive, the content of it is not treated as
630 whitespace. LIM sets an upper limit of the forward movement, if
631 specified."
632 (let ((here (point-max)))
633 (or lim (setq lim here))
634 (while (/= here (point))
635 ;; If forward-comment in at least XEmacs 21 is given a large
636 ;; positive value, it'll loop all the way through if it hits eob.
637 (while (c-forward-comment 5))
638 (setq here (point))
639 (cond
640 ;; Skip line continuations.
641 ((looking-at "\\\\$")
642 (forward-char))
643 ;; Skip preprocessor directives.
644 ((and (looking-at "#[ \t]*[a-zA-Z0-9!]")
645 (save-excursion
646 (skip-chars-backward " \t")
647 (bolp)))
648 (end-of-line)
649 (while (and (<= (point) lim)
650 (eq (char-before) ?\\)
651 (= (forward-line 1) 0))
652 (end-of-line))
653 (when (> (point) lim)
654 ;; Don't move past the macro if that'd take us past the limit.
655 (goto-char here)))
656 ;; Skip in-comment line continuations (used for Pike refdoc).
657 ((and c-opt-in-comment-lc (looking-at c-opt-in-comment-lc))
658 (goto-char (match-end 0)))))
659 (goto-char (min (point) lim))))
661 (defun c-backward-syntactic-ws (&optional lim)
662 "Backward skip of syntactic whitespace.
663 Syntactic whitespace is defined as whitespace characters, comments,
664 and preprocessor directives. However if point starts inside a comment
665 or preprocessor directive, the content of it is not treated as
666 whitespace. LIM sets a lower limit of the backward movement, if
667 specified."
668 (let ((start-line (c-point 'bol))
669 (here (point-min))
670 (line-cont 'maybe)
671 prev-pos)
672 (or lim (setq lim here))
673 (while (/= here (point))
674 (setq prev-pos (point))
675 ;; If forward-comment in Emacs 19.34 is given a large negative
676 ;; value, it'll loop all the way through if it hits bob.
677 (while (c-forward-comment -5))
678 (setq here (point))
679 (cond
680 ((and (eolp)
681 (eq (char-before) ?\\)
682 (if (<= prev-pos (c-point 'eonl))
684 ;; Passed a line continuation, but not from the line we
685 ;; started on.
686 (forward-char)
687 (setq line-cont nil)))
688 (backward-char)
689 (setq line-cont t))
690 ((progn
691 (when (eq line-cont 'maybe)
692 (save-excursion
693 (end-of-line)
694 (setq line-cont (eq (char-before) ?\\))))
695 (or line-cont
696 (and (< (point) start-line)
697 (c-beginning-of-macro))))
698 (if (< (point) lim)
699 ;; Don't move past the macro if we began inside it or at
700 ;; the end of the same line, or if the move would take us
701 ;; past the limit.
702 (goto-char here))
703 (setq line-cont nil))
704 ;; Skip in-comment line continuations (used for Pike refdoc).
705 ((and c-opt-in-comment-lc
706 (save-excursion
707 (and (c-safe (beginning-of-line)
708 (backward-char 2)
710 (looking-at c-opt-in-comment-lc)
711 (eq (match-end 0) here))))
712 (goto-char (match-beginning 0)))))
713 (goto-char (max (point) lim))))
715 (defun c-forward-token-1 (&optional count balanced lim)
716 "Move forward by tokens.
717 A token is defined as all symbols and identifiers which aren't
718 syntactic whitespace \(note that e.g. \"->\" is considered to be two
719 tokens). Point is always either left at the beginning of a token or
720 not moved at all. COUNT specifies the number of tokens to move; a
721 negative COUNT moves in the opposite direction. A COUNT of 0 moves to
722 the next token beginning only if not already at one. If BALANCED is
723 true, move over balanced parens, otherwise move into them. Also, if
724 BALANCED is true, never move out of an enclosing paren. LIM sets the
725 limit for the movement and defaults to the point limit.
727 Return the number of tokens left to move \(positive or negative). If
728 BALANCED is true, a move over a balanced paren counts as one. Note
729 that if COUNT is 0 and no appropriate token beginning is found, 1 will
730 be returned. Thus, a return value of 0 guarantees that point is at
731 the requested position and a return value less \(without signs) than
732 COUNT guarantees that point is at the beginning of some token."
733 (or count (setq count 1))
734 (if (< count 0)
735 (- (c-backward-token-1 (- count) balanced lim))
736 (let ((jump-syntax (if balanced
737 '(?w ?_ ?\( ?\) ?\" ?\\ ?/ ?$ ?')
738 '(?w ?_ ?\" ?\\ ?/ ?')))
739 (last (point))
740 (prev (point)))
741 (save-restriction
742 (if lim (narrow-to-region (point-min) lim))
743 (if (/= (point)
744 (progn (c-forward-syntactic-ws) (point)))
745 ;; Skip whitespace. Count this as a move if we did in fact
746 ;; move and aren't out of bounds.
747 (or (eobp)
748 (setq count (max (1- count) 0))))
749 (if (and (= count 0)
750 (or (and (memq (char-syntax (or (char-after) ? )) '(?w ?_))
751 (memq (char-syntax (or (char-before) ? )) '(?w ?_)))
752 (eobp)))
753 ;; If count is zero we should jump if in the middle of a
754 ;; token or if there is whitespace between point and the
755 ;; following token beginning.
756 (setq count 1))
757 (if (eobp)
758 (goto-char last)
759 ;; Avoid having the limit tests inside the loop.
760 (condition-case nil
761 (while (> count 0)
762 (setq prev last
763 last (point))
764 (if (memq (char-syntax (char-after)) jump-syntax)
765 (goto-char (scan-sexps (point) 1))
766 (forward-char))
767 (c-forward-syntactic-ws)
768 (setq count (1- count)))
769 (error (goto-char last)))
770 (when (eobp)
771 (goto-char prev)
772 (setq count (1+ count)))))
773 count)))
775 (defun c-backward-token-1 (&optional count balanced lim)
776 "Move backward by tokens.
777 See `c-forward-token-1' for details."
778 (or count (setq count 1))
779 (if (< count 0)
780 (- (c-forward-token-1 (- count) balanced lim))
781 (let ((jump-syntax (if balanced
782 '(?w ?_ ?\( ?\) ?\" ?\\ ?/ ?$ ?')
783 '(?w ?_ ?\" ?\\ ?/ ?')))
784 last)
785 (if (and (= count 0)
786 (or (and (memq (char-syntax (or (char-after) ? )) '(?w ?_))
787 (memq (char-syntax (or (char-before) ? )) '(?w ?_)))
788 (/= (point)
789 (save-excursion
790 (c-forward-syntactic-ws (1+ lim))
791 (point)))
792 (eobp)))
793 ;; If count is zero we should jump if in the middle of a
794 ;; token or if there is whitespace between point and the
795 ;; following token beginning.
796 (setq count 1))
797 (save-restriction
798 (if lim (narrow-to-region lim (point-max)))
799 (or (bobp)
800 (progn
801 ;; Avoid having the limit tests inside the loop.
802 (condition-case nil
803 (while (progn
804 (setq last (point))
805 (> count 0))
806 (c-backward-syntactic-ws)
807 (if (memq (char-syntax (char-before)) jump-syntax)
808 (goto-char (scan-sexps (point) -1))
809 (backward-char))
810 (setq count (1- count)))
811 (error (goto-char last)))
812 (if (bobp) (goto-char last)))))
813 count)))
815 (defun c-syntactic-re-search-forward (regexp &optional bound noerror count
816 paren-level)
817 ;; Like `re-search-forward', but only report matches that are found
818 ;; in syntactically significant text. I.e. matches that begins in
819 ;; comments, macros or string literals are ignored. The start point
820 ;; is assumed to be outside any comment, macro or string literal, or
821 ;; else the content of that region is taken as syntactically
822 ;; significant text. If PAREN-LEVEL is non-nil, an additional
823 ;; restriction is added to ignore matches in nested paren sexps, and
824 ;; the search will also not go outside the current paren sexp.
825 (or bound (setq bound (point-max)))
826 (or count (setq count 1))
827 (if paren-level (setq paren-level -1))
828 (let ((start (point))
829 (pos (point))
830 match-pos state)
831 (condition-case err
832 (while (and (> count 0)
833 (re-search-forward regexp bound noerror))
834 (setq match-pos (point)
835 state (parse-partial-sexp pos (match-beginning 0)
836 paren-level nil state)
837 pos (point))
838 (cond ((nth 3 state)
839 ;; Match inside a string. Skip to the end of it
840 ;; before continuing.
841 (let ((ender (make-string 1 (nth 3 state))))
842 (while (progn
843 (search-forward ender bound noerror)
844 (setq state (parse-partial-sexp pos (point)
845 nil nil state)
846 pos (point))
847 (nth 3 state)))))
848 ((nth 7 state)
849 ;; Match inside a line comment. Skip to eol. Use
850 ;; re-search-forward for it to get the right bound
851 ;; behavior.
852 (re-search-forward "[\n\r]" bound noerror))
853 ((nth 4 state)
854 ;; Match inside a block comment. Skip to the '*/'.
855 (re-search-forward "\\*/" bound noerror))
856 ((save-excursion (c-beginning-of-macro start))
857 ;; Match inside a macro. Skip to the end of it.
858 (c-end-of-macro))
859 ((and paren-level (/= (car state) 0))
860 (if (> (car state) 0)
861 ;; Match inside a nested paren sexp. Skip out of it.
862 (setq state (parse-partial-sexp pos bound 0 nil state)
863 pos (point))
864 ;; Have exited the current paren sexp. The
865 ;; parse-partial-sexp above has left us just after
866 ;; the closing paren in this case. Just make
867 ;; re-search-forward above fail in the appropriate
868 ;; way; we'll adjust the leave off point below if
869 ;; necessary.
870 (setq bound (point))))
872 ;; A real match.
873 (setq count (1- count)))))
874 (error
875 (goto-char start)
876 (signal (car err) (cdr err))))
877 (if (= count 0)
878 (progn
879 (goto-char match-pos)
880 match-pos)
881 ;; Search failed. Set point as appropriate.
882 (cond ((eq noerror t)
883 (goto-char start))
884 (paren-level
885 (if (eq (car (parse-partial-sexp pos bound -1 nil state)) -1)
886 (backward-char)))
888 (goto-char bound)))
889 nil)))
892 (defun c-in-literal (&optional lim detect-cpp)
893 "Return the type of literal point is in, if any.
894 The return value is `c' if in a C-style comment, `c++' if in a C++
895 style comment, `string' if in a string literal, `pound' if DETECT-CPP
896 is non-nil and on a preprocessor line, or nil if somewhere else.
897 Optional LIM is used as the backward limit of the search. If omitted,
898 or nil, `c-beginning-of-defun' is used.
900 The last point calculated is cached if the cache is enabled, i.e. if
901 `c-in-literal-cache' is bound to a two element vector."
902 (if (and (vectorp c-in-literal-cache)
903 (= (point) (aref c-in-literal-cache 0)))
904 (aref c-in-literal-cache 1)
905 (let ((rtn (save-excursion
906 (let* ((lim (or lim (c-point 'bod)))
907 (state (parse-partial-sexp lim (point))))
908 (cond
909 ((nth 3 state) 'string)
910 ((nth 4 state) (if (nth 7 state) 'c++ 'c))
911 ((and detect-cpp (c-beginning-of-macro lim)) 'pound)
912 (t nil))))))
913 ;; cache this result if the cache is enabled
914 (if (not c-in-literal-cache)
915 (setq c-in-literal-cache (vector (point) rtn)))
916 rtn)))
918 ;; XEmacs has a built-in function that should make this much quicker.
919 ;; I don't think we even need the cache, which makes our lives more
920 ;; complicated anyway. In this case, lim is only used to detect
921 ;; cpp directives.
922 (defun c-fast-in-literal (&optional lim detect-cpp)
923 (let ((context (buffer-syntactic-context)))
924 (cond
925 ((eq context 'string) 'string)
926 ((eq context 'comment) 'c++)
927 ((eq context 'block-comment) 'c)
928 ((and detect-cpp (save-excursion (c-beginning-of-macro lim))) 'pound))))
930 (if (fboundp 'buffer-syntactic-context)
931 (defalias 'c-in-literal 'c-fast-in-literal))
933 (defun c-literal-limits (&optional lim near not-in-delimiter)
934 "Return a cons of the beginning and end positions of the comment or
935 string surrounding point (including both delimiters), or nil if point
936 isn't in one. If LIM is non-nil, it's used as the \"safe\" position
937 to start parsing from. If NEAR is non-nil, then the limits of any
938 literal next to point is returned. \"Next to\" means there's only [
939 \t] between point and the literal. The search for such a literal is
940 done first in forward direction. If NOT-IN-DELIMITER is non-nil, the
941 case when point is inside a starting delimiter won't be recognized.
942 This only has effect for comments, which have starting delimiters with
943 more than one character."
944 (save-excursion
945 (let* ((pos (point))
946 (lim (or lim (c-point 'bod)))
947 (state (parse-partial-sexp lim (point))))
948 (cond ((nth 3 state)
949 ;; String. Search backward for the start.
950 (while (nth 3 state)
951 (search-backward (make-string 1 (nth 3 state)))
952 (setq state (parse-partial-sexp lim (point))))
953 (cons (point) (or (c-safe (c-forward-sexp 1) (point))
954 (point-max))))
955 ((nth 7 state)
956 ;; Line comment. Search from bol for the comment starter.
957 (beginning-of-line)
958 (setq state (parse-partial-sexp lim (point))
959 lim (point))
960 (while (not (nth 7 state))
961 (search-forward "//") ; Should never fail.
962 (setq state (parse-partial-sexp
963 lim (point) nil nil state)
964 lim (point)))
965 (backward-char 2)
966 (cons (point) (progn (c-forward-comment 1) (point))))
967 ((nth 4 state)
968 ;; Block comment. Search backward for the comment starter.
969 (while (nth 4 state)
970 (search-backward "/*") ; Should never fail.
971 (setq state (parse-partial-sexp lim (point))))
972 (cons (point) (progn (c-forward-comment 1) (point))))
973 ((and (not not-in-delimiter)
974 (not (nth 5 state))
975 (eq (char-before) ?/)
976 (looking-at "[/*]"))
977 ;; We're standing in a comment starter.
978 (backward-char 1)
979 (cons (point) (progn (c-forward-comment 1) (point))))
980 (near
981 (goto-char pos)
982 ;; Search forward for a literal.
983 (skip-chars-forward " \t")
984 (cond
985 ((eq (char-syntax (or (char-after) ?\ )) ?\") ; String.
986 (cons (point) (or (c-safe (c-forward-sexp 1) (point))
987 (point-max))))
988 ((looking-at "/[/*]") ; Line or block comment.
989 (cons (point) (progn (c-forward-comment 1) (point))))
991 ;; Search backward.
992 (skip-chars-backward " \t")
993 (let ((end (point)) beg)
994 (cond
995 ((eq (char-syntax (or (char-before) ?\ )) ?\") ; String.
996 (setq beg (c-safe (c-backward-sexp 1) (point))))
997 ((and (c-safe (forward-char -2) t)
998 (looking-at "*/"))
999 ;; Block comment. Due to the nature of line
1000 ;; comments, they will always be covered by the
1001 ;; normal case above.
1002 (goto-char end)
1003 (c-forward-comment -1)
1004 ;; If LIM is bogus, beg will be bogus.
1005 (setq beg (point))))
1006 (if beg (cons beg end))))))
1007 ))))
1009 (defun c-literal-limits-fast (&optional lim near not-in-delimiter)
1010 ;; Like c-literal-limits, but for emacsen whose `parse-partial-sexp'
1011 ;; returns the pos of the comment start.
1012 (save-excursion
1013 (let* ((pos (point))
1014 (lim (or lim (c-point 'bod)))
1015 (state (parse-partial-sexp lim (point))))
1016 (cond ((nth 3 state) ; String.
1017 (goto-char (nth 8 state))
1018 (cons (point) (or (c-safe (c-forward-sexp 1) (point))
1019 (point-max))))
1020 ((nth 4 state) ; Comment.
1021 (goto-char (nth 8 state))
1022 (cons (point) (progn (c-forward-comment 1) (point))))
1023 ((and (not not-in-delimiter)
1024 (not (nth 5 state))
1025 (eq (char-before) ?/)
1026 (looking-at "[/*]"))
1027 ;; We're standing in a comment starter.
1028 (backward-char 1)
1029 (cons (point) (progn (c-forward-comment 1) (point))))
1030 (near
1031 (goto-char pos)
1032 ;; Search forward for a literal.
1033 (skip-chars-forward " \t")
1034 (cond
1035 ((eq (char-syntax (or (char-after) ?\ )) ?\") ; String.
1036 (cons (point) (or (c-safe (c-forward-sexp 1) (point))
1037 (point-max))))
1038 ((looking-at "/[/*]") ; Line or block comment.
1039 (cons (point) (progn (c-forward-comment 1) (point))))
1041 ;; Search backward.
1042 (skip-chars-backward " \t")
1043 (let ((end (point)) beg)
1044 (cond
1045 ((eq (char-syntax (or (char-before) ?\ )) ?\") ; String.
1046 (setq beg (c-safe (c-backward-sexp 1) (point))))
1047 ((and (c-safe (forward-char -2) t)
1048 (looking-at "*/"))
1049 ;; Block comment. Due to the nature of line
1050 ;; comments, they will always be covered by the
1051 ;; normal case above.
1052 (goto-char end)
1053 (c-forward-comment -1)
1054 ;; If LIM is bogus, beg will be bogus.
1055 (setq beg (point))))
1056 (if beg (cons beg end))))))
1057 ))))
1059 (if (c-safe (> (length (save-excursion (parse-partial-sexp 1 1))) 8))
1060 (defalias 'c-literal-limits 'c-literal-limits-fast))
1062 (defun c-collect-line-comments (range)
1063 "If the argument is a cons of two buffer positions (such as returned by
1064 `c-literal-limits'), and that range contains a C++ style line comment,
1065 then an extended range is returned that contains all adjacent line
1066 comments (i.e. all comments that starts in the same column with no
1067 empty lines or non-whitespace characters between them). Otherwise the
1068 argument is returned."
1069 (save-excursion
1070 (condition-case nil
1071 (if (and (consp range) (progn
1072 (goto-char (car range))
1073 (looking-at "//")))
1074 (let ((col (current-column))
1075 (beg (point))
1076 (bopl (c-point 'bopl))
1077 (end (cdr range)))
1078 ;; Got to take care in the backward direction to handle
1079 ;; comments which are preceded by code.
1080 (while (and (c-forward-comment -1)
1081 (>= (point) bopl)
1082 (looking-at "//")
1083 (= col (current-column)))
1084 (setq beg (point)
1085 bopl (c-point 'bopl)))
1086 (goto-char end)
1087 (while (and (progn (skip-chars-forward " \t")
1088 (looking-at "//"))
1089 (= col (current-column))
1090 (prog1 (zerop (forward-line 1))
1091 (setq end (point)))))
1092 (cons beg end))
1093 range)
1094 (error range))))
1096 (defun c-literal-type (range)
1097 "Convenience function that given the result of `c-literal-limits',
1098 returns nil or the type of literal that the range surrounds. It's
1099 much faster than using `c-in-literal' and is intended to be used when
1100 you need both the type of a literal and its limits."
1101 (if (consp range)
1102 (save-excursion
1103 (goto-char (car range))
1104 (cond ((eq (char-syntax (or (char-after) ?\ )) ?\") 'string)
1105 ((looking-at "//") 'c++)
1106 (t 'c))) ; Assuming the range is valid.
1107 range))
1111 ;; utilities for moving and querying around syntactic elements
1113 (defvar c-state-cache nil)
1114 (make-variable-buffer-local 'c-state-cache)
1115 ;; The state cache used by `c-parse-state' to cut down the amount of
1116 ;; searching. It's the result from some earlier `c-parse-state' call.
1117 ;; The use of the cached info is more effective if the next
1118 ;; `c-parse-state' call is on a line close by the one the cached state
1119 ;; was made at; the cache can actually slow down a little if the
1120 ;; cached state was made very far back in the buffer. The cache is
1121 ;; most effective if `c-parse-state' is used on each line while moving
1122 ;; forward.
1124 (defvar c-state-cache-start nil)
1125 ;; This (point-min) when `c-state-cache' was calculated, to detect
1126 ;; that the start point hasn't changed due to narrowing.
1128 (defun c-parse-state ()
1129 ;; Finds and records all noteworthy parens between some good point
1130 ;; earlier in the file and point. That good point is at least the
1131 ;; beginning of the top-level construct we are in, or the beginning
1132 ;; of the preceding top-level construct if we aren't in one.
1134 ;; The returned value is a list of the noteworthy parens with the
1135 ;; last one first. If an element in the list is an integer, it's
1136 ;; the position of an open paren which has not been closed before
1137 ;; point. If an element is a cons, it gives the position of a
1138 ;; closed brace paren pair; the car is the start paren position and
1139 ;; the cdr is the position following the closing paren. Only the
1140 ;; last closed brace paren pair before each open paren is recorded,
1141 ;; and thus the state never contains two cons elements in
1142 ;; succession.
1143 (save-restriction
1144 (let* ((here (point))
1145 (c-macro-start (c-query-macro-start))
1146 (in-macro-start (or c-macro-start (point)))
1147 old-state last-pos pairs pos)
1148 ;; Somewhat ugly use of c-check-state-cache to get rid of the
1149 ;; part of the state cache that is after point. Can't use
1150 ;; c-whack-state-after for the same reasons as in that function.
1151 (c-check-state-cache (point) nil nil)
1152 ;; Get the latest position we know are directly inside the
1153 ;; closest containing paren of the cached state.
1154 (setq last-pos (and c-state-cache
1155 (if (consp (car c-state-cache))
1156 (cdr (car c-state-cache))
1157 (1+ (car c-state-cache)))))
1158 ;; Check if the found last-pos is in a macro. If it is, and
1159 ;; we're not in the same macro, we must discard everything on
1160 ;; c-state-cache that is inside the macro before using it.
1161 (when last-pos
1162 (save-excursion
1163 (goto-char last-pos)
1164 (when (and (c-beginning-of-macro)
1165 (/= (point) in-macro-start))
1166 (c-check-state-cache (point) nil nil)
1167 ;; Set last-pos again, just like above.
1168 (setq last-pos (and c-state-cache
1169 (if (consp (car c-state-cache))
1170 (cdr (car c-state-cache))
1171 (1+ (car c-state-cache))))))))
1172 (setq pos
1173 ;; Find the start position for the forward search. (Can't
1174 ;; search in the backward direction since point might be
1175 ;; in some kind of literal.)
1176 (or (when last-pos
1177 ;; There's a cached state with a containing paren. Pop
1178 ;; off the stale containing sexps from it by going
1179 ;; forward out of parens as far as possible.
1180 (narrow-to-region (point-min) here)
1181 (let (placeholder pair-beg)
1182 (while (and c-state-cache
1183 (setq placeholder
1184 (c-up-list-forward last-pos)))
1185 (setq last-pos placeholder)
1186 (if (consp (car c-state-cache))
1187 (setq pair-beg (car-safe (cdr c-state-cache))
1188 c-state-cache (cdr-safe (cdr c-state-cache)))
1189 (setq pair-beg (car c-state-cache)
1190 c-state-cache (cdr c-state-cache))))
1191 (when (and pair-beg (eq (char-after pair-beg) ?{))
1192 ;; The last paren pair we moved out from was a brace
1193 ;; pair. Modify the state to record this as a closed
1194 ;; pair now.
1195 (if (consp (car-safe c-state-cache))
1196 (setq c-state-cache (cdr c-state-cache)))
1197 (setq c-state-cache (cons (cons pair-beg last-pos)
1198 c-state-cache))))
1199 ;; Check if the preceding balanced paren is within a
1200 ;; macro; it should be ignored if we're outside the
1201 ;; macro. There's no need to check any further upwards;
1202 ;; if the macro contains an unbalanced opening paren then
1203 ;; we're smoked anyway.
1204 (when (and (<= (point) in-macro-start)
1205 (consp (car c-state-cache)))
1206 (save-excursion
1207 (goto-char (car (car c-state-cache)))
1208 (when (c-beginning-of-macro)
1209 (setq here (point)
1210 c-state-cache (cdr c-state-cache)))))
1211 (when c-state-cache
1212 (setq old-state c-state-cache)
1213 last-pos))
1214 (save-excursion
1215 ;; go back 2 bods, but ignore any bogus positions
1216 ;; returned by beginning-of-defun (i.e. open paren in
1217 ;; column zero)
1218 (goto-char here)
1219 (let ((cnt 2))
1220 (while (not (or (bobp) (zerop cnt)))
1221 (c-beginning-of-defun-1)
1222 (if (eq (char-after) ?\{)
1223 (setq cnt (1- cnt)))))
1224 (point))))
1225 (narrow-to-region (point-min) here)
1226 (while pos
1227 ;; Find the balanced brace pairs.
1228 (setq pairs nil)
1229 (while (and (setq last-pos (c-down-list-forward pos))
1230 (setq pos (c-up-list-forward last-pos)))
1231 (if (eq (char-before last-pos) ?{)
1232 (setq pairs (cons (cons last-pos pos) pairs))))
1233 ;; Should ignore any pairs that are in a macro, providing
1234 ;; we're not in the same one.
1235 (when (and pairs (< (car (car pairs)) in-macro-start))
1236 (while (and (save-excursion
1237 (goto-char (car (car pairs)))
1238 (c-beginning-of-macro))
1239 (setq pairs (cdr pairs)))))
1240 ;; Record the last brace pair.
1241 (when pairs
1242 (if (and (eq c-state-cache old-state)
1243 (consp (car-safe c-state-cache)))
1244 ;; There's a closed pair on the cached state but we've
1245 ;; found a later one, so remove it.
1246 (setq c-state-cache (cdr c-state-cache)))
1247 (setq pairs (car pairs))
1248 (setcar pairs (1- (car pairs)))
1249 (when (consp (car-safe c-state-cache))
1250 ;; There could already be a cons first in `c-state-cache'
1251 ;; if we've jumped over an unbalanced open paren in a
1252 ;; macro below.
1253 (setq c-state-cache (cdr c-state-cache)))
1254 (setq c-state-cache (cons pairs c-state-cache)))
1255 (if last-pos
1256 ;; Prepare to loop, but record the open paren only if it's
1257 ;; outside a macro or within the same macro as point.
1258 (progn
1259 (setq pos last-pos)
1260 (if (or (>= last-pos in-macro-start)
1261 (save-excursion
1262 (goto-char last-pos)
1263 (not (c-beginning-of-macro))))
1264 (setq c-state-cache (cons (1- pos) c-state-cache))))
1265 (if (setq last-pos (c-up-list-forward pos))
1266 ;; Found a close paren without a corresponding opening
1267 ;; one. Maybe we didn't go back far enough, so try to
1268 ;; scan backward for the start paren and then start over.
1269 (progn
1270 (setq pos (c-up-list-backward pos)
1271 c-state-cache nil)
1272 (unless pos
1273 (setq pos last-pos
1274 c-parsing-error
1275 (format "Unbalanced close paren at line %d"
1276 (1+ (count-lines (point-min)
1277 (c-point 'bol last-pos)))))))
1278 (setq pos nil))))
1279 c-state-cache)))
1281 ;; Debug tool to catch cache inconsistencies.
1282 (defvar c-debug-parse-state nil)
1283 (unless (fboundp 'c-real-parse-state)
1284 (fset 'c-real-parse-state (symbol-function 'c-parse-state)))
1285 (cc-bytecomp-defun c-real-parse-state)
1286 (defun c-debug-parse-state ()
1287 (let ((res1 (c-real-parse-state)) res2)
1288 (let ((c-state-cache nil))
1289 (setq res2 (c-real-parse-state)))
1290 (unless (equal res1 res2)
1291 (error "c-parse-state inconsistency: using cache: %s, from scratch: %s"
1292 res1 res2))
1293 res1))
1294 (defun c-toggle-parse-state-debug (&optional arg)
1295 (interactive "P")
1296 (setq c-debug-parse-state (c-calculate-state arg c-debug-parse-state))
1297 (fset 'c-parse-state (symbol-function (if c-debug-parse-state
1298 'c-debug-parse-state
1299 'c-real-parse-state)))
1300 (c-keep-region-active))
1302 (defun c-check-state-cache (beg end old-length)
1303 ;; Used on `after-change-functions' to adjust `c-state-cache'.
1304 ;; Prefer speed to finesse here, since there will be many more calls
1305 ;; to this function than times `c-state-cache' is used.
1307 ;; This is much like `c-whack-state-after', but it never changes a
1308 ;; paren pair element into an open paren element. Doing that would
1309 ;; mean that the new open paren wouldn't have the required preceding
1310 ;; paren pair element.
1311 (if (not (eq c-state-cache-start (point-min)))
1312 (setq c-state-cache-start (point-min)
1313 c-state-cache nil)
1314 (while (and c-state-cache
1315 (let ((elem (car c-state-cache)))
1316 (if (consp elem)
1317 (or (<= beg (car elem))
1318 (< beg (cdr elem)))
1319 (<= beg elem))))
1320 (setq c-state-cache (cdr c-state-cache)))))
1322 (defun c-whack-state-before (bufpos paren-state)
1323 ;; Whack off any state information from PAREN-STATE which lies
1324 ;; before BUFPOS. Not destructive on PAREN-STATE.
1325 (let* ((newstate (list nil))
1326 (ptr newstate)
1327 car)
1328 (while paren-state
1329 (setq car (car paren-state)
1330 paren-state (cdr paren-state))
1331 (if (< (if (consp car) (car car) car) bufpos)
1332 (setq paren-state nil)
1333 (setcdr ptr (list car))
1334 (setq ptr (cdr ptr))))
1335 (cdr newstate)))
1337 (defun c-whack-state-after (bufpos paren-state)
1338 ;; Whack off any state information from PAREN-STATE which lies at or
1339 ;; after BUFPOS. Not destructive on PAREN-STATE.
1340 (catch 'done
1341 (while paren-state
1342 (let ((car (car paren-state)))
1343 (if (consp car)
1344 ;; just check the car, because in a balanced brace
1345 ;; expression, it must be impossible for the corresponding
1346 ;; close brace to be before point, but the open brace to
1347 ;; be after.
1348 (if (<= bufpos (car car))
1349 nil ; whack it off
1350 (if (< bufpos (cdr car))
1351 ;; its possible that the open brace is before
1352 ;; bufpos, but the close brace is after. In that
1353 ;; case, convert this to a non-cons element. The
1354 ;; rest of the state is before bufpos, so we're
1355 ;; done.
1356 (throw 'done (cons (car car) (cdr paren-state)))
1357 ;; we know that both the open and close braces are
1358 ;; before bufpos, so we also know that everything else
1359 ;; on state is before bufpos.
1360 (throw 'done paren-state)))
1361 (if (<= bufpos car)
1362 nil ; whack it off
1363 ;; it's before bufpos, so everything else should too.
1364 (throw 'done paren-state)))
1365 (setq paren-state (cdr paren-state)))
1366 nil)))
1369 (defun c-beginning-of-inheritance-list (&optional lim)
1370 ;; Go to the first non-whitespace after the colon that starts a
1371 ;; multiple inheritance introduction. Optional LIM is the farthest
1372 ;; back we should search.
1373 (let* ((lim (or lim (c-point 'bod))))
1374 (c-with-syntax-table c++-template-syntax-table
1375 (c-backward-token-1 0 t lim)
1376 (while (and (looking-at "[_a-zA-Z<,]")
1377 (= (c-backward-token-1 1 t lim) 0)))
1378 (skip-chars-forward "^:"))))
1380 (defun c-in-method-def-p ()
1381 ;; Return nil if we aren't in a method definition, otherwise the
1382 ;; position of the initial [+-].
1383 (save-excursion
1384 (beginning-of-line)
1385 (and c-opt-method-key
1386 (looking-at c-opt-method-key)
1387 (point))
1390 ;; Contributed by Kevin Ryde <user42@zip.com.au>.
1391 (defun c-in-gcc-asm-p ()
1392 ;; Return non-nil if point is within a gcc \"asm\" block.
1394 ;; This should be called with point inside an argument list.
1396 ;; Only one level of enclosing parentheses is considered, so for
1397 ;; instance `nil' is returned when in a function call within an asm
1398 ;; operand.
1400 (and c-opt-asm-stmt-key
1401 (save-excursion
1402 (beginning-of-line)
1403 (backward-up-list 1)
1404 (c-beginning-of-statement-1 (point-min) nil t)
1405 (looking-at c-opt-asm-stmt-key))))
1407 (defun c-at-toplevel-p ()
1408 "Return a determination as to whether point is at the `top-level'.
1409 Being at the top-level means that point is either outside any
1410 enclosing block (such function definition), or inside a class,
1411 namespace or extern definition, but outside any method blocks.
1413 If point is not at the top-level (e.g. it is inside a method
1414 definition), then nil is returned. Otherwise, if point is at a
1415 top-level not enclosed within a class definition, t is returned.
1416 Otherwise, a 2-vector is returned where the zeroth element is the
1417 buffer position of the start of the class declaration, and the first
1418 element is the buffer position of the enclosing class's opening
1419 brace."
1420 (let ((paren-state (c-parse-state)))
1421 (or (not (c-most-enclosing-brace paren-state))
1422 (c-search-uplist-for-classkey paren-state))))
1424 (defun c-forward-to-cpp-define-body ()
1425 ;; Assuming point is at the "#" that introduces a preprocessor
1426 ;; directive, it's moved forward to the start of the definition body
1427 ;; if it's a "#define". Non-nil is returned in this case, in all
1428 ;; other cases nil is returned and point isn't moved.
1429 (when (and (looking-at
1430 (concat "#[ \t]*"
1431 "define[ \t]+\\(\\sw\\|_\\)+\\(\([^\)]*\)\\)?"
1432 "\\([ \t]\\|\\\\\n\\)*"))
1433 (not (= (match-end 0) (c-point 'eol))))
1434 (goto-char (match-end 0))))
1436 (defun c-just-after-func-arglist-p (&optional containing lim)
1437 ;; Return t if we are between a function's argument list closing
1438 ;; paren and its opening brace. Note that the list close brace
1439 ;; could be followed by a "const" specifier or a member init hanging
1440 ;; colon. Optional CONTAINING is position of containing s-exp open
1441 ;; brace. If not supplied, point is used as search start. LIM is
1442 ;; used as bound for some backward buffer searches; the search might
1443 ;; continue past it.
1445 ;; Note: This test is easily fooled. It only works reasonably well
1446 ;; in the situations where `c-guess-basic-syntax' uses it.
1447 (save-excursion
1448 (c-backward-syntactic-ws lim)
1449 (let ((checkpoint (or containing (point))))
1450 (goto-char checkpoint)
1451 ;; could be looking at const specifier
1452 (if (and (eq (char-before) ?t)
1453 (forward-word -1)
1454 (looking-at "\\<const\\>[^_]"))
1455 (c-backward-syntactic-ws lim)
1456 ;; otherwise, we could be looking at a hanging member init
1457 ;; colon
1458 (goto-char checkpoint)
1459 (while (eq (char-before) ?,)
1460 ;; this will catch member inits with multiple
1461 ;; line arglists
1462 (forward-char -1)
1463 (c-backward-syntactic-ws (c-point 'bol))
1464 (if (eq (char-before) ?\))
1465 (c-backward-sexp 2)
1466 (c-backward-sexp 1))
1467 (c-backward-syntactic-ws lim))
1468 (if (and (eq (char-before) ?:)
1469 (progn
1470 (forward-char -1)
1471 (c-backward-syntactic-ws lim)
1472 (looking-at "\\([ \t\n]\\|\\\\\n\\)*:\\([^:]+\\|$\\)")))
1474 (goto-char checkpoint))
1476 (setq checkpoint (point))
1477 (and (eq (char-before) ?\))
1478 ;; Check that it isn't a cpp expression, e.g. the
1479 ;; expression of an #if directive or the "function header"
1480 ;; of a #define.
1481 (or (not (c-beginning-of-macro))
1482 (and (c-forward-to-cpp-define-body)
1483 (< (point) checkpoint)))
1484 ;; check if we are looking at an ObjC method def
1485 (or (not c-opt-method-key)
1486 (progn
1487 (goto-char checkpoint)
1488 (c-forward-sexp -1)
1489 (forward-char -1)
1490 (c-backward-syntactic-ws lim)
1491 (not (or (memq (char-before) '(?- ?+))
1492 ;; or a class category
1493 (progn
1494 (c-forward-sexp -2)
1495 (looking-at c-class-key))
1496 )))))
1499 (defun c-in-knr-argdecl (&optional lim)
1500 ;; Return the position of the first argument declaration if point is
1501 ;; inside a K&R style argument declaration list, nil otherwise.
1502 ;; `c-recognize-knr-p' is not checked. If LIM is non-nil, it's a
1503 ;; position that bounds the backward search for the argument list.
1505 ;; Note: A declaration level context is assumed; the test can return
1506 ;; false positives for statements and #define headers. This test is
1507 ;; even more easily fooled than `c-just-after-func-arglist-p'.
1508 (save-excursion
1509 (save-restriction
1510 ;; Go back to the closest preceding normal parenthesis sexp. We
1511 ;; take that as the argument list in the function header. Then
1512 ;; check that it's followed by some symbol before the next ';'
1513 ;; or '{'. If it does, it's the header of the K&R argdecl we're
1514 ;; in.
1515 (if lim (narrow-to-region lim (point)))
1516 (let (paren-end)
1517 (and (c-safe (setq paren-end (c-down-list-backward (point))))
1518 (eq (char-after paren-end) ?\))
1519 (progn
1520 (goto-char (1+ paren-end))
1521 (c-forward-syntactic-ws)
1522 (looking-at "\\w\\|\\s_"))
1523 (c-safe (c-up-list-backward paren-end))
1524 (point))))))
1526 (defun c-skip-conditional ()
1527 ;; skip forward over conditional at point, including any predicate
1528 ;; statements in parentheses. No error checking is performed.
1529 (c-forward-sexp (cond
1530 ;; else if()
1531 ((looking-at (concat "\\<else"
1532 "\\([ \t\n]\\|\\\\\n\\)+"
1533 "if\\>\\([^_]\\|$\\)"))
1535 ;; do, else, try, finally
1536 ((looking-at (concat "\\<\\("
1537 "do\\|else\\|try\\|finally"
1538 "\\)\\>\\([^_]\\|$\\)"))
1540 ;; for, if, while, switch, catch, synchronized, foreach
1541 (t 2))))
1543 (defun c-after-conditional (&optional lim)
1544 ;; If looking at the token after a conditional then return the
1545 ;; position of its start, otherwise return nil.
1546 (save-excursion
1547 (and (= (c-backward-token-1 1 t lim) 0)
1548 (or (looking-at c-block-stmt-1-key)
1549 (and (eq (char-after) ?\()
1550 (= (c-backward-token-1 1 t lim) 0)
1551 (looking-at c-block-stmt-2-key)))
1552 (point))))
1554 (defsubst c-backward-to-block-anchor (&optional lim)
1555 ;; Assuming point is at a brace that opens a statement block of some
1556 ;; kind, move to the proper anchor point for that block. It might
1557 ;; need to be adjusted further by c-add-stmt-syntax, but the
1558 ;; position at return is suitable as start position for that
1559 ;; function.
1560 (unless (= (point) (c-point 'boi))
1561 (let ((start (c-after-conditional lim)))
1562 (if start
1563 (goto-char start)))))
1565 (defun c-backward-to-decl-anchor (&optional lim)
1566 ;; Assuming point is at a brace that opens the block of a top level
1567 ;; declaration of some kind, move to the proper anchor point for
1568 ;; that block.
1569 (unless (= (point) (c-point 'boi))
1570 ;; What we have below is actually an extremely stripped variant of
1571 ;; c-beginning-of-statement-1.
1572 (let ((pos (point)))
1573 ;; Switch syntax table to avoid stopping at line continuations.
1574 (save-restriction
1575 (if lim (narrow-to-region lim (point-max)))
1576 (while (and (progn
1577 (c-backward-syntactic-ws)
1578 (c-safe (goto-char (scan-sexps (point) -1)) t))
1579 (not (c-crosses-statement-barrier-p (point) pos)))
1580 (setq pos (point)))
1581 (goto-char pos)))))
1583 (defsubst c-search-decl-header-end ()
1584 ;; Search forward for the end of the "header" of the current
1585 ;; declaration. That's the position where the definition body
1586 ;; starts, or the first variable initializer, or the ending
1587 ;; semicolon. I.e. search forward for the closest following
1588 ;; (syntactically relevant) '{', '=' or ';' token. Point is left
1589 ;; _after_ the first found token, or at point-max if none is found.
1590 (c-with-syntax-table (if (c-major-mode-is 'c++-mode)
1591 c++-template-syntax-table
1592 (syntax-table))
1593 (while (and (c-syntactic-re-search-forward "[;{=]" nil 'move 1 t)
1594 ;; In Pike it can be an operator identifier containing
1595 ;; '='.
1596 (c-major-mode-is 'pike-mode)
1597 (eq (char-before) ?=)
1598 (c-on-identifier)))))
1600 (defun c-beginning-of-decl-1 (&optional lim)
1601 ;; Go to the beginning of the current declaration, or the beginning
1602 ;; of the previous one if already at the start of it. Point won't
1603 ;; be moved out of any surrounding paren. Return a cons cell on the
1604 ;; form (MOVE . KNR-POS). MOVE is like the return value from
1605 ;; `c-beginning-of-statement-1'. If point skipped over some K&R
1606 ;; style argument declarations (and they are to be recognized) then
1607 ;; KNR-POS is set to the start of the first such argument
1608 ;; declaration, otherwise KNR-POS is nil. If LIM is non-nil, it's a
1609 ;; position that bounds the backward search.
1611 ;; NB: Cases where the declaration continues after the block, as in
1612 ;; "struct foo { ... } bar;", are currently recognized as two
1613 ;; declarations, e.g. "struct foo { ... }" and "bar;" in this case.
1614 (catch 'return
1615 (let* ((start (point))
1616 (last-stmt-start (point))
1617 (move (c-beginning-of-statement-1 lim t t)))
1619 (while (and (/= last-stmt-start (point))
1620 (save-excursion
1621 (c-backward-syntactic-ws lim)
1622 (not (memq (char-before) '(?\; ?} ?: nil)))))
1623 ;; `c-beginning-of-statement-1' stops at a block start, but we
1624 ;; want to continue if the block doesn't begin a top level
1625 ;; construct, i.e. if it isn't preceded by ';', '}', ':', or bob.
1626 (setq last-stmt-start (point)
1627 move (c-beginning-of-statement-1 lim t t)))
1629 (when c-recognize-knr-p
1630 (let ((fallback-pos (point)) knr-argdecl-start)
1631 ;; Handle K&R argdecls. Back up after the "statement" jumped
1632 ;; over by `c-beginning-of-statement-1', unless it was the
1633 ;; function body, in which case we're sitting on the opening
1634 ;; brace now. Then test if we're in a K&R argdecl region and
1635 ;; that we started at the other side of the first argdecl in
1636 ;; it.
1637 (unless (eq (char-after) ?{)
1638 (goto-char last-stmt-start))
1639 (if (and (setq knr-argdecl-start (c-in-knr-argdecl lim))
1640 (< knr-argdecl-start start)
1641 (progn
1642 (goto-char knr-argdecl-start)
1643 (not (eq (c-beginning-of-statement-1 lim t t) 'macro))))
1644 (throw 'return
1645 (cons (if (eq (char-after fallback-pos) ?{)
1646 'previous
1647 'same)
1648 knr-argdecl-start))
1649 (goto-char fallback-pos))))
1651 (when c-opt-access-key
1652 ;; Might have ended up before a protection label. This should
1653 ;; perhaps be checked before `c-recognize-knr-p' to be really
1654 ;; accurate, but we know that no language has both.
1655 (while (looking-at c-opt-access-key)
1656 (goto-char (match-end 0))
1657 (c-forward-syntactic-ws)
1658 (when (>= (point) start)
1659 (goto-char start)
1660 (throw 'return (cons 'same nil)))))
1662 ;; `c-beginning-of-statement-1' counts each brace block as a
1663 ;; separate statement, so the result will be 'previous if we've
1664 ;; moved over any. If they were brace list initializers we might
1665 ;; not have moved over a declaration boundary though, so change it
1666 ;; to 'same if we've moved past a '=' before '{', but not ';'.
1667 ;; (This ought to be integrated into `c-beginning-of-statement-1',
1668 ;; so we avoid this extra pass which potentially can search over a
1669 ;; large amount of text.)
1670 (if (and (eq move 'previous)
1671 (c-with-syntax-table (if (c-major-mode-is 'c++-mode)
1672 c++-template-syntax-table
1673 (syntax-table))
1674 (save-excursion
1675 (and (c-syntactic-re-search-forward "[;={]" start t 1 t)
1676 (eq (char-before) ?=)
1677 (c-syntactic-re-search-forward "[;{]" start t 1 t)
1678 (eq (char-before) ?{)
1679 (c-safe (goto-char (c-up-list-forward (point))) t)
1680 (not (c-syntactic-re-search-forward ";" start t 1 t))))))
1681 (cons 'same nil)
1682 (cons move nil)))))
1684 (defun c-end-of-decl-1 ()
1685 ;; Assuming point is at the start of a declaration (as detected by
1686 ;; e.g. `c-beginning-of-decl-1'), go to the end of it. Unlike
1687 ;; `c-beginning-of-decl-1', this function handles the case when a
1688 ;; block is followed by identifiers in e.g. struct declarations in C
1689 ;; or C++. If a proper end was found then t is returned, otherwise
1690 ;; point is moved as far as possible within the current sexp and nil
1691 ;; is returned. This function doesn't handle macros; use
1692 ;; `c-end-of-macro' instead in those cases.
1693 (let ((start (point))
1694 (decl-syntax-table (if (c-major-mode-is 'c++-mode)
1695 c++-template-syntax-table
1696 (syntax-table))))
1697 (catch 'return
1698 (c-search-decl-header-end)
1700 (when (and c-recognize-knr-p
1701 (eq (char-before) ?\;)
1702 (c-in-knr-argdecl start))
1703 ;; Stopped at the ';' in a K&R argdecl section which is
1704 ;; detected using the same criteria as in
1705 ;; `c-beginning-of-decl-1'. Move to the following block
1706 ;; start.
1707 (c-syntactic-re-search-forward "{" nil 'move 1 t))
1709 (when (eq (char-before) ?{)
1710 ;; Encountered a block in the declaration. Jump over it.
1711 (condition-case nil
1712 (goto-char (c-up-list-forward (point)))
1713 (goto-char (point-max))
1714 (throw 'return nil))
1715 (if (or (not c-opt-block-decls-with-vars-key)
1716 (save-excursion
1717 (c-with-syntax-table decl-syntax-table
1718 (let ((lim (point)))
1719 (goto-char start)
1720 (not (and
1721 ;; Check for `c-opt-block-decls-with-vars-key'
1722 ;; before the first paren.
1723 (c-syntactic-re-search-forward
1724 (concat "[;=\(\[{]\\|\\<\\("
1725 c-opt-block-decls-with-vars-key
1726 "\\)")
1727 lim t 1 t)
1728 (match-beginning 1)
1729 (not (eq (char-before) ?_))
1730 ;; Check that the first following paren is the block.
1731 (c-syntactic-re-search-forward "[;=\(\[{]" lim t 1 t)
1732 (eq (char-before) ?{)))))))
1733 ;; The declaration doesn't have any of the
1734 ;; `c-opt-block-decls-with-vars' keywords in the
1735 ;; beginning, so it ends here at the end of the block.
1736 (throw 'return t)))
1738 (c-with-syntax-table decl-syntax-table
1739 (while (progn
1740 (if (eq (char-before) ?\;)
1741 (throw 'return t))
1742 (c-syntactic-re-search-forward ";" nil 'move 1 t))))
1743 nil)))
1745 (defun c-beginning-of-member-init-list (&optional limit)
1746 ;; Goes to the beginning of a member init list (i.e. just after the
1747 ;; ':') if inside one. Returns t in that case, nil otherwise.
1748 (or limit
1749 (setq limit (point-min)))
1750 (skip-chars-forward " \t")
1751 (if (eq (char-after) ?,)
1752 (forward-char 1)
1753 (c-backward-syntactic-ws limit))
1754 (while (and (< limit (point))
1755 (eq (char-before) ?,))
1756 ;; this will catch member inits with multiple
1757 ;; line arglists
1758 (forward-char -1)
1759 (c-backward-syntactic-ws limit)
1760 (if (eq (char-before) ?\))
1761 (c-backward-sexp 1))
1762 (c-backward-syntactic-ws limit)
1763 ;; Skip over any template arg to the class.
1764 (if (eq (char-before) ?>)
1765 (c-with-syntax-table c++-template-syntax-table
1766 (c-backward-sexp 1)))
1767 (c-backward-sexp 1)
1768 (c-backward-syntactic-ws limit)
1769 ;; Skip backwards over a fully::qualified::name.
1770 (while (and (eq (char-before) ?:)
1771 (save-excursion
1772 (forward-char -1)
1773 (eq (char-before) ?:)))
1774 (backward-char 2)
1775 (c-backward-sexp 1))
1776 ;; now continue checking
1777 (c-backward-syntactic-ws limit))
1778 (and (< limit (point))
1779 (eq (char-before) ?:)))
1781 (defun c-search-uplist-for-classkey (paren-state)
1782 ;; search for the containing class, returning a 2 element vector if
1783 ;; found. aref 0 contains the bufpos of the boi of the class key
1784 ;; line, and aref 1 contains the bufpos of the open brace.
1785 (if (null paren-state)
1786 ;; no paren-state means we cannot be inside a class
1788 (let ((carcache (car paren-state))
1789 search-start search-end)
1790 (if (consp carcache)
1791 ;; a cons cell in the first element means that there is some
1792 ;; balanced sexp before the current bufpos. this we can
1793 ;; ignore. the nth 1 and nth 2 elements define for us the
1794 ;; search boundaries
1795 (setq search-start (nth 2 paren-state)
1796 search-end (nth 1 paren-state))
1797 ;; if the car was not a cons cell then nth 0 and nth 1 define
1798 ;; for us the search boundaries
1799 (setq search-start (nth 1 paren-state)
1800 search-end (nth 0 paren-state)))
1801 ;; if search-end is nil, or if the search-end character isn't an
1802 ;; open brace, we are definitely not in a class
1803 (when (consp search-end)
1804 (setq search-end (car search-end)))
1805 (unless (or (not search-end)
1806 (< search-end (point-min))
1807 (not (eq (char-after search-end) ?{)))
1808 ;; now, we need to look more closely at search-start. if
1809 ;; search-start is nil, then our start boundary is really
1810 ;; point-min.
1811 (if (not search-start)
1812 (setq search-start (point-min))
1813 ;; if search-start is a cons cell, then we can start
1814 ;; searching from the end of the balanced sexp just ahead of
1815 ;; us
1816 (if (consp search-start)
1817 (setq search-start (cdr search-start))))
1818 ;; now we can do a quick regexp search from search-start to
1819 ;; search-end and see if we can find a class key. watch for
1820 ;; class like strings in literals
1821 (save-excursion
1822 (save-restriction
1823 (goto-char search-start)
1824 (let (foundp class match-end)
1825 (while (and (not foundp)
1826 (progn
1827 (c-forward-syntactic-ws search-end)
1828 (> search-end (point)))
1829 (re-search-forward c-decl-block-key search-end t))
1830 (setq class (match-beginning 0)
1831 match-end (match-end 0))
1832 (goto-char class)
1833 (if (c-in-literal search-start)
1834 (goto-char match-end) ; its in a comment or string, ignore
1835 (c-skip-ws-forward)
1836 (setq foundp (vector (c-point 'boi) search-end))
1837 (cond
1838 ;; check for embedded keywords
1839 ((let ((char (char-after (1- class))))
1840 (and char
1841 (memq (char-syntax char) '(?w ?_))))
1842 (goto-char match-end)
1843 (setq foundp nil))
1844 ;; make sure we're really looking at the start of a
1845 ;; class definition, and not an ObjC method.
1846 ((and c-opt-method-key
1847 (re-search-forward c-opt-method-key search-end t)
1848 (not (c-in-literal class)))
1849 (setq foundp nil))
1850 ;; Check if this is an anonymous inner class.
1851 ((and c-opt-inexpr-class-key
1852 (looking-at c-opt-inexpr-class-key))
1853 (while (and (= (c-forward-token-1 1 t) 0)
1854 (looking-at "(\\|\\w\\|\\s_\\|\\.")))
1855 (if (eq (point) search-end)
1856 ;; We're done. Just trap this case in the cond.
1858 ;; False alarm; all conditions aren't satisfied.
1859 (setq foundp nil)))
1860 ;; Its impossible to define a regexp for this, and
1861 ;; nearly so to do it programmatically.
1863 ;; ; picks up forward decls
1864 ;; = picks up init lists
1865 ;; ) picks up return types
1866 ;; > picks up templates, but remember that we can
1867 ;; inherit from templates!
1868 ((let ((skipchars "^;=)"))
1869 ;; try to see if we found the `class' keyword
1870 ;; inside a template arg list
1871 (save-excursion
1872 (skip-chars-backward "^<>" search-start)
1873 (if (eq (char-before) ?<)
1874 (setq skipchars (concat skipchars ">"))))
1875 (while (progn
1876 (skip-chars-forward skipchars search-end)
1877 (c-in-literal class))
1878 (forward-char))
1879 (/= (point) search-end))
1880 (setq foundp nil))
1882 foundp))
1883 )))))
1885 (defun c-inside-bracelist-p (containing-sexp paren-state)
1886 ;; return the buffer position of the beginning of the brace list
1887 ;; statement if we're inside a brace list, otherwise return nil.
1888 ;; CONTAINING-SEXP is the buffer pos of the innermost containing
1889 ;; paren. BRACE-STATE is the remainder of the state of enclosing
1890 ;; braces
1892 ;; N.B.: This algorithm can potentially get confused by cpp macros
1893 ;; places in inconvenient locations. Its a trade-off we make for
1894 ;; speed.
1896 ;; this will pick up enum lists
1897 (c-safe
1898 (save-excursion
1899 (goto-char containing-sexp)
1900 (c-forward-sexp -1)
1901 (let (bracepos)
1902 (if (and (or (looking-at "enum\\>[^_]")
1903 (progn (c-forward-sexp -1)
1904 (looking-at "enum\\>[^_]")))
1905 (setq bracepos (c-down-list-forward (point)))
1906 (not (c-crosses-statement-barrier-p (point)
1907 (- bracepos 2))))
1908 (point)))))
1909 ;; this will pick up array/aggregate init lists, even if they are nested.
1910 (save-excursion
1911 (let ((class-key
1912 ;; Pike can have class definitions anywhere, so we must
1913 ;; check for the class key here.
1914 (and (c-major-mode-is 'pike-mode)
1915 c-decl-block-key))
1916 bufpos braceassignp lim next-containing)
1917 (while (and (not bufpos)
1918 containing-sexp)
1919 (when paren-state
1920 (if (consp (car paren-state))
1921 (setq lim (cdr (car paren-state))
1922 paren-state (cdr paren-state))
1923 (setq lim (car paren-state)))
1924 (when paren-state
1925 (setq next-containing (car paren-state)
1926 paren-state (cdr paren-state))))
1927 (goto-char containing-sexp)
1928 (if (c-looking-at-inexpr-block next-containing next-containing)
1929 ;; We're in an in-expression block of some kind. Do not
1930 ;; check nesting. We deliberately set the limit to the
1931 ;; containing sexp, so that c-looking-at-inexpr-block
1932 ;; doesn't check for an identifier before it.
1933 (setq containing-sexp nil)
1934 ;; see if the open brace is preceded by = or [...] in
1935 ;; this statement, but watch out for operator=
1936 (setq braceassignp 'dontknow)
1937 (c-backward-token-1 1 t lim)
1938 ;; Checks to do only on the first sexp before the brace.
1939 (when (and (c-major-mode-is 'java-mode)
1940 (eq (char-after) ?\[))
1941 ;; In Java, an initialization brace list may follow
1942 ;; directly after "new Foo[]", so check for a "new"
1943 ;; earlier.
1944 (while (eq braceassignp 'dontknow)
1945 (setq braceassignp
1946 (cond ((/= (c-backward-token-1 1 t lim) 0) nil)
1947 ((looking-at "new\\>[^_]") t)
1948 ((looking-at "\\sw\\|\\s_\\|[.[]")
1949 ;; Carry on looking if this is an
1950 ;; identifier (may contain "." in Java)
1951 ;; or another "[]" sexp.
1952 'dontknow)
1953 (t nil)))))
1954 ;; Checks to do on all sexps before the brace, up to the
1955 ;; beginning of the statement.
1956 (while (eq braceassignp 'dontknow)
1957 (cond ((eq (char-after) ?\;)
1958 (setq braceassignp nil))
1959 ((and class-key
1960 (looking-at class-key))
1961 (setq braceassignp nil))
1962 ((eq (char-after) ?=)
1963 ;; We've seen a =, but must check earlier tokens so
1964 ;; that it isn't something that should be ignored.
1965 (setq braceassignp 'maybe)
1966 (while (and (eq braceassignp 'maybe)
1967 (zerop (c-backward-token-1 1 t lim)))
1968 (setq braceassignp
1969 (cond
1970 ;; Check for operator =
1971 ((looking-at "operator\\>[^_]") nil)
1972 ;; Check for `<opchar>= in Pike.
1973 ((and (c-major-mode-is 'pike-mode)
1974 (or (eq (char-after) ?`)
1975 ;; Special case for Pikes
1976 ;; `[]=, since '[' is not in
1977 ;; the punctuation class.
1978 (and (eq (char-after) ?\[)
1979 (eq (char-before) ?`))))
1980 nil)
1981 ((looking-at "\\s.") 'maybe)
1982 ;; make sure we're not in a C++ template
1983 ;; argument assignment
1984 ((and
1985 (c-major-mode-is 'c++-mode)
1986 (save-excursion
1987 (let ((here (point))
1988 (pos< (progn
1989 (skip-chars-backward "^<>")
1990 (point))))
1991 (and (eq (char-before) ?<)
1992 (not (c-crosses-statement-barrier-p
1993 pos< here))
1994 (not (c-in-literal))
1995 ))))
1996 nil)
1997 (t t))))))
1998 (if (and (eq braceassignp 'dontknow)
1999 (/= (c-backward-token-1 1 t lim) 0))
2000 (setq braceassignp nil)))
2001 (if (not braceassignp)
2002 (if (eq (char-after) ?\;)
2003 ;; Brace lists can't contain a semicolon, so we're done.
2004 (setq containing-sexp nil)
2005 ;; Go up one level.
2006 (setq containing-sexp next-containing
2007 lim nil
2008 next-containing nil))
2009 ;; we've hit the beginning of the aggregate list
2010 (c-beginning-of-statement-1
2011 (c-most-enclosing-brace paren-state))
2012 (setq bufpos (point))))
2014 bufpos))
2017 (defun c-looking-at-special-brace-list (&optional lim)
2018 ;; If we're looking at the start of a pike-style list, ie `({ })',
2019 ;; `([ ])', `(< >)' etc, a cons of a cons of its starting and ending
2020 ;; positions and its entry in c-special-brace-lists is returned, nil
2021 ;; otherwise. The ending position is nil if the list is still open.
2022 ;; LIM is the limit for forward search. The point may either be at
2023 ;; the `(' or at the following paren character. Tries to check the
2024 ;; matching closer, but assumes it's correct if no balanced paren is
2025 ;; found (i.e. the case `({ ... } ... )' is detected as _not_ being
2026 ;; a special brace list).
2027 (if c-special-brace-lists
2028 (condition-case ()
2029 (save-excursion
2030 (let ((beg (point))
2031 end type)
2032 (c-forward-syntactic-ws)
2033 (if (eq (char-after) ?\()
2034 (progn
2035 (forward-char 1)
2036 (c-forward-syntactic-ws)
2037 (setq type (assq (char-after) c-special-brace-lists)))
2038 (if (setq type (assq (char-after) c-special-brace-lists))
2039 (progn
2040 (c-backward-syntactic-ws)
2041 (forward-char -1)
2042 (setq beg (if (eq (char-after) ?\()
2043 (point)
2044 nil)))))
2045 (if (and beg type)
2046 (if (and (c-safe (goto-char beg)
2047 (c-forward-sexp 1)
2048 (setq end (point))
2049 (= (char-before) ?\)))
2050 (c-safe (goto-char beg)
2051 (forward-char 1)
2052 (c-forward-sexp 1)
2053 ;; Kludges needed to handle inner
2054 ;; chars both with and without
2055 ;; paren syntax.
2056 (or (/= (char-syntax (char-before)) ?\))
2057 (= (char-before) (cdr type)))))
2058 (if (or (/= (char-syntax (char-before)) ?\))
2059 (= (progn
2060 (c-forward-syntactic-ws)
2061 (point))
2062 (1- end)))
2063 (cons (cons beg end) type))
2064 (cons (list beg) type)))))
2065 (error nil))))
2067 (defun c-looking-at-bos (&optional lim)
2068 ;; Return non-nil if between two statements or declarations, assuming
2069 ;; point is not inside a literal or comment.
2070 (save-excursion
2071 (c-backward-syntactic-ws lim)
2072 (or (bobp)
2073 ;; Return t if at the start inside some parenthesis expression
2074 ;; too, to catch macros that have statements as arguments.
2075 (memq (char-before) '(?\; ?} ?\())
2076 (and (eq (char-before) ?{)
2077 (not (and c-special-brace-lists
2078 (progn (backward-char)
2079 (c-looking-at-special-brace-list))))))))
2081 (defun c-looking-at-inexpr-block (lim containing-sexp)
2082 ;; Returns non-nil if we're looking at the beginning of a block
2083 ;; inside an expression. The value returned is actually a cons of
2084 ;; either 'inlambda, 'inexpr-statement or 'inexpr-class and the
2085 ;; position of the beginning of the construct. LIM limits the
2086 ;; backward search. CONTAINING-SEXP is the start position of the
2087 ;; closest containing list. If it's nil, the containing paren isn't
2088 ;; used to decide whether we're inside an expression or not. If
2089 ;; both LIM and CONTAINING-SEXP is used, LIM needs to be farther
2090 ;; back.
2091 (save-excursion
2092 (let ((res 'maybe) passed-bracket
2093 (closest-lim (or containing-sexp lim (point-min)))
2094 ;; Look at the character after point only as a last resort
2095 ;; when we can't disambiguate.
2096 (block-follows (and (eq (char-after) ?{) (point))))
2097 (while (and (eq res 'maybe)
2098 (progn (c-backward-syntactic-ws)
2099 (> (point) closest-lim))
2100 (not (bobp))
2101 (progn (backward-char)
2102 (looking-at "[\]\).]\\|\\w\\|\\s_"))
2103 (progn (forward-char)
2104 (goto-char (scan-sexps (point) -1))))
2105 (setq res
2106 (cond
2107 ((and block-follows
2108 c-opt-inexpr-class-key
2109 (looking-at c-opt-inexpr-class-key))
2110 (and (not passed-bracket)
2111 (or (not (looking-at c-class-key))
2112 ;; If the class definition is at the start of
2113 ;; a statement, we don't consider it an
2114 ;; in-expression class.
2115 (let ((prev (point)))
2116 (while (and
2117 (= (c-backward-token-1 1 nil closest-lim) 0)
2118 (eq (char-syntax (char-after)) ?w))
2119 (setq prev (point)))
2120 (goto-char prev)
2121 (not (c-looking-at-bos)))
2122 ;; Also, in Pike we treat it as an
2123 ;; in-expression class if it's used in an
2124 ;; object clone expression.
2125 (save-excursion
2126 (and (c-major-mode-is 'pike-mode)
2127 (progn (goto-char block-follows)
2128 (= (c-forward-token-1 1 t) 0))
2129 (eq (char-after) ?\())))
2130 (cons 'inexpr-class (point))))
2131 ((and c-opt-inexpr-block-key
2132 (looking-at c-opt-inexpr-block-key))
2133 (cons 'inexpr-statement (point)))
2134 ((and c-opt-lambda-key
2135 (looking-at c-opt-lambda-key))
2136 (cons 'inlambda (point)))
2137 ((and c-opt-block-stmt-key
2138 (looking-at c-opt-block-stmt-key))
2139 nil)
2141 (if (eq (char-after) ?\[)
2142 (setq passed-bracket t))
2143 'maybe))))
2144 (if (eq res 'maybe)
2145 (when (and block-follows
2146 containing-sexp
2147 (eq (char-after containing-sexp) ?\())
2148 (goto-char containing-sexp)
2149 (if (or (save-excursion
2150 (c-backward-syntactic-ws lim)
2151 (and (> (point) (or lim (point-min)))
2152 (c-on-identifier)))
2153 (and c-special-brace-lists
2154 (c-looking-at-special-brace-list)))
2156 (cons 'inexpr-statement (point))))
2157 res))))
2159 (defun c-looking-at-inexpr-block-backward (paren-state)
2160 ;; Returns non-nil if we're looking at the end of an in-expression
2161 ;; block, otherwise the same as `c-looking-at-inexpr-block'.
2162 ;; PAREN-STATE is the paren state relevant at the current position.
2163 (save-excursion
2164 ;; We currently only recognize a block.
2165 (let ((here (point))
2166 (elem (car-safe paren-state))
2167 containing-sexp)
2168 (when (and (consp elem)
2169 (progn (goto-char (cdr elem))
2170 (c-forward-syntactic-ws here)
2171 (= (point) here)))
2172 (goto-char (car elem))
2173 (if (setq paren-state (cdr paren-state))
2174 (setq containing-sexp (car-safe paren-state)))
2175 (c-looking-at-inexpr-block (c-safe-position containing-sexp
2176 paren-state)
2177 containing-sexp)))))
2179 (defun c-on-identifier ()
2180 "Return non-nil if we're on or directly after an identifier.
2181 Keywords are recognized and not considered identifiers."
2182 (if (or (memq (char-syntax (or (char-after) ? )) '(?w ?_))
2183 (memq (char-syntax (or (char-before) ? )) '(?w ?_)))
2184 (save-excursion
2185 (skip-syntax-backward "w_")
2186 (not (looking-at c-keywords-regexp)))
2187 (if (c-major-mode-is 'pike-mode)
2188 ;; Handle the `<operator> syntax in Pike.
2189 (save-excursion
2190 (if (eq (char-after) ?\`) (forward-char))
2191 (skip-chars-backward "!%&*+\\-/<=>^|~")
2192 (let ((pos (point)))
2193 (cond ((memq (char-before) '(?\) ?\]))
2194 (c-safe (backward-char 2)))
2195 ((memq (char-before) '(?\( ?\[))
2196 (c-safe (backward-char 1))))
2197 (if (not (looking-at "()\\|\\[]"))
2198 (goto-char pos)))
2199 (and (eq (char-before) ?\`)
2200 (looking-at "[-!%&*+/<=>^|~]\\|()\\|\\[]"))))))
2203 (defun c-most-enclosing-brace (paren-state &optional bufpos)
2204 ;; Return the bufpos of the innermost enclosing brace before bufpos
2205 ;; that hasn't been narrowed out, or nil if none was found.
2206 (let (enclosingp)
2207 (or bufpos (setq bufpos 134217727))
2208 (while paren-state
2209 (setq enclosingp (car paren-state)
2210 paren-state (cdr paren-state))
2211 (if (or (consp enclosingp)
2212 (>= enclosingp bufpos))
2213 (setq enclosingp nil)
2214 (if (< enclosingp (point-min))
2215 (setq enclosingp nil))
2216 (setq paren-state nil)))
2217 enclosingp))
2219 (defun c-least-enclosing-brace (paren-state &optional bufpos)
2220 ;; Return the bufpos of the outermost enclosing brace before bufpos
2221 ;; that hasn't been narrowed out, or nil if none was found.
2222 (let (pos elem)
2223 (or bufpos (setq bufpos 134217727))
2224 (while paren-state
2225 (setq elem (car paren-state)
2226 paren-state (cdr paren-state))
2227 (unless (or (consp elem)
2228 (>= elem bufpos))
2229 (if (>= elem (point-min))
2230 (setq pos elem))))
2231 pos))
2233 (defun c-safe-position (bufpos paren-state)
2234 ;; Return the closest known safe position higher up than BUFPOS, or
2235 ;; nil if PAREN-STATE doesn't contain one. Return nil if BUFPOS is
2236 ;; nil, which is useful to find the closest limit before a given
2237 ;; limit that might be nil.
2238 (when bufpos
2239 (let ((c-macro-start (c-query-macro-start)) safepos)
2240 (if (and c-macro-start
2241 (< c-macro-start bufpos))
2242 ;; Make sure bufpos is outside the macro we might be in.
2243 (setq bufpos c-macro-start))
2244 (catch 'done
2245 (while paren-state
2246 (setq safepos
2247 (if (consp (car paren-state))
2248 (cdr (car paren-state))
2249 (car paren-state)))
2250 (if (< safepos bufpos)
2251 (throw 'done safepos)
2252 (setq paren-state (cdr paren-state))))
2253 (if (eq c-macro-start bufpos)
2254 ;; Backed up bufpos to the macro start and got outside the
2255 ;; state. We know the macro is at the top level in this case,
2256 ;; so we can use the macro start as the safe position.
2257 c-macro-start)))))
2259 (defun c-narrow-out-enclosing-class (paren-state lim)
2260 ;; Narrow the buffer so that the enclosing class is hidden. Uses
2261 ;; and returns the value from c-search-uplist-for-classkey.
2262 (setq paren-state (c-whack-state-after (point) paren-state))
2263 (let (inclass-p)
2264 (and paren-state
2265 (setq inclass-p (c-search-uplist-for-classkey paren-state))
2266 (narrow-to-region
2267 (progn
2268 (goto-char (1+ (aref inclass-p 1)))
2269 (c-skip-ws-forward lim)
2270 ;; if point is now left of the class opening brace, we're
2271 ;; hosed, so try a different tact
2272 (if (<= (point) (aref inclass-p 1))
2273 (progn
2274 (goto-char (1+ (aref inclass-p 1)))
2275 (c-forward-syntactic-ws lim)))
2276 (point))
2277 ;; end point is the end of the current line
2278 (progn
2279 (goto-char lim)
2280 (c-point 'eol))))
2281 ;; return the class vector
2282 inclass-p))
2285 ;; c-guess-basic-syntax implements the main decision tree for
2286 ;; determining the syntactic analysis of the current line of code.
2287 ;; Yes, it's huge and bloated!
2289 ;; It's useful to break out some parts of the decision tree to
2290 ;; separate functions, which are all collected below. Use dynamic
2291 ;; binding to propagate back the syntax results from them.
2292 (defvar syntax)
2293 (defvar syntactic-relpos)
2295 (defun c-add-stmt-syntax (syntax-symbol
2296 stop-at-boi-only
2297 containing-sexp
2298 paren-state
2299 &optional at-block-start)
2300 ;; Do the generic processing to anchor the given syntax symbol on
2301 ;; the preceding statement: Skip over any labels and containing
2302 ;; statements on the same line, and then search backward until we
2303 ;; find a statement or block start that begins at boi without a
2304 ;; label or comment.
2306 ;; Point is assumed to be at the prospective anchor point for the
2307 ;; given SYNTAX-SYMBOL. More syntax entries are added if we need to
2308 ;; skip past block opens and containing statement. All the added
2309 ;; syntax elements will get the same anchor point.
2311 ;; If STOP-AT-BOI-ONLY is nil, we might stop in the middle of the
2312 ;; line if another statement precedes the current one on this line.
2314 ;; If AT-BLOCK-START is non-nil, point is taken to be at the
2315 ;; beginning of a block or brace list, which then might be nested
2316 ;; inside an expression. If AT-BLOCK-START is nil, this is found
2317 ;; out by checking whether the character at point is "{" or not.
2318 (if (= (point) (c-point 'boi))
2319 ;; This is by far the most common case, so let's give it special
2320 ;; treatment.
2321 (c-add-syntax syntax-symbol (point))
2323 (let* ((savepos (point))
2324 (syms (list syntax-symbol))
2325 (syms-tail syms)
2326 (boi (c-point 'boi))
2327 (prev-paren (if at-block-start ?{ (char-after)))
2328 step-type step-tmp at-comment add-inexpr-stmt)
2330 ;; Begin by skipping any labels and containing statements that
2331 ;; are on the same line.
2332 (while (and (/= (point) boi)
2333 (if (memq (setq step-tmp
2334 (c-beginning-of-statement-1 boi nil t))
2335 '(up label))
2337 (goto-char savepos)
2338 nil)
2339 (/= (point) savepos))
2340 (setq savepos (point)
2341 step-type step-tmp))
2343 (catch 'done
2344 ;; Loop if we have to back out of the containing block.
2345 (while
2346 (progn
2347 ;; Loop if we have to back up another statement.
2348 (while
2349 (progn
2351 ;; Always start by skipping over any comments that
2352 ;; stands between the statement and boi.
2353 (while (and (/= (setq savepos (point)) boi)
2354 (c-forward-comment -1))
2355 (setq at-comment t
2356 boi (c-point 'boi)))
2357 (goto-char savepos)
2359 (and
2360 (or at-comment
2361 (eq step-type 'label)
2362 (/= savepos boi))
2364 (progn
2365 ;; Current position might not be good enough;
2366 ;; skip backward another statement.
2367 (setq step-type (c-beginning-of-statement-1
2368 containing-sexp))
2370 (if (and (not stop-at-boi-only)
2371 (/= savepos boi)
2372 (memq step-type '(up previous)))
2373 ;; If stop-at-boi-only is nil, we shouldn't
2374 ;; back up over previous or containing
2375 ;; statements to try to reach boi, so go
2376 ;; back to the last position and exit.
2377 (progn
2378 (goto-char savepos)
2379 nil)
2380 (if (and (not stop-at-boi-only)
2381 (memq step-type '(up previous beginning)))
2382 ;; If we've moved into another statement
2383 ;; then we should no longer try to stop
2384 ;; after boi.
2385 (setq stop-at-boi-only t))
2387 ;; Record this a substatement if we skipped up
2388 ;; one level, but not if we're still on the
2389 ;; same line. This so e.g. a sequence of "else
2390 ;; if" clauses won't indent deeper and deeper.
2391 (when (and (eq step-type 'up)
2392 (< (point) boi))
2393 (setcdr syms-tail (list 'substatement))
2394 (setq syms-tail (cdr syms-tail)))
2396 (setq boi (c-point 'boi))
2397 (/= (point) savepos)))))
2399 (setq savepos (point)
2400 at-comment nil))
2401 (setq at-comment nil)
2403 (when (and (eq step-type 'same)
2404 containing-sexp)
2405 (goto-char containing-sexp)
2406 (setq paren-state (c-whack-state-after containing-sexp
2407 paren-state)
2408 containing-sexp (c-most-enclosing-brace paren-state))
2411 (when (eq (setq prev-paren (char-after)) ?\()
2412 (c-backward-syntactic-ws containing-sexp)
2413 (when (c-on-identifier)
2414 ;; Arrived at a function arglist start. Exit with
2415 ;; the position of the first argument inside it.
2416 (goto-char savepos)
2417 (throw 'done t))
2418 ;; We're in an in-expression statement. Remember
2419 ;; this. We'll iterate below, but won't add any
2420 ;; syntax element.
2421 (setq add-inexpr-stmt t))
2423 (setq savepos (point)
2424 boi (c-point 'boi)
2425 step-type (c-beginning-of-statement-1 containing-sexp))
2427 (let ((at-bod (and (eq step-type 'same)
2428 (/= savepos (point))
2429 (eq prev-paren ?{))))
2430 (when (= savepos boi)
2431 ;; If the open brace was at boi, we're always
2432 ;; done. The c-beginning-of-statement-1 call
2433 ;; above is necessary anyway, to decide the type
2434 ;; of block-intro to add.
2435 (goto-char savepos)
2436 (setq savepos nil))
2438 (when (eq prev-paren ?{)
2439 (setcdr syms-tail (list (if at-bod
2440 'defun-block-intro
2441 'statement-block-intro)))
2442 (setq syms-tail (cdr syms-tail)))
2444 (when (and (not at-bod) savepos)
2445 ;; Loop if the brace wasn't at boi, and we didn't
2446 ;; arrive at a defun block.
2447 (if (eq step-type 'same)
2448 ;; Avoid backing up another sexp if the point
2449 ;; we're at now is found to be good enough in
2450 ;; the loop above.
2451 (setq step-type nil))
2452 (if (and (not stop-at-boi-only)
2453 (memq step-type '(up previous beginning)))
2454 (setq stop-at-boi-only t))
2455 (setq boi (c-point 'boi)))))
2458 (while syms
2459 (c-add-syntax (car syms) (point))
2460 (setq syms (cdr syms)))
2461 (if add-inexpr-stmt
2462 (c-add-syntax 'inexpr-statement))
2465 (defun c-add-class-syntax (symbol classkey paren-state)
2466 ;; The inclass and class-close syntactic symbols are added in
2467 ;; several places and some work is needed to fix everything.
2468 ;; Therefore it's collected here.
2469 (save-restriction
2470 (widen)
2471 (let (inexpr anchor containing-sexp)
2472 (goto-char (aref classkey 1))
2473 (if (and (eq symbol 'inclass) (= (point) (c-point 'boi)))
2474 (c-add-syntax symbol (setq anchor (point)))
2475 (c-add-syntax symbol (setq anchor (aref classkey 0)))
2476 (if (and c-opt-inexpr-class-key
2477 (setq containing-sexp (c-most-enclosing-brace paren-state
2478 (point))
2479 inexpr (cdr (c-looking-at-inexpr-block
2480 (c-safe-position containing-sexp
2481 paren-state)
2482 containing-sexp)))
2483 (/= inexpr (c-point 'boi inexpr)))
2484 (c-add-syntax 'inexpr-class)))
2485 anchor)))
2487 (defun c-guess-continued-construct (indent-point
2488 char-after-ip
2489 beg-of-same-or-containing-stmt
2490 containing-sexp
2491 paren-state)
2492 ;; This function contains the decision tree reached through both
2493 ;; cases 18 and 10. It's a continued statement or top level
2494 ;; construct of some kind.
2495 (let (special-brace-list)
2496 (goto-char indent-point)
2497 (skip-chars-forward " \t")
2498 (cond
2499 ;; (CASE A removed.)
2500 ;; CASE B: open braces for class or brace-lists
2501 ((setq special-brace-list
2502 (or (and c-special-brace-lists
2503 (c-looking-at-special-brace-list))
2504 (eq char-after-ip ?{)))
2505 (cond
2506 ;; CASE B.1: class-open
2507 ((save-excursion
2508 (goto-char indent-point)
2509 (skip-chars-forward " \t{")
2510 (let ((decl (c-search-uplist-for-classkey (c-parse-state))))
2511 (and decl
2512 (setq beg-of-same-or-containing-stmt (aref decl 0)))
2514 (c-add-syntax 'class-open beg-of-same-or-containing-stmt))
2515 ;; CASE B.2: brace-list-open
2516 ((or (consp special-brace-list)
2517 (save-excursion
2518 (goto-char beg-of-same-or-containing-stmt)
2519 (looking-at "enum\\>[^_]"))
2520 (save-excursion
2521 (goto-char indent-point)
2522 (while (and (> (point) beg-of-same-or-containing-stmt)
2523 (= (c-backward-token-1 1 t) 0)
2524 (/= (char-after) ?=)))
2525 (eq (char-after) ?=)))
2526 ;; The most semantically accurate symbol here is
2527 ;; brace-list-open, but we report it simply as a statement-cont.
2528 ;; The reason is that one normally adjusts brace-list-open for
2529 ;; brace lists as top-level constructs, and brace lists inside
2530 ;; statements is a completely different context.
2531 (c-beginning-of-statement-1 containing-sexp)
2532 (c-add-stmt-syntax 'statement-cont nil containing-sexp paren-state))
2533 ;; CASE B.3: The body of a function declared inside a normal
2534 ;; block. Can occur e.g. in Pike and when using gcc
2535 ;; extensions. Might also trigger it with some macros followed
2536 ;; by blocks, and this gives sane indentation then too.
2537 ;; C.f. cases 16F and 17G.
2538 ((progn
2539 (goto-char indent-point)
2540 (and (not (c-looking-at-bos))
2541 (eq (c-beginning-of-statement-1 containing-sexp nil nil t)
2542 'same)))
2543 (c-add-stmt-syntax 'defun-open t containing-sexp paren-state))
2544 ;; CASE B.4: Continued statement with block open.
2546 (goto-char beg-of-same-or-containing-stmt)
2547 (c-add-stmt-syntax 'statement-cont nil containing-sexp paren-state)
2548 (c-add-syntax 'block-open))
2550 ;; CASE C: iostream insertion or extraction operator
2551 ((and (looking-at "<<\\|>>")
2552 (save-excursion
2553 (goto-char beg-of-same-or-containing-stmt)
2554 (while (and (re-search-forward "<<\\|>>" indent-point 'move)
2555 (c-in-literal beg-of-same-or-containing-stmt)))
2556 ;; if we ended up at indent-point, then the first streamop is on a
2557 ;; separate line. Indent the line like a statement-cont instead
2558 (when (/= (point) indent-point)
2559 (c-add-syntax 'stream-op (c-point 'boi))
2560 t))))
2561 ;; CASE D: continued statement.
2563 (c-beginning-of-statement-1 containing-sexp)
2564 (c-add-stmt-syntax 'statement-cont nil containing-sexp paren-state))
2567 (defun c-guess-basic-syntax ()
2568 "Return the syntactic context of the current line."
2569 (save-excursion
2570 (save-restriction
2571 (beginning-of-line)
2572 (let* ((indent-point (point))
2573 (case-fold-search nil)
2574 (paren-state (c-parse-state))
2575 literal containing-sexp char-before-ip char-after-ip lim
2576 syntax placeholder c-in-literal-cache step-type
2577 tmpsymbol keyword injava-inher special-brace-list
2578 ;; narrow out any enclosing class or extern "C" block
2579 (inclass-p (c-narrow-out-enclosing-class paren-state
2580 indent-point))
2581 ;; c-state-cache is shadowed here. That means we must
2582 ;; not do any changes during the execution of this
2583 ;; function, since c-check-state-cache then would change
2584 ;; this local variable and leave a bogus value in the
2585 ;; global one.
2586 (c-state-cache (if inclass-p
2587 (c-whack-state-before (point-min) paren-state)
2588 paren-state))
2589 (c-state-cache-start (point-min))
2590 inenclosing-p macro-start in-macro-expr
2591 ;; There's always at most one syntactic element which got
2592 ;; a relpos. It's stored in syntactic-relpos.
2593 syntactic-relpos
2594 (c-stmt-delim-chars c-stmt-delim-chars))
2595 ;; check for meta top-level enclosing constructs, possible
2596 ;; extern language definitions, possibly (in C++) namespace
2597 ;; definitions.
2598 (save-excursion
2599 (save-restriction
2600 (widen)
2601 (if (and inclass-p
2602 (progn
2603 (goto-char (aref inclass-p 0))
2604 (looking-at c-other-decl-block-key)))
2605 (let ((enclosing (match-string 1)))
2606 (cond
2607 ((string-equal enclosing "extern")
2608 (setq inenclosing-p 'extern))
2609 ((string-equal enclosing "namespace")
2610 (setq inenclosing-p 'namespace))
2611 )))))
2613 ;; Init some position variables:
2615 ;; containing-sexp is the open paren of the closest
2616 ;; surrounding sexp or nil if there is none that hasn't been
2617 ;; narrowed out.
2619 ;; lim is the position after the closest preceding brace sexp
2620 ;; (nested sexps are ignored), or the position after
2621 ;; containing-sexp if there is none, or (point-min) if
2622 ;; containing-sexp is nil.
2624 ;; c-state-cache is the state from c-parse-state at
2625 ;; indent-point, without any parens outside the region
2626 ;; narrowed by c-narrow-out-enclosing-class.
2628 ;; paren-state is the state from c-parse-state outside
2629 ;; containing-sexp, or at indent-point if containing-sexp is
2630 ;; nil. paren-state is not limited to the narrowed region, as
2631 ;; opposed to c-state-cache.
2632 (if c-state-cache
2633 (progn
2634 (setq containing-sexp (car paren-state)
2635 paren-state (cdr paren-state))
2636 (if (consp containing-sexp)
2637 (progn
2638 (setq lim (cdr containing-sexp))
2639 (if (cdr c-state-cache)
2640 ;; Ignore balanced paren. The next entry
2641 ;; can't be another one.
2642 (setq containing-sexp (car (cdr c-state-cache))
2643 paren-state (cdr paren-state))
2644 ;; If there is no surrounding open paren then
2645 ;; put the last balanced pair back on paren-state.
2646 (setq paren-state (cons containing-sexp paren-state)
2647 containing-sexp nil)))
2648 (setq lim (1+ containing-sexp))))
2649 (setq lim (point-min)))
2651 ;; If we're in a parenthesis list then ',' delimits the
2652 ;; "statements" rather than being an operator (with the
2653 ;; exception of the "for" clause). This difference is
2654 ;; typically only noticeable when statements are used in macro
2655 ;; arglists.
2656 (when (and containing-sexp
2657 (eq (char-after containing-sexp) ?\())
2658 (setq c-stmt-delim-chars c-stmt-delim-chars-with-comma))
2660 ;; cache char before and after indent point, and move point to
2661 ;; the most likely position to perform the majority of tests
2662 (goto-char indent-point)
2663 (c-backward-syntactic-ws lim)
2664 (setq char-before-ip (char-before))
2665 (goto-char indent-point)
2666 (skip-chars-forward " \t")
2667 (setq char-after-ip (char-after))
2669 ;; are we in a literal?
2670 (setq literal (c-in-literal lim))
2672 ;; now figure out syntactic qualities of the current line
2673 (cond
2674 ;; CASE 1: in a string.
2675 ((eq literal 'string)
2676 (c-add-syntax 'string (c-point 'bopl)))
2677 ;; CASE 2: in a C or C++ style comment.
2678 ((memq literal '(c c++))
2679 (c-add-syntax literal (car (c-literal-limits lim))))
2680 ;; CASE 3: in a cpp preprocessor macro continuation.
2681 ((and (save-excursion
2682 (when (c-beginning-of-macro)
2683 (setq macro-start (point))))
2684 (/= macro-start (c-point 'boi))
2685 (progn
2686 (setq tmpsymbol 'cpp-macro-cont)
2687 (or (not c-syntactic-indentation-in-macros)
2688 (save-excursion
2689 (goto-char macro-start)
2690 ;; If at the beginning of the body of a #define
2691 ;; directive then analyze as cpp-define-intro
2692 ;; only. Go on with the syntactic analysis
2693 ;; otherwise. in-macro-expr is set if we're in a
2694 ;; cpp expression, i.e. before the #define body
2695 ;; or anywhere in a non-#define directive.
2696 (if (c-forward-to-cpp-define-body)
2697 (let ((indent-boi (c-point 'boi indent-point)))
2698 (setq in-macro-expr (> (point) indent-boi)
2699 tmpsymbol 'cpp-define-intro)
2700 (= (point) indent-boi))
2701 (setq in-macro-expr t)
2702 nil)))))
2703 (c-add-syntax tmpsymbol macro-start)
2704 (setq macro-start nil))
2705 ;; CASE 11: an else clause?
2706 ((looking-at "else\\>[^_]")
2707 (c-beginning-of-statement-1 containing-sexp)
2708 (c-add-stmt-syntax 'else-clause t containing-sexp paren-state))
2709 ;; CASE 12: while closure of a do/while construct?
2710 ((and (looking-at "while\\>[^_]")
2711 (save-excursion
2712 (prog1 (eq (c-beginning-of-statement-1 containing-sexp)
2713 'beginning)
2714 (setq placeholder (point)))))
2715 (goto-char placeholder)
2716 (c-add-stmt-syntax 'do-while-closure t containing-sexp paren-state))
2717 ;; CASE 13: A catch or finally clause? This case is simpler
2718 ;; than if-else and do-while, because a block is required
2719 ;; after every try, catch and finally.
2720 ((save-excursion
2721 (and (cond ((c-major-mode-is 'c++-mode)
2722 (looking-at "catch\\>[^_]"))
2723 ((c-major-mode-is 'java-mode)
2724 (looking-at "\\(catch\\|finally\\)\\>[^_]")))
2725 (and (c-safe (c-backward-syntactic-ws)
2726 (c-backward-sexp)
2728 (eq (char-after) ?{)
2729 (c-safe (c-backward-syntactic-ws)
2730 (c-backward-sexp)
2732 (if (eq (char-after) ?\()
2733 (c-safe (c-backward-sexp) t)
2735 (looking-at "\\(try\\|catch\\)\\>[^_]")
2736 (setq placeholder (point))))
2737 (goto-char placeholder)
2738 (c-add-stmt-syntax 'catch-clause t containing-sexp paren-state))
2739 ;; CASE 18: A substatement we can recognize by keyword.
2740 ((save-excursion
2741 (and c-opt-block-stmt-key
2742 (not (eq char-before-ip ?\;))
2743 (not (memq char-after-ip '(?\) ?\] ?,)))
2744 (or (not (eq char-before-ip ?}))
2745 (c-looking-at-inexpr-block-backward c-state-cache))
2746 (> (point)
2747 (progn
2748 ;; Ought to cache the result from the
2749 ;; c-beginning-of-statement-1 calls here.
2750 (setq placeholder (point))
2751 (while (eq (setq step-type
2752 (c-beginning-of-statement-1 lim))
2753 'label))
2754 (if (eq step-type 'previous)
2755 (goto-char placeholder)
2756 (setq placeholder (point))
2757 (if (and (eq step-type 'same)
2758 (not (looking-at c-opt-block-stmt-key)))
2759 ;; Step up to the containing statement if we
2760 ;; stayed in the same one.
2761 (let (step)
2762 (while (eq
2763 (setq step
2764 (c-beginning-of-statement-1 lim))
2765 'label))
2766 (if (eq step 'up)
2767 (setq placeholder (point))
2768 ;; There was no containing statement afterall.
2769 (goto-char placeholder)))))
2770 placeholder))
2771 (if (looking-at c-block-stmt-2-key)
2772 ;; Require a parenthesis after these keywords.
2773 ;; Necessary to catch e.g. synchronized in Java,
2774 ;; which can be used both as statement and
2775 ;; modifier.
2776 (and (= (c-forward-token-1 1 nil) 0)
2777 (eq (char-after) ?\())
2778 (looking-at c-opt-block-stmt-key))))
2779 (if (eq step-type 'up)
2780 ;; CASE 18A: Simple substatement.
2781 (progn
2782 (goto-char placeholder)
2783 (cond
2784 ((eq char-after-ip ?{)
2785 (c-add-stmt-syntax 'substatement-open nil
2786 containing-sexp paren-state))
2787 ((save-excursion
2788 (goto-char indent-point)
2789 (back-to-indentation)
2790 (looking-at c-label-key))
2791 (c-add-stmt-syntax 'substatement-label nil
2792 containing-sexp paren-state))
2794 (c-add-stmt-syntax 'substatement nil
2795 containing-sexp paren-state))))
2796 ;; CASE 18B: Some other substatement. This is shared
2797 ;; with case 10.
2798 (c-guess-continued-construct indent-point
2799 char-after-ip
2800 placeholder
2802 paren-state)))
2803 ;; CASE 4: In-expression statement. C.f. cases 7B, 16A and
2804 ;; 17E.
2805 ((and (or c-opt-inexpr-class-key
2806 c-opt-inexpr-block-key
2807 c-opt-lambda-key)
2808 (setq placeholder (c-looking-at-inexpr-block
2809 (c-safe-position containing-sexp paren-state)
2810 containing-sexp)))
2811 (setq tmpsymbol (assq (car placeholder)
2812 '((inexpr-class . class-open)
2813 (inexpr-statement . block-open))))
2814 (if tmpsymbol
2815 ;; It's a statement block or an anonymous class.
2816 (setq tmpsymbol (cdr tmpsymbol))
2817 ;; It's a Pike lambda. Check whether we are between the
2818 ;; lambda keyword and the argument list or at the defun
2819 ;; opener.
2820 (setq tmpsymbol (if (eq char-after-ip ?{)
2821 'inline-open
2822 'lambda-intro-cont)))
2823 (goto-char (cdr placeholder))
2824 (back-to-indentation)
2825 (c-add-stmt-syntax tmpsymbol t
2826 (c-most-enclosing-brace c-state-cache (point))
2827 (c-whack-state-after (point) paren-state))
2828 (unless (eq (point) (cdr placeholder))
2829 (c-add-syntax (car placeholder))))
2830 ;; CASE 5: Line is at top level.
2831 ((null containing-sexp)
2832 (cond
2833 ;; CASE 5A: we are looking at a defun, brace list, class,
2834 ;; or inline-inclass method opening brace
2835 ((setq special-brace-list
2836 (or (and c-special-brace-lists
2837 (c-looking-at-special-brace-list))
2838 (eq char-after-ip ?{)))
2839 (cond
2840 ;; CASE 5A.1: extern language or namespace construct
2841 ((save-excursion
2842 (goto-char indent-point)
2843 (skip-chars-forward " \t")
2844 (and (c-safe (progn (c-backward-sexp 2) t))
2845 (looking-at c-other-decl-block-key)
2846 (setq keyword (match-string 1)
2847 placeholder (point))
2848 (or (and (string-equal keyword "namespace")
2849 (setq tmpsymbol 'namespace-open))
2850 (and (string-equal keyword "extern")
2851 (progn
2852 (c-forward-sexp 1)
2853 (c-forward-syntactic-ws)
2854 (eq (char-after) ?\"))
2855 (setq tmpsymbol 'extern-lang-open)))
2857 (goto-char placeholder)
2858 (c-add-syntax tmpsymbol (c-point 'boi)))
2859 ;; CASE 5A.2: we are looking at a class opening brace
2860 ((save-excursion
2861 (goto-char indent-point)
2862 (skip-chars-forward " \t{")
2863 (let ((decl (c-search-uplist-for-classkey (c-parse-state))))
2864 (and decl
2865 (setq placeholder (aref decl 0)))
2867 (c-add-syntax 'class-open placeholder))
2868 ;; CASE 5A.3: brace list open
2869 ((save-excursion
2870 (c-beginning-of-statement-1 lim t)
2871 (if (looking-at "typedef\\>[^_]")
2872 (progn (c-forward-sexp 1)
2873 (c-forward-syntactic-ws indent-point)))
2874 (setq placeholder (c-point 'boi))
2875 (or (consp special-brace-list)
2876 (and (or (save-excursion
2877 (goto-char indent-point)
2878 (setq tmpsymbol nil)
2879 (while (and (> (point) placeholder)
2880 (= (c-backward-token-1 1 t) 0)
2881 (/= (char-after) ?=))
2882 (if (and (not tmpsymbol)
2883 (looking-at "new\\>[^_]"))
2884 (setq tmpsymbol 'topmost-intro-cont)))
2885 (eq (char-after) ?=))
2886 (looking-at "enum\\>[^_]"))
2887 (save-excursion
2888 (while (and (< (point) indent-point)
2889 (= (c-forward-token-1 1 t) 0)
2890 (not (memq (char-after) '(?\; ?\()))))
2891 (not (memq (char-after) '(?\; ?\()))
2892 ))))
2893 (if (and (c-major-mode-is 'java-mode)
2894 (eq tmpsymbol 'topmost-intro-cont))
2895 ;; We're in Java and have found that the open brace
2896 ;; belongs to a "new Foo[]" initialization list,
2897 ;; which means the brace list is part of an
2898 ;; expression and not a top level definition. We
2899 ;; therefore treat it as any topmost continuation
2900 ;; even though the semantically correct symbol still
2901 ;; is brace-list-open, on the same grounds as in
2902 ;; case 10B.2.
2903 (progn
2904 (c-beginning-of-statement-1 lim)
2905 (c-add-syntax 'topmost-intro-cont (c-point 'boi)))
2906 (c-add-syntax 'brace-list-open placeholder)))
2907 ;; CASE 5A.4: inline defun open
2908 ((and inclass-p (not inenclosing-p))
2909 (c-add-syntax 'inline-open)
2910 (c-add-class-syntax 'inclass inclass-p paren-state))
2911 ;; CASE 5A.5: ordinary defun open
2913 (goto-char placeholder)
2914 (if (or inclass-p macro-start)
2915 (c-add-syntax 'defun-open (c-point 'boi))
2916 ;; Bogus to use bol here, but it's the legacy.
2917 (c-add-syntax 'defun-open (c-point 'bol)))
2919 ;; CASE 5B: first K&R arg decl or member init
2920 ((c-just-after-func-arglist-p nil lim)
2921 (cond
2922 ;; CASE 5B.1: a member init
2923 ((or (eq char-before-ip ?:)
2924 (eq char-after-ip ?:))
2925 ;; this line should be indented relative to the beginning
2926 ;; of indentation for the topmost-intro line that contains
2927 ;; the prototype's open paren
2928 ;; TBD: is the following redundant?
2929 (if (eq char-before-ip ?:)
2930 (forward-char -1))
2931 (c-backward-syntactic-ws lim)
2932 ;; TBD: is the preceding redundant?
2933 (if (eq (char-before) ?:)
2934 (progn (forward-char -1)
2935 (c-backward-syntactic-ws lim)))
2936 (if (eq (char-before) ?\))
2937 (c-backward-sexp 1))
2938 (setq placeholder (point))
2939 (save-excursion
2940 (and (c-safe (c-backward-sexp 1) t)
2941 (looking-at "throw[^_]")
2942 (c-safe (c-backward-sexp 1) t)
2943 (setq placeholder (point))))
2944 (goto-char placeholder)
2945 (c-add-syntax 'member-init-intro (c-point 'boi))
2946 ;; we don't need to add any class offset since this
2947 ;; should be relative to the ctor's indentation
2949 ;; CASE 5B.2: K&R arg decl intro
2950 (c-recognize-knr-p
2951 (c-beginning-of-statement-1 lim)
2952 (c-add-syntax 'knr-argdecl-intro (c-point 'boi))
2953 (if inclass-p
2954 (c-add-class-syntax 'inclass inclass-p paren-state)))
2955 ;; CASE 5B.3: Inside a member init list.
2956 ((c-beginning-of-member-init-list lim)
2957 (c-forward-syntactic-ws)
2958 (c-add-syntax 'member-init-cont (point)))
2959 ;; CASE 5B.4: Nether region after a C++ or Java func
2960 ;; decl, which could include a `throws' declaration.
2962 (c-beginning-of-statement-1 lim)
2963 (c-add-syntax 'func-decl-cont (c-point 'boi))
2965 ;; CASE 5C: inheritance line. could be first inheritance
2966 ;; line, or continuation of a multiple inheritance
2967 ((or (and (c-major-mode-is 'c++-mode)
2968 (progn
2969 (when (eq char-after-ip ?,)
2970 (skip-chars-forward " \t")
2971 (forward-char))
2972 (looking-at c-opt-decl-spec-key)))
2973 (and (or (eq char-before-ip ?:)
2974 ;; watch out for scope operator
2975 (save-excursion
2976 (and (eq char-after-ip ?:)
2977 (c-safe (progn (forward-char 1) t))
2978 (not (eq (char-after) ?:))
2980 (save-excursion
2981 (c-backward-syntactic-ws lim)
2982 (if (eq char-before-ip ?:)
2983 (progn
2984 (forward-char -1)
2985 (c-backward-syntactic-ws lim)))
2986 (back-to-indentation)
2987 (looking-at c-class-key)))
2988 ;; for Java
2989 (and (c-major-mode-is 'java-mode)
2990 (let ((fence (save-excursion
2991 (c-beginning-of-statement-1 lim)
2992 (point)))
2993 cont done)
2994 (save-excursion
2995 (while (not done)
2996 (cond ((looking-at c-opt-decl-spec-key)
2997 (setq injava-inher (cons cont (point))
2998 done t))
2999 ((or (not (c-safe (c-forward-sexp -1) t))
3000 (<= (point) fence))
3001 (setq done t))
3003 (setq cont t)))
3004 injava-inher)
3005 (not (c-crosses-statement-barrier-p (cdr injava-inher)
3006 (point)))
3008 (cond
3009 ;; CASE 5C.1: non-hanging colon on an inher intro
3010 ((eq char-after-ip ?:)
3011 (c-beginning-of-statement-1 lim)
3012 (c-add-syntax 'inher-intro (c-point 'boi))
3013 ;; don't add inclass symbol since relative point already
3014 ;; contains any class offset
3016 ;; CASE 5C.2: hanging colon on an inher intro
3017 ((eq char-before-ip ?:)
3018 (c-beginning-of-statement-1 lim)
3019 (c-add-syntax 'inher-intro (c-point 'boi))
3020 (if inclass-p
3021 (c-add-class-syntax 'inclass inclass-p paren-state)))
3022 ;; CASE 5C.3: in a Java implements/extends
3023 (injava-inher
3024 (let ((where (cdr injava-inher))
3025 (cont (car injava-inher)))
3026 (goto-char where)
3027 (cond ((looking-at "throws\\>[^_]")
3028 (c-add-syntax 'func-decl-cont
3029 (progn (c-beginning-of-statement-1 lim)
3030 (c-point 'boi))))
3031 (cont (c-add-syntax 'inher-cont where))
3032 (t (c-add-syntax 'inher-intro
3033 (progn (goto-char (cdr injava-inher))
3034 (c-beginning-of-statement-1 lim)
3035 (point))))
3037 ;; CASE 5C.4: a continued inheritance line
3039 (c-beginning-of-inheritance-list lim)
3040 (c-add-syntax 'inher-cont (point))
3041 ;; don't add inclass symbol since relative point already
3042 ;; contains any class offset
3044 ;; CASE 5D: this could be a top-level initialization, a
3045 ;; member init list continuation, or a template argument
3046 ;; list continuation.
3047 ((c-with-syntax-table (if (c-major-mode-is 'c++-mode)
3048 c++-template-syntax-table
3049 (syntax-table))
3050 (save-excursion
3051 ;; Note: We use the fact that lim is always after any
3052 ;; preceding brace sexp.
3053 (while (and (= (c-backward-token-1 1 t lim) 0)
3054 (not (looking-at "[;<,=]"))))
3055 (or (memq (char-after) '(?, ?=))
3056 (and (c-major-mode-is 'c++-mode)
3057 (= (c-backward-token-1 1 nil lim) 0)
3058 (eq (char-after) ?<)))))
3059 (goto-char indent-point)
3060 (c-beginning-of-member-init-list lim)
3061 (cond
3062 ;; CASE 5D.1: hanging member init colon, but watch out
3063 ;; for bogus matches on access specifiers inside classes.
3064 ((and (save-excursion
3065 (setq placeholder (point))
3066 (c-backward-token-1 1 t lim)
3067 (and (eq (char-after) ?:)
3068 (not (eq (char-before) ?:))))
3069 (save-excursion
3070 (goto-char placeholder)
3071 (back-to-indentation)
3073 (/= (car (save-excursion
3074 (parse-partial-sexp (point) placeholder)))
3076 (and
3077 (if c-opt-access-key
3078 (not (looking-at c-opt-access-key)) t)
3079 (not (looking-at c-class-key))
3080 (if c-opt-bitfield-key
3081 (not (looking-at c-opt-bitfield-key)) t))
3083 (goto-char placeholder)
3084 (c-forward-syntactic-ws)
3085 (c-add-syntax 'member-init-cont (point))
3086 ;; we do not need to add class offset since relative
3087 ;; point is the member init above us
3089 ;; CASE 5D.2: non-hanging member init colon
3090 ((progn
3091 (c-forward-syntactic-ws indent-point)
3092 (eq (char-after) ?:))
3093 (skip-chars-forward " \t:")
3094 (c-add-syntax 'member-init-cont (point)))
3095 ;; CASE 5D.3: perhaps a template list continuation?
3096 ((and (c-major-mode-is 'c++-mode)
3097 (save-excursion
3098 (save-restriction
3099 (c-with-syntax-table c++-template-syntax-table
3100 (goto-char indent-point)
3101 (setq placeholder (c-up-list-backward (point)))
3102 (and placeholder
3103 (eq (char-after placeholder) ?<))))))
3104 ;; we can probably indent it just like an arglist-cont
3105 (goto-char placeholder)
3106 (c-beginning-of-statement-1 lim t)
3107 (c-add-syntax 'template-args-cont (c-point 'boi)))
3108 ;; CASE 5D.4: perhaps a multiple inheritance line?
3109 ((and (c-major-mode-is 'c++-mode)
3110 (save-excursion
3111 (c-beginning-of-statement-1 lim)
3112 (setq placeholder (point))
3113 (if (looking-at "static\\>[^_]")
3114 (c-forward-token-1 1 nil indent-point))
3115 (and (looking-at c-class-key)
3116 (= (c-forward-token-1 2 nil indent-point) 0)
3117 (if (eq (char-after) ?<)
3118 (c-with-syntax-table c++-template-syntax-table
3119 (= (c-forward-token-1 1 t indent-point) 0))
3121 (eq (char-after) ?:))))
3122 (goto-char placeholder)
3123 (c-add-syntax 'inher-cont (c-point 'boi)))
3124 ;; CASE 5D.5: Continuation of the "expression part" of a
3125 ;; top level construct.
3127 (while (and (eq (car (c-beginning-of-decl-1 containing-sexp))
3128 'same)
3129 (save-excursion
3130 (c-backward-syntactic-ws)
3131 (eq (char-before) ?}))))
3132 (c-add-stmt-syntax
3133 (if (eq char-before-ip ?,)
3134 ;; A preceding comma at the top level means that a
3135 ;; new variable declaration starts here. Use
3136 ;; topmost-intro-cont for it, for consistency with
3137 ;; the first variable declaration. C.f. case 5N.
3138 'topmost-intro-cont
3139 'statement-cont)
3140 nil containing-sexp paren-state))
3142 ;; CASE 5E: we are looking at a access specifier
3143 ((and inclass-p
3144 c-opt-access-key
3145 (looking-at c-opt-access-key))
3146 (setq placeholder (c-add-class-syntax 'inclass inclass-p
3147 paren-state))
3148 ;; Append access-label with the same anchor point as inclass gets.
3149 (nconc syntax (list (cons 'access-label placeholder))))
3150 ;; CASE 5F: extern-lang-close or namespace-close?
3151 ((and inenclosing-p
3152 (eq char-after-ip ?}))
3153 (setq tmpsymbol (if (eq inenclosing-p 'extern)
3154 'extern-lang-close
3155 'namespace-close))
3156 (c-add-syntax tmpsymbol (aref inclass-p 0)))
3157 ;; CASE 5G: we are looking at the brace which closes the
3158 ;; enclosing nested class decl
3159 ((and inclass-p
3160 (eq char-after-ip ?})
3161 (save-excursion
3162 (save-restriction
3163 (widen)
3164 (forward-char 1)
3165 (and (c-safe (progn (c-backward-sexp 1) t))
3166 (= (point) (aref inclass-p 1))
3167 ))))
3168 (c-add-class-syntax 'class-close inclass-p paren-state))
3169 ;; CASE 5H: we could be looking at subsequent knr-argdecls
3170 ((and c-recognize-knr-p
3171 (not (eq char-before-ip ?}))
3172 (save-excursion
3173 (setq placeholder (cdr (c-beginning-of-decl-1 lim)))
3174 (and placeholder
3175 ;; Do an extra check to avoid tripping up on
3176 ;; statements that occur in invalid contexts
3177 ;; (e.g. in macro bodies where we don't really
3178 ;; know the context of what we're looking at).
3179 (not (and c-opt-block-stmt-key
3180 (looking-at c-opt-block-stmt-key)))))
3181 (< placeholder indent-point))
3182 (goto-char placeholder)
3183 (c-add-syntax 'knr-argdecl (point)))
3184 ;; CASE 5I: ObjC method definition.
3185 ((and c-opt-method-key
3186 (looking-at c-opt-method-key))
3187 (c-beginning-of-statement-1 lim)
3188 (c-add-syntax 'objc-method-intro (c-point 'boi)))
3189 ;; CASE 5N: At a variable declaration that follows a class
3190 ;; definition or some other block declaration that doesn't
3191 ;; end at the closing '}'. C.f. case 5D.5.
3192 ((progn
3193 (c-backward-syntactic-ws lim)
3194 (and (eq (char-before) ?})
3195 (save-excursion
3196 (let ((start (point)))
3197 (if paren-state
3198 ;; Speed up the backward search a bit.
3199 (goto-char (car (car paren-state))))
3200 (c-beginning-of-decl-1 containing-sexp)
3201 (setq placeholder (point))
3202 (if (= start (point))
3203 ;; The '}' is unbalanced.
3205 (c-end-of-decl-1)
3206 (> (point) indent-point))))))
3207 (goto-char placeholder)
3208 (c-add-stmt-syntax 'topmost-intro-cont nil
3209 containing-sexp paren-state))
3210 ;; CASE 5J: we are at the topmost level, make
3211 ;; sure we skip back past any access specifiers
3212 ((progn
3213 (while (and inclass-p
3214 c-opt-access-key
3215 (not (bobp))
3216 (save-excursion
3217 (c-safe (progn (c-backward-sexp 1) t))
3218 (looking-at c-opt-access-key)))
3219 (c-backward-sexp 1)
3220 (c-backward-syntactic-ws lim))
3221 (or (bobp)
3222 (memq (char-before) '(?\; ?}))
3223 (and (c-major-mode-is 'objc-mode)
3224 (progn
3225 (c-beginning-of-statement-1 lim)
3226 (eq (char-after) ?@)))))
3227 ;; real beginning-of-line could be narrowed out due to
3228 ;; enclosure in a class block
3229 (save-restriction
3230 (widen)
3231 (c-add-syntax 'topmost-intro (c-point 'bol))
3232 ;; Using bol instead of boi above is highly bogus, and
3233 ;; it makes our lives hard to remain compatible. :P
3234 (if inclass-p
3235 (progn
3236 (goto-char (aref inclass-p 1))
3237 (or (= (point) (c-point 'boi))
3238 (goto-char (aref inclass-p 0)))
3239 (cond
3240 ((eq inenclosing-p 'extern)
3241 (c-add-syntax 'inextern-lang (c-point 'boi)))
3242 ((eq inenclosing-p 'namespace)
3243 (c-add-syntax 'innamespace (c-point 'boi)))
3244 (t (c-add-class-syntax 'inclass inclass-p paren-state)))
3246 (when (and c-syntactic-indentation-in-macros
3247 macro-start
3248 (/= macro-start (c-point 'boi indent-point)))
3249 (c-add-syntax 'cpp-define-intro)
3250 (setq macro-start nil))
3252 ;; CASE 5K: we are at an ObjC method definition
3253 ;; continuation line.
3254 ((and c-opt-method-key
3255 (progn
3256 (c-beginning-of-statement-1 lim)
3257 (beginning-of-line)
3258 (looking-at c-opt-method-key)))
3259 (c-add-syntax 'objc-method-args-cont (point)))
3260 ;; CASE 5L: we are at the first argument of a template
3261 ;; arglist that begins on the previous line.
3262 ((eq (char-before) ?<)
3263 (c-beginning-of-statement-1 (c-safe-position (point) paren-state))
3264 (c-add-syntax 'template-args-cont (c-point 'boi)))
3265 ;; CASE 5M: we are at a topmost continuation line
3267 (c-beginning-of-statement-1 (c-safe-position (point) paren-state))
3268 (c-add-syntax 'topmost-intro-cont (c-point 'boi)))
3270 ;; (CASE 6 has been removed.)
3271 ;; CASE 7: line is an expression, not a statement. Most
3272 ;; likely we are either in a function prototype or a function
3273 ;; call argument list
3274 ((not (or (and c-special-brace-lists
3275 (save-excursion
3276 (goto-char containing-sexp)
3277 (c-looking-at-special-brace-list)))
3278 (eq (char-after containing-sexp) ?{)))
3279 (cond
3280 ;; CASE 7A: we are looking at the arglist closing paren
3281 ((memq char-after-ip '(?\) ?\]))
3282 (goto-char containing-sexp)
3283 (setq placeholder (c-point 'boi))
3284 (when (and (c-safe (backward-up-list 1) t)
3285 (> (point) placeholder))
3286 (forward-char)
3287 (skip-chars-forward " \t")
3288 (setq placeholder (point)))
3289 (c-add-syntax 'arglist-close placeholder))
3290 ;; CASE 7B: Looking at the opening brace of an
3291 ;; in-expression block or brace list. C.f. cases 4, 16A
3292 ;; and 17E.
3293 ((and (eq char-after-ip ?{)
3294 (progn
3295 (setq placeholder (c-inside-bracelist-p (point)
3296 c-state-cache))
3297 (if placeholder
3298 (setq tmpsymbol '(brace-list-open . inexpr-class))
3299 (setq tmpsymbol '(block-open . inexpr-statement)
3300 placeholder
3301 (cdr-safe (c-looking-at-inexpr-block
3302 (c-safe-position containing-sexp
3303 paren-state)
3304 containing-sexp)))
3305 ;; placeholder is nil if it's a block directly in
3306 ;; a function arglist. That makes us skip out of
3307 ;; this case.
3309 (goto-char placeholder)
3310 (back-to-indentation)
3311 (c-add-stmt-syntax (car tmpsymbol) t
3312 (c-most-enclosing-brace paren-state (point))
3313 (c-whack-state-after (point) paren-state))
3314 (if (/= (point) placeholder)
3315 (c-add-syntax (cdr tmpsymbol))))
3316 ;; CASE 7C: we are looking at the first argument in an empty
3317 ;; argument list. Use arglist-close if we're actually
3318 ;; looking at a close paren or bracket.
3319 ((memq char-before-ip '(?\( ?\[))
3320 (goto-char containing-sexp)
3321 (setq placeholder (c-point 'boi))
3322 (when (and (c-safe (backward-up-list 1) t)
3323 (> (point) placeholder))
3324 (forward-char)
3325 (skip-chars-forward " \t")
3326 (setq placeholder (point)))
3327 (c-add-syntax 'arglist-intro placeholder))
3328 ;; CASE 7D: we are inside a conditional test clause. treat
3329 ;; these things as statements
3330 ((progn
3331 (goto-char containing-sexp)
3332 (and (c-safe (progn (c-forward-sexp -1) t))
3333 (looking-at "\\<for\\>[^_]")))
3334 (goto-char (1+ containing-sexp))
3335 (c-forward-syntactic-ws indent-point)
3336 (if (eq char-before-ip ?\;)
3337 (c-add-syntax 'statement (point))
3338 (c-add-syntax 'statement-cont (point))
3340 ;; CASE 7E: maybe a continued ObjC method call. This is the
3341 ;; case when we are inside a [] bracketed exp, and what
3342 ;; precede the opening bracket is not an identifier.
3343 ((and c-opt-method-key
3344 (eq (char-after containing-sexp) ?\[)
3345 (progn
3346 (goto-char (1- containing-sexp))
3347 (c-backward-syntactic-ws (c-point 'bod))
3348 (if (not (looking-at c-symbol-key))
3349 (c-add-syntax 'objc-method-call-cont containing-sexp))
3351 ;; CASE 7F: we are looking at an arglist continuation line,
3352 ;; but the preceding argument is on the same line as the
3353 ;; opening paren. This case includes multi-line
3354 ;; mathematical paren groupings, but we could be on a
3355 ;; for-list continuation line
3356 ((progn
3357 (goto-char (1+ containing-sexp))
3358 (skip-chars-forward " \t")
3359 (and (not (eolp))
3360 (not (looking-at "\\\\$"))))
3361 (goto-char containing-sexp)
3362 (setq placeholder (c-point 'boi))
3363 (when (and (c-safe (backward-up-list 1) t)
3364 (> (point) placeholder))
3365 (forward-char)
3366 (skip-chars-forward " \t")
3367 (setq placeholder (point)))
3368 (c-add-syntax 'arglist-cont-nonempty placeholder))
3369 ;; CASE 7G: we are looking at just a normal arglist
3370 ;; continuation line
3371 (t (c-forward-syntactic-ws indent-point)
3372 (c-add-syntax 'arglist-cont (c-point 'boi)))
3374 ;; CASE 8: func-local multi-inheritance line
3375 ((and (c-major-mode-is 'c++-mode)
3376 (save-excursion
3377 (goto-char indent-point)
3378 (skip-chars-forward " \t")
3379 (looking-at c-opt-decl-spec-key)))
3380 (goto-char indent-point)
3381 (skip-chars-forward " \t")
3382 (cond
3383 ;; CASE 8A: non-hanging colon on an inher intro
3384 ((eq char-after-ip ?:)
3385 (c-backward-syntactic-ws lim)
3386 (c-add-syntax 'inher-intro (c-point 'boi)))
3387 ;; CASE 8B: hanging colon on an inher intro
3388 ((eq char-before-ip ?:)
3389 (c-add-syntax 'inher-intro (c-point 'boi)))
3390 ;; CASE 8C: a continued inheritance line
3392 (c-beginning-of-inheritance-list lim)
3393 (c-add-syntax 'inher-cont (point))
3395 ;; CASE 9: we are inside a brace-list
3396 ((setq special-brace-list
3397 (or (and c-special-brace-lists
3398 (save-excursion
3399 (goto-char containing-sexp)
3400 (c-looking-at-special-brace-list)))
3401 (c-inside-bracelist-p containing-sexp paren-state)))
3402 (cond
3403 ;; CASE 9A: In the middle of a special brace list opener.
3404 ((and (consp special-brace-list)
3405 (save-excursion
3406 (goto-char containing-sexp)
3407 (eq (char-after) ?\())
3408 (eq char-after-ip (car (cdr special-brace-list))))
3409 (goto-char (car (car special-brace-list)))
3410 (skip-chars-backward " \t")
3411 (if (and (bolp)
3412 (assoc 'statement-cont
3413 (setq placeholder (c-guess-basic-syntax))))
3414 (setq syntax placeholder)
3415 (c-beginning-of-statement-1
3416 (c-safe-position (1- containing-sexp) paren-state))
3417 (c-forward-token-1 0)
3418 (if (looking-at "typedef\\>[^_]") (c-forward-token-1 1))
3419 (c-add-syntax 'brace-list-open (c-point 'boi))))
3420 ;; CASE 9B: brace-list-close brace
3421 ((if (consp special-brace-list)
3422 ;; Check special brace list closer.
3423 (progn
3424 (goto-char (car (car special-brace-list)))
3425 (save-excursion
3426 (goto-char indent-point)
3427 (back-to-indentation)
3429 ;; We were between the special close char and the `)'.
3430 (and (eq (char-after) ?\))
3431 (eq (1+ (point)) (cdr (car special-brace-list))))
3432 ;; We were before the special close char.
3433 (and (eq (char-after) (cdr (cdr special-brace-list)))
3434 (= (c-forward-token-1) 0)
3435 (eq (1+ (point)) (cdr (car special-brace-list)))))))
3436 ;; Normal brace list check.
3437 (and (eq char-after-ip ?})
3438 (c-safe (progn (goto-char (c-up-list-backward (point)))
3440 (= (point) containing-sexp)))
3441 (if (eq (point) (c-point 'boi))
3442 (c-add-syntax 'brace-list-close (point))
3443 (setq lim (c-most-enclosing-brace c-state-cache (point)))
3444 (c-beginning-of-statement-1 lim)
3445 (c-add-stmt-syntax 'brace-list-close t lim
3446 (c-whack-state-after (point) paren-state)
3447 t)))
3449 ;; Prepare for the rest of the cases below by going to the
3450 ;; token following the opening brace
3451 (if (consp special-brace-list)
3452 (progn
3453 (goto-char (car (car special-brace-list)))
3454 (c-forward-token-1 1 nil indent-point))
3455 (goto-char containing-sexp))
3456 (forward-char)
3457 (let ((start (point)))
3458 (c-forward-syntactic-ws indent-point)
3459 (goto-char (max start (c-point 'bol))))
3460 (c-skip-ws-forward indent-point)
3461 (cond
3462 ;; CASE 9C: we're looking at the first line in a brace-list
3463 ((= (point) indent-point)
3464 (if (consp special-brace-list)
3465 (goto-char (car (car special-brace-list)))
3466 (goto-char containing-sexp))
3467 (if (eq (point) (c-point 'boi))
3468 (c-add-syntax 'brace-list-intro (point))
3469 (setq lim (c-most-enclosing-brace c-state-cache (point)))
3470 (c-beginning-of-statement-1 lim)
3471 (c-add-stmt-syntax 'brace-list-intro t lim
3472 (c-whack-state-after (point) paren-state)
3473 t)))
3474 ;; CASE 9D: this is just a later brace-list-entry or
3475 ;; brace-entry-open
3476 (t (if (or (eq char-after-ip ?{)
3477 (and c-special-brace-lists
3478 (save-excursion
3479 (goto-char indent-point)
3480 (c-forward-syntactic-ws (c-point 'eol))
3481 (c-looking-at-special-brace-list (point)))))
3482 (c-add-syntax 'brace-entry-open (point))
3483 (c-add-syntax 'brace-list-entry (point))
3485 ))))
3486 ;; CASE 10: A continued statement or top level construct.
3487 ((and (not (memq char-before-ip '(?\; ?:)))
3488 (or (not (eq char-before-ip ?}))
3489 (c-looking-at-inexpr-block-backward c-state-cache))
3490 (> (point)
3491 (save-excursion
3492 (c-beginning-of-statement-1 containing-sexp)
3493 (setq placeholder (point))))
3494 (/= placeholder containing-sexp))
3495 ;; This is shared with case 18.
3496 (c-guess-continued-construct indent-point
3497 char-after-ip
3498 placeholder
3499 containing-sexp
3500 paren-state))
3501 ;; CASE 14: A case or default label
3502 ((looking-at c-label-kwds-regexp)
3503 (goto-char containing-sexp)
3504 (setq lim (c-most-enclosing-brace c-state-cache containing-sexp))
3505 (c-backward-to-block-anchor lim)
3506 (c-add-stmt-syntax 'case-label t lim paren-state))
3507 ;; CASE 15: any other label
3508 ((looking-at c-label-key)
3509 (goto-char containing-sexp)
3510 (setq lim (c-most-enclosing-brace c-state-cache containing-sexp))
3511 (save-excursion
3512 (setq tmpsymbol
3513 (if (and (eq (c-beginning-of-statement-1 lim) 'up)
3514 (looking-at "switch\\>[^_]"))
3515 ;; If the surrounding statement is a switch then
3516 ;; let's analyze all labels as switch labels, so
3517 ;; that they get lined up consistently.
3518 'case-label
3519 'label)))
3520 (c-backward-to-block-anchor lim)
3521 (c-add-stmt-syntax tmpsymbol t lim paren-state))
3522 ;; CASE 16: block close brace, possibly closing the defun or
3523 ;; the class
3524 ((eq char-after-ip ?})
3525 ;; From here on we have the next containing sexp in lim.
3526 (setq lim (c-most-enclosing-brace paren-state))
3527 (goto-char containing-sexp)
3528 (cond
3529 ;; CASE 16E: Closing a statement block? This catches
3530 ;; cases where it's preceded by a statement keyword,
3531 ;; which works even when used in an "invalid" context,
3532 ;; e.g. a macro argument.
3533 ((c-after-conditional)
3534 (c-backward-to-block-anchor lim)
3535 (c-add-stmt-syntax 'block-close t lim paren-state))
3536 ;; CASE 16A: closing a lambda defun or an in-expression
3537 ;; block? C.f. cases 4, 7B and 17E.
3538 ((setq placeholder (c-looking-at-inexpr-block
3539 (c-safe-position containing-sexp paren-state)
3540 nil))
3541 (setq tmpsymbol (if (eq (car placeholder) 'inlambda)
3542 'inline-close
3543 'block-close))
3544 (goto-char containing-sexp)
3545 (back-to-indentation)
3546 (if (= containing-sexp (point))
3547 (c-add-syntax tmpsymbol (point))
3548 (goto-char (cdr placeholder))
3549 (back-to-indentation)
3550 (c-add-stmt-syntax tmpsymbol t
3551 (c-most-enclosing-brace paren-state (point))
3552 (c-whack-state-after (point) paren-state))
3553 (if (/= (point) (cdr placeholder))
3554 (c-add-syntax (car placeholder)))))
3555 ;; CASE 16B: does this close an inline or a function in
3556 ;; an extern block or namespace?
3557 ((setq placeholder (c-search-uplist-for-classkey paren-state))
3558 (c-backward-to-decl-anchor lim)
3559 (back-to-indentation)
3560 (if (save-excursion
3561 (goto-char (aref placeholder 0))
3562 (looking-at c-other-decl-block-key))
3563 (c-add-syntax 'defun-close (point))
3564 (c-add-syntax 'inline-close (point))))
3565 ;; CASE 16F: Can be a defun-close of a function declared
3566 ;; in a statement block, e.g. in Pike or when using gcc
3567 ;; extensions. Might also trigger it with some macros
3568 ;; followed by blocks, and this gives sane indentation
3569 ;; then too. Let it through to be handled below.
3570 ;; C.f. cases B.3 and 17G.
3571 ((and (not inenclosing-p)
3573 (save-excursion
3574 (and (not (c-looking-at-bos))
3575 (eq (c-beginning-of-statement-1 lim nil nil t) 'same)
3576 (setq placeholder (point)))))
3577 (back-to-indentation)
3578 (if (/= (point) containing-sexp)
3579 (goto-char placeholder))
3580 (c-add-stmt-syntax 'defun-close t lim paren-state))
3581 ;; CASE 16C: if there an enclosing brace that hasn't
3582 ;; been narrowed out by a class, then this is a
3583 ;; block-close. C.f. case 17H.
3584 ((and (not inenclosing-p) lim)
3585 ;; If the block is preceded by a case/switch label on
3586 ;; the same line, we anchor at the first preceding label
3587 ;; at boi. The default handling in c-add-stmt-syntax is
3588 ;; really fixes it better, but we do like this to keep
3589 ;; the indentation compatible with version 5.28 and
3590 ;; earlier.
3591 (while (and (/= (setq placeholder (point)) (c-point 'boi))
3592 (eq (c-beginning-of-statement-1 lim) 'label)))
3593 (goto-char placeholder)
3594 (if (looking-at c-label-kwds-regexp)
3595 (c-add-syntax 'block-close (point))
3596 (goto-char containing-sexp)
3597 ;; c-backward-to-block-anchor not necessary here; those
3598 ;; situations are handled in case 16E above.
3599 (c-add-stmt-syntax 'block-close t lim paren-state)))
3600 ;; CASE 16D: find out whether we're closing a top-level
3601 ;; class or a defun
3603 (save-restriction
3604 (narrow-to-region (point-min) indent-point)
3605 (let ((decl (c-search-uplist-for-classkey (c-parse-state))))
3606 (if decl
3607 (c-add-class-syntax 'class-close decl paren-state)
3608 (goto-char containing-sexp)
3609 (c-backward-to-decl-anchor lim)
3610 (back-to-indentation)
3611 (c-add-syntax 'defun-close (point)))))
3613 ;; CASE 17: Statement or defun catchall.
3615 (goto-char indent-point)
3616 ;; Back up statements until we find one that starts at boi.
3617 (while (let* ((prev-point (point))
3618 (last-step-type (c-beginning-of-statement-1
3619 containing-sexp)))
3620 (if (= (point) prev-point)
3621 (progn
3622 (setq step-type (or step-type last-step-type))
3623 nil)
3624 (setq step-type last-step-type)
3625 (/= (point) (c-point 'boi)))))
3626 (cond
3627 ;; CASE 17B: continued statement
3628 ((and (eq step-type 'same)
3629 (/= (point) indent-point))
3630 (c-add-stmt-syntax 'statement-cont nil
3631 containing-sexp paren-state))
3632 ;; CASE 17A: After a case/default label?
3633 ((progn
3634 (while (and (eq step-type 'label)
3635 (not (looking-at c-label-kwds-regexp)))
3636 (setq step-type
3637 (c-beginning-of-statement-1 containing-sexp)))
3638 (eq step-type 'label))
3639 (c-add-stmt-syntax (if (eq char-after-ip ?{)
3640 'statement-case-open
3641 'statement-case-intro)
3642 t containing-sexp paren-state))
3643 ;; CASE 17D: any old statement
3644 ((progn
3645 (while (eq step-type 'label)
3646 (setq step-type
3647 (c-beginning-of-statement-1 containing-sexp)))
3648 (eq step-type 'previous))
3649 (c-add-stmt-syntax 'statement t containing-sexp paren-state)
3650 (if (eq char-after-ip ?{)
3651 (c-add-syntax 'block-open)))
3652 ;; CASE 17I: Inside a substatement block.
3653 ((progn
3654 ;; The following tests are all based on containing-sexp.
3655 (goto-char containing-sexp)
3656 ;; From here on we have the next containing sexp in lim.
3657 (setq lim (c-most-enclosing-brace paren-state containing-sexp))
3658 (c-after-conditional))
3659 (c-backward-to-block-anchor lim)
3660 (c-add-stmt-syntax 'statement-block-intro t lim paren-state)
3661 (if (eq char-after-ip ?{)
3662 (c-add-syntax 'block-open)))
3663 ;; CASE 17E: first statement in an in-expression block.
3664 ;; C.f. cases 4, 7B and 16A.
3665 ((setq placeholder (c-looking-at-inexpr-block
3666 (c-safe-position containing-sexp paren-state)
3667 nil))
3668 (setq tmpsymbol (if (eq (car placeholder) 'inlambda)
3669 'defun-block-intro
3670 'statement-block-intro))
3671 (back-to-indentation)
3672 (if (= containing-sexp (point))
3673 (c-add-syntax tmpsymbol (point))
3674 (goto-char (cdr placeholder))
3675 (back-to-indentation)
3676 (c-add-stmt-syntax tmpsymbol t
3677 (c-most-enclosing-brace c-state-cache (point))
3678 (c-whack-state-after (point) paren-state))
3679 (if (/= (point) (cdr placeholder))
3680 (c-add-syntax (car placeholder))))
3681 (if (eq char-after-ip ?{)
3682 (c-add-syntax 'block-open)))
3683 ;; CASE 17F: first statement in an inline, or first
3684 ;; statement in a top-level defun. we can tell this is it
3685 ;; if there are no enclosing braces that haven't been
3686 ;; narrowed out by a class (i.e. don't use bod here).
3687 ;; However, we first check for statements that we can
3688 ;; recognize by keywords. That increases the robustness in
3689 ;; cases where statements are used on the top level,
3690 ;; e.g. in macro definitions.
3691 ((save-excursion
3692 (save-restriction
3693 (widen)
3694 (c-narrow-out-enclosing-class paren-state containing-sexp)
3695 (not (c-most-enclosing-brace paren-state))))
3696 (c-backward-to-decl-anchor lim)
3697 (back-to-indentation)
3698 (c-add-syntax 'defun-block-intro (point)))
3699 ;; CASE 17G: First statement in a function declared inside
3700 ;; a normal block. This can occur in Pike and with
3701 ;; e.g. the gcc extensions. Might also trigger it with
3702 ;; some macros followed by blocks, and this gives sane
3703 ;; indentation then too. C.f. cases B.3 and 16F.
3704 ((save-excursion
3705 (and (not (c-looking-at-bos))
3706 (eq (c-beginning-of-statement-1 lim nil nil t) 'same)
3707 (setq placeholder (point))))
3708 (back-to-indentation)
3709 (if (/= (point) containing-sexp)
3710 (goto-char placeholder))
3711 (c-add-stmt-syntax 'defun-block-intro t lim paren-state))
3712 ;; CASE 17H: First statement in a block. C.f. case 16C.
3714 ;; If the block is preceded by a case/switch label on the
3715 ;; same line, we anchor at the first preceding label at
3716 ;; boi. The default handling in c-add-stmt-syntax is
3717 ;; really fixes it better, but we do like this to keep the
3718 ;; indentation compatible with version 5.28 and earlier.
3719 (while (and (/= (setq placeholder (point)) (c-point 'boi))
3720 (eq (c-beginning-of-statement-1 lim) 'label)))
3721 (goto-char placeholder)
3722 (if (looking-at c-label-kwds-regexp)
3723 (c-add-syntax 'statement-block-intro (point))
3724 (goto-char containing-sexp)
3725 ;; c-backward-to-block-anchor not necessary here; those
3726 ;; situations are handled in case 17I above.
3727 (c-add-stmt-syntax 'statement-block-intro t lim paren-state))
3728 (if (eq char-after-ip ?{)
3729 (c-add-syntax 'block-open)))
3732 ;; now we need to look at any modifiers
3733 (goto-char indent-point)
3734 (skip-chars-forward " \t")
3735 ;; are we looking at a comment only line?
3736 (when (and (looking-at c-comment-start-regexp)
3737 (/= (c-forward-token-1 0 nil (c-point 'eol)) 0))
3738 (c-add-syntax 'comment-intro))
3739 ;; we might want to give additional offset to friends (in C++).
3740 (when (and c-opt-friend-key
3741 (looking-at c-opt-friend-key))
3742 (c-add-syntax 'friend))
3743 ;; Start of or a continuation of a preprocessor directive?
3744 (if (and macro-start
3745 (eq macro-start (c-point 'boi))
3746 (not (and (c-major-mode-is 'pike-mode)
3747 (eq (char-after (1+ macro-start)) ?\"))))
3748 (c-add-syntax 'cpp-macro)
3749 (when (and c-syntactic-indentation-in-macros macro-start)
3750 (if in-macro-expr
3751 (when (or (< syntactic-relpos macro-start)
3752 (not (or (assq 'arglist-intro syntax)
3753 (assq 'arglist-cont syntax)
3754 (assq 'arglist-cont-nonempty syntax)
3755 (assq 'arglist-close syntax))))
3756 ;; If inside a cpp expression, i.e. anywhere in a
3757 ;; cpp directive except a #define body, we only let
3758 ;; through the syntactic analysis that is internal
3759 ;; in the expression. That means the arglist
3760 ;; elements, if they are anchored inside the cpp
3761 ;; expression.
3762 (setq syntax `((cpp-macro-cont . ,macro-start))))
3763 (when (and (eq macro-start syntactic-relpos)
3764 (not (assq 'cpp-define-intro syntax))
3765 (save-excursion
3766 (goto-char macro-start)
3767 (or (not (c-forward-to-cpp-define-body))
3768 (<= (point) (c-point 'boi indent-point)))))
3769 ;; Inside a #define body and the syntactic analysis is
3770 ;; anchored on the start of the #define. In this case
3771 ;; we add cpp-define-intro to get the extra
3772 ;; indentation of the #define body.
3773 (c-add-syntax 'cpp-define-intro)))))
3774 ;; return the syntax
3775 syntax))))
3778 (defun c-echo-parsing-error (&optional quiet)
3779 (when (and c-report-syntactic-errors c-parsing-error (not quiet))
3780 (c-benign-error "%s" c-parsing-error))
3781 c-parsing-error)
3783 (defun c-evaluate-offset (offset langelem symbol)
3784 ;; offset can be a number, a function, a variable, a list, or one of
3785 ;; the symbols + or -
3786 (cond
3787 ((eq offset '+) c-basic-offset)
3788 ((eq offset '-) (- c-basic-offset))
3789 ((eq offset '++) (* 2 c-basic-offset))
3790 ((eq offset '--) (* 2 (- c-basic-offset)))
3791 ((eq offset '*) (/ c-basic-offset 2))
3792 ((eq offset '/) (/ (- c-basic-offset) 2))
3793 ((numberp offset) offset)
3794 ((functionp offset) (c-evaluate-offset
3795 (funcall offset langelem) langelem symbol))
3796 ((vectorp offset) offset)
3797 ((null offset) nil)
3798 ((listp offset)
3799 (let (done)
3800 (while (and (not done) offset)
3801 (setq done (c-evaluate-offset (car offset) langelem symbol)
3802 offset (cdr offset)))
3803 (if (and c-strict-syntax-p (not done))
3804 (c-benign-error "No offset found for syntactic symbol %s" symbol))
3805 done))
3806 (t (symbol-value offset))
3809 (defun c-get-offset (langelem)
3810 "Get offset from LANGELEM which is a cons cell of the form:
3811 \(SYMBOL . RELPOS). The symbol is matched against `c-offsets-alist'
3812 and the offset found there is returned."
3813 (let* ((symbol (car langelem))
3814 (match (assq symbol c-offsets-alist))
3815 (offset (cdr-safe match)))
3816 (if match
3817 (setq offset (c-evaluate-offset offset langelem symbol))
3818 (if c-strict-syntax-p
3819 (c-benign-error "No offset found for syntactic symbol %s" symbol))
3820 (setq offset 0))
3821 (if (vectorp offset)
3822 offset
3823 (or (and (numberp offset) offset)
3824 (and (symbolp offset) (symbol-value offset))
3828 (defun c-get-syntactic-indentation (langelems)
3829 "Apply `c-get-offset' to a list of langelem cells to get the total
3830 syntactic indentation. The anchor position, whose column is used as a
3831 base for all the collected offsets, is taken from the first element
3832 with a relpos."
3833 ;; Note that topmost-intro always has a relpos at bol, for
3834 ;; historical reasons. It's often used together with other symbols
3835 ;; that has more sane positions. Since we always use the first
3836 ;; found relpos, we rely on that these other symbols always precede
3837 ;; topmost-intro in the LANGELEMS list.
3838 (let ((indent 0) anchor)
3839 (catch 'done
3840 (while langelems
3841 (let ((res (c-get-offset (car langelems))))
3842 (if (vectorp res)
3843 (throw 'done (elt res 0))
3844 (unless anchor
3845 (let ((relpos (cdr (car langelems))))
3846 (if relpos
3847 (setq anchor relpos))))
3848 (setq indent (+ indent res)
3849 langelems (cdr langelems)))))
3850 (+ indent
3851 (if anchor
3852 (save-excursion
3853 (goto-char anchor)
3854 (current-column))
3855 0)))))
3858 (cc-provide 'cc-engine)
3860 ;;; cc-engine.el ends here