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