(outline-previous-heading): New function.
[bpt/emacs.git] / lisp / progmodes / cc-engine.el
Content-type: text/html HCoop Git - bpt/emacs.git/blame - lisp/progmodes/cc-engine.el


500 - Internal Server Error

Malformed UTF-8 character (fatal) at (eval 8) line 1, <$fd> line 2439.
CommitLineData
785eecbb
RS
1;;; cc-engine.el --- core syntax guessing engine for CC mode
2
e1c458ae 3;; Copyright (C) 1985,87,92,93,94,95,96,97,98 Free Software Foundation, Inc.
785eecbb 4
0ec8351b
BW
5;; Authors: 1998 Barry A. Warsaw and Martin Stjernholm
6;; 1992-1997 Barry A. Warsaw
785eecbb
RS
7;; 1987 Dave Detlefs and Stewart Clamen
8;; 1985 Richard M. Stallman
0ec8351b 9;; Maintainer: bug-cc-mode@gnu.org
785eecbb 10;; Created: 22-Apr-1997 (split from cc-mode.el)
6430c434 11;; Version: See cc-mode.el
785eecbb
RS
12;; Keywords: c languages oop
13
14;; This file is part of GNU Emacs.
15
16;; GNU Emacs is free software; you can redistribute it and/or modify
17;; it under the terms of the GNU General Public License as published by
18;; the Free Software Foundation; either version 2, or (at your option)
19;; any later version.
20
21;; GNU Emacs is distributed in the hope that it will be useful,
22;; but WITHOUT ANY WARRANTY; without even the implied warranty of
23;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24;; GNU General Public License for more details.
25
26;; You should have received a copy of the GNU General Public License
27;; along with GNU Emacs; see the file COPYING. If not, write to the
28;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
29;; Boston, MA 02111-1307, USA.
30
31\f
0ec8351b
BW
32(eval-when-compile
33 (require 'cc-defs))
34
64001211
RS
35;; KLUDGE ALERT: c-maybe-labelp is used to pass information between
36;; c-crosses-statement-barrier-p and c-beginning-of-statement-1. A
37;; better way should be implemented, but this will at least shut up
38;; the byte compiler.
39(defvar c-maybe-labelp nil)
40
41;; WARNING WARNING WARNING
42;;
43;; Be *exceptionally* careful about modifications to this function!
44;; Much of CC Mode depends on this Doing The Right Thing. If you
45;; break it you will be sorry. If you think you know how this works,
46;; you probably don't. No human on Earth does! :-)
47;;
48;; WARNING WARNING WARNING
785eecbb
RS
49
50(defun c-beginning-of-statement-1 (&optional lim)
51 ;; move to the start of the current statement, or the previous
52 ;; statement if already at the beginning of one.
53 (let ((firstp t)
54 (substmt-p t)
64001211 55 donep c-in-literal-cache saved
785eecbb
RS
56 (last-begin (point)))
57 ;; first check for bare semicolon
58 (if (and (progn (c-backward-syntactic-ws lim)
59 (eq (char-before) ?\;))
60 (c-safe (progn (forward-char -1)
61 (setq saved (point))
62 t))
63 (progn (c-backward-syntactic-ws lim)
d0c50a29 64 (memq (char-before) '(?\; ?{ ?:)))
785eecbb
RS
65 )
66 (setq last-begin saved)
67 (goto-char last-begin)
68 (while (not donep)
69 ;; stop at beginning of buffer
70 (if (bobp) (setq donep t)
71 ;; go backwards one balanced expression, but be careful of
72 ;; unbalanced paren being reached
0ec8351b 73 (if (not (c-safe (progn (c-backward-sexp 1) t)))
785eecbb
RS
74 (progn
75 (if firstp
76 (backward-up-list 1)
77 (goto-char last-begin))
78 ;; skip over any unary operators, or other special
79 ;; characters appearing at front of identifier
80 (save-excursion
81 (c-backward-syntactic-ws lim)
0ec8351b 82 (skip-chars-backward "-+!*&:.~@ \t\n")
785eecbb
RS
83 (if (eq (char-before) ?\()
84 (setq last-begin (point))))
85 (goto-char last-begin)
86 (setq last-begin (point)
87 donep t)))
88
64001211 89 (setq c-maybe-labelp nil)
785eecbb
RS
90 ;; see if we're in a literal. if not, then this bufpos may be
91 ;; a candidate for stopping
92 (cond
93 ;; CASE 0: did we hit the error condition above?
94 (donep)
95 ;; CASE 1: are we in a literal?
96 ((eq (c-in-literal lim) 'pound)
97 (beginning-of-line))
98 ;; CASE 2: some other kind of literal?
99 ((c-in-literal lim))
100 ;; CASE 3: are we looking at a conditional keyword?
101 ((or (looking-at c-conditional-key)
102 (and (eq (char-after) ?\()
103 (save-excursion
0ec8351b 104 (c-forward-sexp 1)
785eecbb
RS
105 (c-forward-syntactic-ws)
106 (not (eq (char-after) ?\;)))
107 (let ((here (point))
108 (foundp (progn
109 (c-backward-syntactic-ws lim)
110 (forward-word -1)
111 (and lim
112 (<= lim (point))
113 (not (c-in-literal lim))
6430c434 114 (not (eq (char-before) ?_))
785eecbb
RS
115 (looking-at c-conditional-key)
116 ))))
117 ;; did we find a conditional?
118 (if (not foundp)
119 (goto-char here))
120 foundp)))
121 ;; are we in the middle of an else-if clause?
122 (if (save-excursion
123 (and (not substmt-p)
0ec8351b 124 (c-safe (progn (c-forward-sexp -1) t))
785eecbb
RS
125 (looking-at "\\<else\\>[ \t\n]+\\<if\\>")
126 (not (c-in-literal lim))))
127 (progn
0ec8351b 128 (c-forward-sexp -1)
785eecbb
RS
129 (c-backward-to-start-of-if lim)))
130 ;; are we sitting at an else clause, that we are not a
131 ;; substatement of?
132 (if (and (not substmt-p)
133 (looking-at "\\<else\\>[^_]"))
134 (c-backward-to-start-of-if lim))
0ec8351b
BW
135 ;; a finally or a series of catches?
136 (if (not substmt-p)
137 (while (looking-at "\\<\\(catch\\|finally\\)\\>[^_]")
138 (c-safe (c-backward-sexp 2))
139 (if (eq (char-after) ?\()
140 (c-safe (c-backward-sexp)))))
785eecbb
RS
141 ;; are we sitting at the while of a do-while?
142 (if (and (looking-at "\\<while\\>[^_]")
143 (c-backward-to-start-of-do lim))
144 (setq substmt-p nil))
145 (setq last-begin (point)
146 donep substmt-p))
147 ;; CASE 4: are we looking at a label?
148 ((looking-at c-label-key))
149 ;; CASE 5: is this the first time we're checking?
150 (firstp (setq firstp nil
151 substmt-p (not (c-crosses-statement-barrier-p
152 (point) last-begin))
153 last-begin (point)))
154 ;; CASE 6: have we crossed a statement barrier?
0ec8351b
BW
155 ((save-excursion
156 ;; Move over in-expression blocks before checking the
157 ;; barrier
158 (if (or (memq (char-after) '(?\( ?\[))
159 (and (eq (char-after) ?{)
160 (c-looking-at-inexpr-block lim)))
161 (c-forward-sexp 1))
162 (c-crosses-statement-barrier-p (point) last-begin))
785eecbb
RS
163 (setq donep t))
164 ;; CASE 7: ignore labels
64001211 165 ((and c-maybe-labelp
785eecbb
RS
166 (or (and c-access-key (looking-at c-access-key))
167 ;; with switch labels, we have to go back further
168 ;; to try to pick up the case or default
169 ;; keyword. Potential bogosity alert: we assume
170 ;; `case' or `default' is first thing on line
171 (let ((here (point)))
172 (beginning-of-line)
173 (c-forward-syntactic-ws)
174 (if (looking-at c-switch-label-key)
175 t
176 (goto-char here)
177 nil))
178 (looking-at c-label-key))))
179 ;; CASE 8: ObjC or Java method def
180 ((and c-method-key
181 (setq last-begin (c-in-method-def-p)))
182 (setq donep t))
183 ;; CASE 9: nothing special
184 (t (setq last-begin (point)))
185 ))))
186 (goto-char last-begin)
0ec8351b
BW
187 ;; We always want to skip over the non-whitespace modifier
188 ;; characters that can start a statement.
189 (let ((lim (point)))
190 (skip-chars-backward "-+!*&~@ \t\n" (c-point 'boi))
191 (skip-chars-forward " \t\n" lim))))
785eecbb
RS
192
193(defun c-end-of-statement-1 ()
041ec7f6
RS
194 (condition-case nil
195 (let (beg end found)
785eecbb 196 (while (and (not (eobp))
041ec7f6
RS
197 (progn
198 (setq beg (point))
0ec8351b 199 (c-forward-sexp 1)
041ec7f6
RS
200 (setq end (point))
201 (goto-char beg)
202 (setq found nil)
203 (while (and (not found)
204 (re-search-forward "[;{}]" end t))
205 (if (not (c-in-literal beg))
206 (setq found t)))
207 (not found)))
208 (goto-char end))
209 (re-search-backward "[;{}]")
785eecbb 210 (forward-char 1))
9796cb5b 211 (error
785eecbb 212 (let ((beg (point)))
9796cb5b 213 (c-safe (backward-up-list -1))
785eecbb
RS
214 (let ((end (point)))
215 (goto-char beg)
9796cb5b
RS
216 (search-forward ";" end 'move)))
217 )))
785eecbb
RS
218
219\f
220(defun c-crosses-statement-barrier-p (from to)
221 ;; Does buffer positions FROM to TO cross a C statement boundary?
222 (let ((here (point))
223 (lim from)
224 crossedp)
225 (condition-case ()
226 (progn
227 (goto-char from)
228 (while (and (not crossedp)
229 (< (point) to))
0ec8351b 230 (skip-chars-forward "^;{}:" (1- to))
785eecbb
RS
231 (if (not (c-in-literal lim))
232 (progn
233 (if (memq (char-after) '(?\; ?{ ?}))
234 (setq crossedp t)
235 (if (eq (char-after) ?:)
64001211 236 (setq c-maybe-labelp t))
785eecbb
RS
237 (forward-char 1))
238 (setq lim (point)))
239 (forward-char 1))))
240 (error (setq crossedp nil)))
241 (goto-char here)
242 crossedp))
243
244\f
245;; Skipping of "syntactic whitespace", defined as lexical whitespace,
246;; C and C++ style comments, and preprocessor directives. Search no
247;; farther back or forward than optional LIM. If LIM is omitted,
248;; `beginning-of-defun' is used for backward skipping, point-max is
249;; used for forward skipping.
250
251(defun c-forward-syntactic-ws (&optional lim)
252 ;; Forward skip of syntactic whitespace for Emacs 19.
e1c458ae
RS
253 (let* ((here (point-max))
254 (hugenum (point-max)))
255 (while (/= here (point))
256 (setq here (point))
257 (forward-comment hugenum)
258 ;; skip preprocessor directives
259 (when (and (eq (char-after) ?#)
785eecbb 260 (= (c-point 'boi) (point)))
e1c458ae
RS
261 (while (eq (char-before (c-point 'eol)) ?\\)
262 (forward-line 1))
263 (end-of-line))
264 )
265 (if lim (goto-char (min (point) lim)))))
266
267(defsubst c-beginning-of-macro (&optional lim)
268 ;; Go to the beginning of a cpp macro definition. Leaves point at
269 ;; the beginning of the macro and returns t if in a cpp macro
270 ;; definition, otherwise returns nil and leaves point unchanged.
271 ;; `lim' is currently ignored, but the interface requires it.
272 (let ((here (point)))
273 (beginning-of-line)
274 (while (eq (char-before (1- (point))) ?\\)
275 (forward-line -1))
276 (back-to-indentation)
277 (if (eq (char-after) ?#)
278 t
279 (goto-char here)
280 nil)))
785eecbb
RS
281
282(defun c-backward-syntactic-ws (&optional lim)
283 ;; Backward skip over syntactic whitespace for Emacs 19.
e1c458ae
RS
284 (let* ((here (point-min))
285 (hugenum (- (point-max))))
286 (while (/= here (point))
287 (setq here (point))
288 (forward-comment hugenum)
289 (c-beginning-of-macro))
290 (if lim (goto-char (max (point) lim)))))
785eecbb
RS
291
292\f
b2acd789 293;; Moving by tokens, where a token is defined as all symbols and
0ec8351b
BW
294;; identifiers which aren't syntactic whitespace (note that "->" is
295;; considered to be two tokens). Point is always either left at the
296;; beginning of a token or not moved at all. COUNT specifies the
297;; number of tokens to move; a negative COUNT moves in the opposite
298;; direction. A COUNT of 0 moves to the next token beginning only if
299;; not already at one. If BALANCED is true, move over balanced
300;; parens, otherwise move into them. Also, if BALANCED is true, never
301;; move out of an enclosing paren. LIM sets the limit for the
302;; movement and defaults to the point limit. Returns the number of
b2acd789 303;; tokens left to move (positive or negative). If BALANCED is true, a
0ec8351b
BW
304;; move over a balanced paren counts as one. Note that if COUNT is 0
305;; and no appropriate token beginning is found, 1 will be returned.
306;; Thus, a return value of 0 guarantees that point is at the requested
307;; position and a return value less (without signs) than COUNT
308;; guarantees that point is at the beginning of some token.
b2acd789
RS
309
310(defun c-forward-token-1 (&optional count balanced lim)
0ec8351b
BW
311 (or count (setq count 1))
312 (if (< count 0)
313 (- (c-backward-token-1 (- count) balanced lim))
314 (let ((jump-syntax (if balanced
315 '(?w ?_ ?\( ?\) ?\" ?\\ ?/ ?$ ?')
316 '(?w ?_ ?\" ?\\ ?/ ?')))
317 (last (point))
318 (prev (point)))
319 (if (/= (point)
320 (progn (c-forward-syntactic-ws) (point)))
321 ;; Skip whitespace. Count this as a move if we did in fact
322 ;; move and aren't out of bounds.
323 (or (eobp)
324 (and lim (> (point) lim))
325 (setq count (max (1- count) 0))))
326 (if (and (= count 0)
327 (or (and (memq (char-syntax (or (char-after) ? )) '(?w ?_))
328 (memq (char-syntax (or (char-before) ? )) '(?w ?_)))
329 (eobp)))
330 ;; If count is zero we should jump if in the middle of a
331 ;; token or if there is whitespace between point and the
332 ;; following token beginning.
333 (setq count 1))
334 ;; Avoid having the limit tests inside the loop.
335 (save-restriction
336 (if lim (narrow-to-region (point-min) lim))
337 (if (eobp)
338 (goto-char last)
339 (condition-case nil
340 (while (> count 0)
341 (setq prev last
342 last (point))
343 (if (memq (char-syntax (char-after)) jump-syntax)
344 (goto-char (scan-sexps (point) 1))
345 (forward-char))
346 (c-forward-syntactic-ws lim)
347 (setq count (1- count)))
348 (error (goto-char last)))
349 (when (eobp)
350 (goto-char prev)
351 (setq count (1+ count)))))
352 count)))
b2acd789
RS
353
354(defun c-backward-token-1 (&optional count balanced lim)
0ec8351b
BW
355 (or count (setq count 1))
356 (if (< count 0)
357 (- (c-forward-token-1 (- count) balanced lim))
358 (let ((jump-syntax (if balanced
359 '(?w ?_ ?\( ?\) ?\" ?\\ ?/ ?$ ?')
360 '(?w ?_ ?\" ?\\ ?/ ?')))
361 last)
362 (if (and (= count 0)
363 (or (and (memq (char-syntax (or (char-after) ? )) '(?w ?_))
364 (memq (char-syntax (or (char-before) ? )) '(?w ?_)))
365 (/= (point)
366 (save-excursion (c-forward-syntactic-ws) (point)))
367 (eobp)))
368 ;; If count is zero we should jump if in the middle of a
369 ;; token or if there is whitespace between point and the
370 ;; following token beginning.
371 (setq count 1))
372 ;; Avoid having the limit tests inside the loop.
373 (save-restriction
374 (if lim (narrow-to-region lim (point-max)))
375 (or (bobp)
376 (progn
377 (condition-case nil
378 (while (progn
379 (setq last (point))
380 (> count 0))
381 (c-backward-syntactic-ws lim)
382 (if (memq (char-syntax (char-before)) jump-syntax)
383 (goto-char (scan-sexps (point) -1))
384 (backward-char))
385 (setq count (1- count)))
386 (error (goto-char last)))
387 (if (bobp) (goto-char last)))))
388 count)))
b2acd789
RS
389
390\f
785eecbb
RS
391;; Return `c' if in a C-style comment, `c++' if in a C++ style
392;; comment, `string' if in a string literal, `pound' if on a
393;; preprocessor line, or nil if not in a comment at all. Optional LIM
394;; is used as the backward limit of the search. If omitted, or nil,
395;; `beginning-of-defun' is used."
396
397(defun c-in-literal (&optional lim)
398 ;; Determine if point is in a C++ literal. we cache the last point
399 ;; calculated if the cache is enabled
400 (if (and (boundp 'c-in-literal-cache)
401 c-in-literal-cache
402 (= (point) (aref c-in-literal-cache 0)))
403 (aref c-in-literal-cache 1)
404 (let ((rtn (save-excursion
405 (let* ((lim (or lim (c-point 'bod)))
785eecbb
RS
406 (state (parse-partial-sexp lim (point))))
407 (cond
408 ((nth 3 state) 'string)
409 ((nth 4 state) (if (nth 7 state) 'c++ 'c))
e1c458ae 410 ((c-beginning-of-macro lim) 'pound)
785eecbb
RS
411 (t nil))))))
412 ;; cache this result if the cache is enabled
413 (and (boundp 'c-in-literal-cache)
414 (setq c-in-literal-cache (vector (point) rtn)))
415 rtn)))
416
e1c458ae
RS
417;; XEmacs has a built-in function that should make this much quicker.
418;; I don't think we even need the cache, which makes our lives more
419;; complicated anyway. In this case, lim is ignored.
420(defun c-fast-in-literal (&optional lim)
421 (let ((context (buffer-syntactic-context)))
422 (cond
423 ((eq context 'string) 'string)
424 ((eq context 'comment) 'c++)
425 ((eq context 'block-comment) 'c)
426 ((save-excursion (c-beginning-of-macro lim)) 'pound))))
427
428(if (fboundp 'buffer-syntactic-context)
429 (defalias 'c-in-literal 'c-fast-in-literal))
430
0ec8351b 431(defun c-literal-limits (&optional lim near)
e1c458ae
RS
432 ;; Returns a cons of the beginning and end positions of the comment
433 ;; or string surrounding point (including both delimiters), or nil
0ec8351b
BW
434 ;; if point isn't in one. If LIM is non-nil, it's used as the
435 ;; "safe" position to start parsing from. If NEAR is non-nil, then
436 ;; the limits of any literal next to point is returned. "Next to"
437 ;; means there's only [ \t] between point and the literal. The
438 ;; search for such a literal is done first in forward direction.
439 ;;
440 ;; This is the Emacs 19 version.
e1c458ae 441 (save-excursion
0ec8351b
BW
442 (let* ((pos (point))
443 (lim (or lim (c-point 'bod)))
e1c458ae
RS
444 (state (parse-partial-sexp lim (point))))
445 (cond ((nth 3 state)
446 ;; String. Search backward for the start.
447 (while (nth 3 state)
448 (search-backward (make-string 1 (nth 3 state)))
449 (setq state (parse-partial-sexp lim (point))))
0ec8351b 450 (cons (point) (or (c-safe (c-forward-sexp 1) (point))
e1c458ae
RS
451 (point-max))))
452 ((nth 7 state)
0ec8351b 453 ;; Line comment. Search from bol for the comment starter.
e1c458ae
RS
454 (beginning-of-line)
455 (setq state (parse-partial-sexp lim (point))
456 lim (point))
457 (while (not (nth 7 state))
458 (search-forward "//") ; Should never fail.
459 (setq state (parse-partial-sexp
460 lim (point) nil nil state)
461 lim (point)))
462 (backward-char 2)
463 (cons (point) (progn (forward-comment 1) (point))))
464 ((nth 4 state)
0ec8351b 465 ;; Block comment. Search backward for the comment starter.
e1c458ae
RS
466 (while (nth 4 state)
467 (search-backward "/*") ; Should never fail.
468 (setq state (parse-partial-sexp lim (point))))
469 (cons (point) (progn (forward-comment 1) (point))))
470 ((c-safe (nth 4 (parse-partial-sexp ; Can't use prev state due
471 lim (1+ (point))))) ; to bug in Emacs 19.34.
472 ;; We're standing in a comment starter.
473 (backward-char 2)
474 (cons (point) (progn (forward-comment 1) (point))))
0ec8351b
BW
475 (near
476 (goto-char pos)
477 ;; Search forward for a literal.
478 (skip-chars-forward " \t")
479 (cond
480 ((eq (char-syntax (or (char-after) ?\ )) ?\") ; String.
481 (cons (point) (or (c-safe (c-forward-sexp 1) (point))
482 (point-max))))
483 ((looking-at "/[/*]") ; Line or block comment.
484 (cons (point) (progn (forward-comment 1) (point))))
485 (t
486 ;; Search backward.
487 (skip-chars-backward " \t")
488 (let ((end (point)) beg)
489 (cond
490 ((eq (char-syntax (or (char-before) ?\ )) ?\") ; String.
491 (setq beg (c-safe (c-backward-sexp 1) (point))))
492 ((and (c-safe (forward-char -2) t)
493 (looking-at "*/"))
494 ;; Block comment. Due to the nature of line
495 ;; comments, they will always be covered by the
496 ;; normal case above.
497 (goto-char end)
498 (forward-comment -1)
499 ;; If LIM is bogus, beg will be bogus.
500 (setq beg (point))))
501 (if beg (cons beg end))))))
e1c458ae
RS
502 ))))
503
504(defun c-literal-limits-fast (&optional lim)
0ec8351b
BW
505 ;; Like c-literal-limits, but for emacsen whose `parse-partial-sexp'
506 ;; returns the pos of the comment start. FIXME: Add NEAR.
e1c458ae
RS
507 (save-excursion
508 (let ((state (parse-partial-sexp lim (point))))
509 (cond ((nth 3 state) ; String.
510 (goto-char (nth 8 state))
0ec8351b 511 (cons (point) (or (c-safe (c-forward-sexp 1) (point))
e1c458ae
RS
512 (point-max))))
513 ((nth 4 state) ; Comment.
514 (goto-char (nth 8 state))
515 (cons (point) (progn (forward-comment 1) (point))))
516 ((c-safe
517 (nth 4 (parse-partial-sexp ; Works?
518 (point) (1+ (point)) nil nil state)))
519 ;; We're in a comment starter.
520 (backward-char 2)
521 (cons (point) (progn (forward-comment 1) (point))))
522 ))))
523
524(defun c-collect-line-comments (range)
525 ;; If the argument is a cons of two buffer positions (such as
526 ;; returned by c-literal-limits), and that range contains a C++
527 ;; style line comment, then an extended range is returned that
b2acd789
RS
528 ;; contains all adjacent line comments (i.e. all comments that
529 ;; starts in the same column with no empty lines or non-whitespace
530 ;; characters between them). Otherwise the argument is returned.
e1c458ae
RS
531 (save-excursion
532 (condition-case nil
533 (if (and (consp range) (progn
534 (goto-char (car range))
535 (looking-at "//")))
b2acd789
RS
536 (let ((col (current-column))
537 (beg (point))
538 (end (cdr range)))
e1c458ae
RS
539 (while (and (not (bobp))
540 (forward-comment -1)
b2acd789
RS
541 (looking-at "//")
542 (= col (current-column)))
e1c458ae 543 (setq beg (point)))
b2acd789
RS
544 (goto-char end)
545 (while (progn
546 (skip-chars-forward " \t")
547 (and (looking-at "//")
548 (= col (current-column))))
549 (forward-comment 1)
550 (setq end (point)))
551 (cons beg end))
e1c458ae
RS
552 range)
553 (error range))))
554
0ec8351b
BW
555(defun c-literal-type (range)
556 ;; Convenience function that given the result of c-literal-limits,
557 ;; returns nil or the type of literal that the range surrounds.
558 ;; It's much faster than using c-in-literal and is intended to be
559 ;; used when you need both the type of a literal and its limits.
560 (if (consp range)
561 (save-excursion
562 (goto-char (car range))
563 (cond ((eq (char-syntax (or (char-after) ?\ )) ?\") 'string)
564 ((looking-at "//") 'c++)
565 (t 'c))) ; Assuming the range is valid.
566 range))
567
e1c458ae 568
785eecbb
RS
569\f
570;; utilities for moving and querying around syntactic elements
571(defvar c-parsing-error nil)
572
573(defun c-parse-state ()
574 ;; Finds and records all open parens between some important point
575 ;; earlier in the file and point.
576 ;;
577 ;; if there's a state cache, return it
578 (setq c-parsing-error nil)
579 (if (boundp 'c-state-cache) c-state-cache
580 (let* (at-bob
581 (pos (save-excursion
582 ;; go back 2 bods, but ignore any bogus positions
583 ;; returned by beginning-of-defun (i.e. open paren
584 ;; in column zero)
585 (let ((cnt 2))
586 (while (not (or at-bob (zerop cnt)))
e1c458ae 587 (goto-char (c-point 'bod))
0ec8351b
BW
588 (if (and
589 (eq (char-after) ?\{)
590 ;; The following catches an obscure special
591 ;; case where the brace is preceded by an
592 ;; open paren. That can only legally occur
593 ;; with blocks inside expressions and in
594 ;; Pike special brace lists. Even so, this
595 ;; test is still bogus then, but hopefully
596 ;; good enough. (We don't want to use
597 ;; up-list here since it might be slow.)
598 (save-excursion
599 (c-backward-syntactic-ws)
600 (not (eq (char-before) ?\())))
785eecbb
RS
601 (setq cnt (1- cnt)))
602 (if (bobp)
603 (setq at-bob t))))
604 (point)))
605 (here (save-excursion
606 ;;(skip-chars-forward " \t}")
607 (point)))
608 (last-bod pos) (last-pos pos)
609 placeholder state sexp-end)
610 ;; cache last bod position
611 (while (catch 'backup-bod
612 (setq state nil)
613 (while (and pos (< pos here))
614 (setq last-pos pos)
615 (if (and (setq pos (c-safe (scan-lists pos 1 -1)))
616 (<= pos here))
617 (progn
618 (setq sexp-end (c-safe (scan-sexps (1- pos) 1)))
619 (if (and sexp-end
620 (<= sexp-end here))
621 ;; we want to record both the start and end
622 ;; of this sexp, but we only want to record
623 ;; the last-most of any of them before here
624 (progn
625 (if (eq (char-after (1- pos)) ?\{)
626 (setq state (cons (cons (1- pos) sexp-end)
627 (if (consp (car state))
628 (cdr state)
629 state))))
630 (setq pos sexp-end))
631 ;; we're contained in this sexp so put pos on
632 ;; front of list
633 (setq state (cons (1- pos) state))))
634 ;; something bad happened. check to see if we
635 ;; crossed an unbalanced close brace. if so, we
636 ;; didn't really find the right `important bufpos'
637 ;; so lets back up and try again
638 (if (and (not pos) (not at-bob)
639 (setq placeholder
640 (c-safe (scan-lists last-pos 1 1)))
641 ;;(char-after (1- placeholder))
642 (<= placeholder here)
643 (eq (char-after (1- placeholder)) ?\}))
644 (while t
645 (setq last-bod (c-safe (scan-lists last-bod -1 1)))
646 (if (not last-bod)
647 (progn
648 ;; bogus, but what can we do here?
649 (setq c-parsing-error (1- placeholder))
650 (throw 'backup-bod nil))
651 (setq at-bob (= last-bod (point-min))
652 pos last-bod)
653 (if (= (char-after last-bod) ?\{)
654 (throw 'backup-bod t)))
655 )) ;end-if
656 )) ;end-while
657 nil))
658 state)))
659
660(defun c-whack-state (bufpos state)
661 ;; whack off any state information that appears on STATE which lies
662 ;; after the bounds of BUFPOS.
663 (let (newstate car)
664 (while state
665 (setq car (car state)
666 state (cdr state))
667 (if (consp car)
668 ;; just check the car, because in a balanced brace
669 ;; expression, it must be impossible for the corresponding
670 ;; close brace to be before point, but the open brace to be
671 ;; after.
672 (if (<= bufpos (car car))
673 nil ; whack it off
674 ;; its possible that the open brace is before bufpos, but
675 ;; the close brace is after. In that case, convert this
676 ;; to a non-cons element.
677 (if (<= bufpos (cdr car))
678 (setq newstate (append newstate (list (car car))))
679 ;; we know that both the open and close braces are
680 ;; before bufpos, so we also know that everything else
681 ;; on state is before bufpos, so we can glom up the
682 ;; whole thing and exit.
683 (setq newstate (append newstate (list car) state)
684 state nil)))
685 (if (<= bufpos car)
686 nil ; whack it off
687 ;; it's before bufpos, so everything else should too
688 (setq newstate (append newstate (list car) state)
689 state nil))))
690 newstate))
691
692(defun c-hack-state (bufpos which state)
693 ;; Using BUFPOS buffer position, and WHICH (must be 'open or
694 ;; 'close), hack the c-parse-state STATE and return the results.
695 (if (eq which 'open)
696 (let ((car (car state)))
697 (if (or (null car)
698 (consp car)
699 (/= bufpos car))
700 (cons bufpos state)
701 state))
702 (if (not (eq which 'close))
703 (error "c-hack-state, bad argument: %s" which))
704 ;; 'close brace
705 (let ((car (car state))
706 (cdr (cdr state)))
707 (if (consp car)
708 (setq car (car cdr)
709 cdr (cdr cdr)))
710 ;; TBD: is this test relevant???
711 (if (consp car)
712 state ;on error, don't change
713 ;; watch out for balanced expr already on cdr of list
714 (cons (cons car bufpos)
715 (if (consp (car cdr))
716 (cdr cdr) cdr))
717 ))))
718
719(defun c-adjust-state (from to shift state)
720 ;; Adjust all points in state that lie in the region FROM..TO by
0ec8351b 721 ;; SHIFT amount.
785eecbb
RS
722 (mapcar
723 (function
724 (lambda (e)
725 (if (consp e)
726 (let ((car (car e))
727 (cdr (cdr e)))
728 (if (and (<= from car) (< car to))
729 (setcar e (+ shift car)))
730 (if (and (<= from cdr) (< cdr to))
731 (setcdr e (+ shift cdr))))
732 (if (and (<= from e) (< e to))
733 (setq e (+ shift e))))
734 e))
735 state))
736
737\f
738(defun c-beginning-of-inheritance-list (&optional lim)
739 ;; Go to the first non-whitespace after the colon that starts a
740 ;; multiple inheritance introduction. Optional LIM is the farthest
741 ;; back we should search.
742 (let ((lim (or lim (c-point 'bod)))
743 (placeholder (progn
744 (back-to-indentation)
745 (point))))
746 (c-backward-syntactic-ws lim)
747 (while (and (> (point) lim)
748 (memq (char-before) '(?, ?:))
749 (progn
750 (beginning-of-line)
751 (setq placeholder (point))
752 (skip-chars-forward " \t")
753 (not (looking-at c-class-key))
754 ))
755 (c-backward-syntactic-ws lim))
756 (goto-char placeholder)
757 (skip-chars-forward "^:" (c-point 'eol))))
758
785eecbb
RS
759(defun c-in-method-def-p ()
760 ;; Return nil if we aren't in a method definition, otherwise the
761 ;; position of the initial [+-].
762 (save-excursion
763 (beginning-of-line)
764 (and c-method-key
765 (looking-at c-method-key)
766 (point))
767 ))
768
abb7e5cf
SM
769(defun c-at-toplevel-p ()
770 "Return a determination as to whether point is at the `top-level'.
771Being at the top-level means that point is either outside any
772enclosing block (such function definition), or inside a class
773definition, but outside any method blocks.
774
775If point is not at the top-level (e.g. it is inside a method
776definition), then nil is returned. Otherwise, if point is at a
777top-level not enclosed within a class definition, t is returned.
778Otherwise, a 2-vector is returned where the zeroth element is the
779buffer position of the start of the class declaration, and the first
780element is the buffer position of the enclosing class's opening
781brace."
782 (let ((state (c-parse-state)))
783 (or (not (c-most-enclosing-brace state))
784 (c-search-uplist-for-classkey state))))
785
785eecbb
RS
786(defun c-just-after-func-arglist-p (&optional containing)
787 ;; Return t if we are between a function's argument list closing
788 ;; paren and its opening brace. Note that the list close brace
789 ;; could be followed by a "const" specifier or a member init hanging
790 ;; colon. Optional CONTAINING is position of containing s-exp open
791 ;; brace. If not supplied, point is used as search start.
792 (save-excursion
793 (c-backward-syntactic-ws)
794 (let ((checkpoint (or containing (point))))
795 (goto-char checkpoint)
796 ;; could be looking at const specifier
797 (if (and (eq (char-before) ?t)
798 (forward-word -1)
799 (looking-at "\\<const\\>"))
800 (c-backward-syntactic-ws)
801 ;; otherwise, we could be looking at a hanging member init
802 ;; colon
803 (goto-char checkpoint)
804 (if (and (eq (char-before) ?:)
805 (progn
806 (forward-char -1)
807 (c-backward-syntactic-ws)
808 (looking-at "[ \t\n]*:\\([^:]+\\|$\\)")))
809 nil
810 (goto-char checkpoint))
811 )
812 (and (eq (char-before) ?\))
813 ;; check if we are looking at a method def
814 (or (not c-method-key)
815 (progn
0ec8351b 816 (c-forward-sexp -1)
785eecbb
RS
817 (forward-char -1)
818 (c-backward-syntactic-ws)
819 (not (or (memq (char-before) '(?- ?+))
820 ;; or a class category
821 (progn
0ec8351b 822 (c-forward-sexp -2)
785eecbb
RS
823 (looking-at c-class-key))
824 )))))
825 )))
826
827;; defuns to look backwards for things
828(defun c-backward-to-start-of-do (&optional lim)
829 ;; Move to the start of the last "unbalanced" do expression.
830 ;; Optional LIM is the farthest back to search. If none is found,
831 ;; nil is returned and point is left unchanged, otherwise t is returned.
832 (let ((do-level 1)
833 (case-fold-search nil)
834 (lim (or lim (c-point 'bod)))
835 (here (point))
836 foundp)
837 (while (not (zerop do-level))
838 ;; we protect this call because trying to execute this when the
839 ;; while is not associated with a do will throw an error
840 (condition-case nil
841 (progn
0ec8351b 842 (c-backward-sexp 1)
785eecbb 843 (cond
e1c458ae
RS
844 ;; break infloop for illegal C code
845 ((bobp) (setq do-level 0))
785eecbb
RS
846 ((memq (c-in-literal lim) '(c c++)))
847 ((looking-at "while\\b[^_]")
848 (setq do-level (1+ do-level)))
849 ((looking-at "do\\b[^_]")
850 (if (zerop (setq do-level (1- do-level)))
851 (setq foundp t)))
852 ((<= (point) lim)
853 (setq do-level 0)
854 (goto-char lim))))
855 (error
856 (goto-char lim)
857 (setq do-level 0))))
858 (if (not foundp)
859 (goto-char here))
860 foundp))
861
862(defun c-backward-to-start-of-if (&optional lim)
863 ;; Move to the start of the last "unbalanced" if and return t. If
864 ;; none is found, and we are looking at an if clause, nil is
865 ;; returned. If none is found and we are looking at an else clause,
866 ;; an error is thrown.
867 (let ((if-level 1)
868 (here (c-point 'bol))
869 (case-fold-search nil)
e1c458ae
RS
870 (lim (or (and (>= (point) lim)
871 lim)
872 (c-point 'bod)))
785eecbb
RS
873 (at-if (looking-at "if\\b[^_]")))
874 (catch 'orphan-if
875 (while (and (not (bobp))
876 (not (zerop if-level)))
877 (c-backward-syntactic-ws)
878 (condition-case nil
0ec8351b 879 (c-backward-sexp 1)
785eecbb
RS
880 (error
881 (if at-if
882 (throw 'orphan-if nil)
883 (error "No matching `if' found for `else' on line %d."
884 (1+ (count-lines 1 here))))))
885 (cond
886 ((looking-at "else\\b[^_]")
887 (setq if-level (1+ if-level)))
888 ((looking-at "if\\b[^_]")
889 ;; check for else if... skip over
890 (let ((here (point)))
0ec8351b 891 (c-safe (c-forward-sexp -1))
785eecbb
RS
892 (if (looking-at "\\<else\\>[ \t]+\\<if\\>")
893 nil
894 (setq if-level (1- if-level))
895 (goto-char here))))
896 ((< (point) lim)
897 (setq if-level 0)
898 (goto-char lim))
899 ))
900 t)))
901
902(defun c-skip-conditional ()
903 ;; skip forward over conditional at point, including any predicate
904 ;; statements in parentheses. No error checking is performed.
0ec8351b
BW
905 (c-forward-sexp (cond
906 ;; else if()
907 ((looking-at "\\<else\\>[ \t]+\\<if\\>") 3)
908 ;; do, else, try, finally
909 ((looking-at "\\<\\(do\\|else\\|try\\|finally\\)\\>") 1)
910 ;; for, if, while, switch, catch, synchronized
911 (t 2))))
785eecbb
RS
912
913(defun c-skip-case-statement-forward (state &optional lim)
914 ;; skip forward over case/default bodies, with optional maximal
915 ;; limit. if no next case body is found, nil is returned and point
916 ;; is not moved
917 (let ((lim (or lim (point-max)))
918 (here (point))
919 donep foundp bufpos
920 (safepos (point))
921 (balanced (car state)))
922 ;; search until we've passed the limit, or we've found our match
923 (while (and (< (point) lim)
924 (not donep))
925 (setq safepos (point))
926 ;; see if we can find a case statement, not in a literal
927 (if (and (re-search-forward c-switch-label-key lim 'move)
928 (setq bufpos (match-beginning 0))
929 (not (c-in-literal safepos))
930 (/= bufpos here))
931 ;; if we crossed into a balanced sexp, we know the case is
932 ;; not part of our switch statement, so just bound over the
933 ;; sexp and keep looking.
934 (if (and (consp balanced)
935 (> bufpos (car balanced))
936 (< bufpos (cdr balanced)))
937 (goto-char (cdr balanced))
938 (goto-char bufpos)
939 (setq donep t
940 foundp t))))
941 (if (not foundp)
942 (goto-char here))
943 foundp))
944
945(defun c-search-uplist-for-classkey (brace-state)
946 ;; search for the containing class, returning a 2 element vector if
0ec8351b
BW
947 ;; found. aref 0 contains the bufpos of the boi of the class key
948 ;; line, and aref 1 contains the bufpos of the open brace.
785eecbb
RS
949 (if (null brace-state)
950 ;; no brace-state means we cannot be inside a class
951 nil
952 (let ((carcache (car brace-state))
953 search-start search-end)
954 (if (consp carcache)
955 ;; a cons cell in the first element means that there is some
956 ;; balanced sexp before the current bufpos. this we can
957 ;; ignore. the nth 1 and nth 2 elements define for us the
958 ;; search boundaries
959 (setq search-start (nth 2 brace-state)
960 search-end (nth 1 brace-state))
961 ;; if the car was not a cons cell then nth 0 and nth 1 define
962 ;; for us the search boundaries
963 (setq search-start (nth 1 brace-state)
964 search-end (nth 0 brace-state)))
965 ;; search-end cannot be a cons cell
966 (and (consp search-end)
967 (error "consp search-end: %s" search-end))
968 ;; if search-end is nil, or if the search-end character isn't an
969 ;; open brace, we are definitely not in a class
970 (if (or (not search-end)
971 (< search-end (point-min))
972 (not (eq (char-after search-end) ?{)))
973 nil
974 ;; now, we need to look more closely at search-start. if
975 ;; search-start is nil, then our start boundary is really
976 ;; point-min.
977 (if (not search-start)
978 (setq search-start (point-min))
979 ;; if search-start is a cons cell, then we can start
980 ;; searching from the end of the balanced sexp just ahead of
981 ;; us
982 (if (consp search-start)
983 (setq search-start (cdr search-start))))
984 ;; now we can do a quick regexp search from search-start to
985 ;; search-end and see if we can find a class key. watch for
986 ;; class like strings in literals
987 (save-excursion
988 (save-restriction
989 (goto-char search-start)
e1c458ae 990 (let ((search-key (concat c-class-key "\\|" c-extra-toplevel-key))
785eecbb 991 foundp class match-end)
0ec8351b
BW
992 (if c-inexpr-class-key
993 (setq search-key (concat search-key "\\|"
994 c-inexpr-class-key)))
785eecbb
RS
995 (while (and (not foundp)
996 (progn
997 (c-forward-syntactic-ws)
998 (> search-end (point)))
999 (re-search-forward search-key search-end t))
1000 (setq class (match-beginning 0)
1001 match-end (match-end 0))
1002 (if (c-in-literal search-start)
1003 nil ; its in a comment or string, ignore
1004 (goto-char class)
1005 (skip-chars-forward " \t\n")
1006 (setq foundp (vector (c-point 'boi) search-end))
1007 (cond
1008 ;; check for embedded keywords
1009 ((let ((char (char-after (1- class))))
1010 (and char
1011 (memq (char-syntax char) '(?w ?_))))
1012 (goto-char match-end)
1013 (setq foundp nil))
1014 ;; make sure we're really looking at the start of a
1015 ;; class definition, and not a forward decl, return
1016 ;; arg, template arg list, or an ObjC or Java method.
1017 ((and c-method-key
0ec8351b
BW
1018 (re-search-forward c-method-key search-end t)
1019 (not (c-in-literal class)))
785eecbb 1020 (setq foundp nil))
0ec8351b
BW
1021 ;; Check if this is an anonymous inner class.
1022 ((and c-inexpr-class-key
1023 (looking-at c-inexpr-class-key))
1024 (while (and (= (c-forward-token-1 1 t) 0)
1025 (looking-at "(\\|\\w\\|\\s_\\|\\.")))
1026 (if (eq (point) search-end)
1027 ;; We're done. Just trap this case in the cond.
1028 nil
1029 ;; False alarm; all conditions aren't satisfied.
1030 (setq foundp nil)))
785eecbb
RS
1031 ;; Its impossible to define a regexp for this, and
1032 ;; nearly so to do it programmatically.
1033 ;;
1034 ;; ; picks up forward decls
1035 ;; = picks up init lists
1036 ;; ) picks up return types
1037 ;; > picks up templates, but remember that we can
1038 ;; inherit from templates!
1039 ((let ((skipchars "^;=)"))
1040 ;; try to see if we found the `class' keyword
1041 ;; inside a template arg list
1042 (save-excursion
1043 (skip-chars-backward "^<>" search-start)
1044 (if (eq (char-before) ?<)
1045 (setq skipchars (concat skipchars ">"))))
0ec8351b
BW
1046 (while (progn
1047 (skip-chars-forward skipchars search-end)
1048 (c-in-literal class))
1049 (forward-char))
785eecbb
RS
1050 (/= (point) search-end))
1051 (setq foundp nil))
1052 )))
1053 foundp))
1054 )))))
1055
1056(defun c-inside-bracelist-p (containing-sexp brace-state)
1057 ;; return the buffer position of the beginning of the brace list
1058 ;; statement if we're inside a brace list, otherwise return nil.
1059 ;; CONTAINING-SEXP is the buffer pos of the innermost containing
1060 ;; paren. BRACE-STATE is the remainder of the state of enclosing braces
1061 ;;
1062 ;; N.B.: This algorithm can potentially get confused by cpp macros
1063 ;; places in inconvenient locations. Its a trade-off we make for
1064 ;; speed.
1065 (or
1066 ;; this will pick up enum lists
b2acd789
RS
1067 (c-safe
1068 (save-excursion
1069 (goto-char containing-sexp)
0ec8351b 1070 (c-forward-sexp -1)
b2acd789
RS
1071 (let (bracepos)
1072 (if (and (or (looking-at "enum[\t\n ]+")
0ec8351b 1073 (progn (c-forward-sexp -1)
b2acd789
RS
1074 (looking-at "enum[\t\n ]+")))
1075 (setq bracepos (c-safe (scan-lists (point) 1 -1)))
1076 (not (c-crosses-statement-barrier-p (point)
1077 (- bracepos 2))))
1078 (point)))))
785eecbb
RS
1079 ;; this will pick up array/aggregate init lists, even if they are nested.
1080 (save-excursion
0ec8351b
BW
1081 (let ((class-key
1082 ;; Pike can have class definitions anywhere, so we must
1083 ;; check for the class key here.
1084 (and (c-major-mode-is 'pike-mode)
1085 (concat c-class-key "\\|" c-extra-toplevel-key)))
1086 bufpos lim braceassignp)
785eecbb
RS
1087 (while (and (not bufpos)
1088 containing-sexp)
1089 (if (consp containing-sexp)
1090 (setq containing-sexp (car brace-state)
1091 brace-state (cdr brace-state))
785eecbb 1092 (goto-char containing-sexp)
0ec8351b
BW
1093 (if (c-looking-at-inexpr-block)
1094 ;; We're in an in-expression block of some kind. Do
1095 ;; not check nesting.
1096 (setq containing-sexp nil)
1097 ;; see if the open brace is preceded by = or [...] in
1098 ;; this statement, but watch out for operator=
1099 (setq lim (if (consp (car brace-state))
1100 (cdr (car brace-state))
1101 (car brace-state))
1102 braceassignp 'dontknow)
1103 (while (and (eq braceassignp 'dontknow)
1104 (zerop (c-backward-token-1 1 t lim)))
1105 (cond ((eq (char-after) ?\;)
1106 (setq braceassignp nil))
1107 ((and class-key
1108 (looking-at class-key))
1109 (setq braceassignp nil))
1110 ((eq (char-after) ?=)
1111 ;; We've seen a =, but must check earlier tokens so
1112 ;; that it isn't something that should be ignored.
1113 (setq braceassignp 'maybe)
1114 (while (and (eq braceassignp 'maybe)
1115 (zerop (c-backward-token-1 1 t lim)))
1116 (setq braceassignp
1117 (cond
1118 ;; Check for operator =
1119 ((looking-at "operator\\>") nil)
1120 ;; Check for `<opchar>= (Pike)
1121 ((eq (char-after) ?`) nil)
1122 ((looking-at "\\s.") 'maybe)
1123 ;; make sure we're not in a C++ template
1124 ;; argument assignment
1125 ((save-excursion
1126 (let ((here (point))
1127 (pos< (progn
1128 (skip-chars-backward "^<")
1129 (point))))
1130 (and (c-major-mode-is 'c++-mode)
1131 (eq (char-before) ?<)
1132 (not (c-crosses-statement-barrier-p
1133 here pos<))
1134 (not (c-in-literal))
1135 )))
1136 nil)
1137 (t t)))))
1138 ((eq (char-after) ?\[)
1139 ;; In Java, an initialization brace list may
1140 ;; follow "new Foo[]", so check for []. Got to
1141 ;; watch out for the C++ "operator[]" defun,
1142 ;; though.
1143 (setq braceassignp
1144 (save-excursion
1145 (c-backward-token-1)
1146 (not (looking-at "operator\\>")))))
1147 ))
1148 (if (memq braceassignp '(nil dontknow))
1149 (if (eq (char-after) ?\;)
1150 ;; Brace lists can't contain a semicolon, so we're done.
1151 (setq containing-sexp nil)
1152 ;; lets see if we're nested. find the most nested
1153 ;; containing brace
1154 (setq containing-sexp (car brace-state)
1155 brace-state (cdr brace-state)))
1156 ;; we've hit the beginning of the aggregate list
1157 (c-beginning-of-statement-1
1158 (c-most-enclosing-brace brace-state))
1159 (setq bufpos (point))))
785eecbb
RS
1160 ))
1161 bufpos))
1162 ))
1163
0ec8351b
BW
1164(defun c-looking-at-special-brace-list (&optional lim)
1165