(c-before-change): Fix BOB bug.
[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 14288.
CommitLineData
785eecbb
RS
1;;; cc-engine.el --- core syntax guessing engine for CC mode
2
92ab3834 3;; Copyright (C) 1985, 1987, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
d7a0267c
GM
4;; 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
5;; Free Software Foundation, Inc.
785eecbb 6
e309f66c
AM
7;; Authors: 2001- Alan Mackenzie
8;; 1998- Martin Stjernholm
d9e94c22 9;; 1992-1999 Barry A. Warsaw
785eecbb
RS
10;; 1987 Dave Detlefs and Stewart Clamen
11;; 1985 Richard M. Stallman
0ec8351b 12;; Maintainer: bug-cc-mode@gnu.org
785eecbb 13;; Created: 22-Apr-1997 (split from cc-mode.el)
6430c434 14;; Version: See cc-mode.el
785eecbb
RS
15;; Keywords: c languages oop
16
17;; This file is part of GNU Emacs.
18
19;; GNU Emacs is free software; you can redistribute it and/or modify
20;; it under the terms of the GNU General Public License as published by
21;; the Free Software Foundation; either version 2, or (at your option)
22;; any later version.
23
24;; GNU Emacs is distributed in the hope that it will be useful,
25;; but WITHOUT ANY WARRANTY; without even the implied warranty of
26;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27;; GNU General Public License for more details.
28
29;; You should have received a copy of the GNU General Public License
3efc2cd7
MS
30;; along with this program; see the file COPYING. If not, write to
31;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
32;; Boston, MA 02110-1301, USA.
785eecbb 33
3afbc435
PJ
34;;; Commentary:
35
a66cd3ee
MS
36;; The functions which have docstring documentation can be considered
37;; part of an API which other packages can use in CC Mode buffers.
38;; Otoh, undocumented functions and functions with the documentation
39;; in comments are considered purely internal and can change semantics
40;; or even disappear in the future.
41;;
42;; (This policy applies to CC Mode as a whole, not just this file. It
43;; probably also applies to many other Emacs packages, but here it's
44;; clearly spelled out.)
45
d9e94c22
MS
46;; Hidden buffer changes
47;;
48;; Various functions in CC Mode use text properties for caching and
49;; syntactic markup purposes, and those of them that might modify such
0386b551
AM
50;; properties but still don't modify the buffer in a visible way are
51;; said to do "hidden buffer changes". They should be used within
52;; `c-save-buffer-state' or a similar function that saves and restores
53;; buffer modifiedness, disables buffer change hooks, etc.
d9e94c22 54;;
0386b551
AM
55;; Interactive functions are assumed to not do hidden buffer changes,
56;; except in the specific parts of them that do real changes.
d9e94c22 57;;
0386b551
AM
58;; Lineup functions are assumed to do hidden buffer changes. They
59;; must not do real changes, though.
d9e94c22 60;;
0386b551
AM
61;; All other functions that do hidden buffer changes have that noted
62;; in their doc string or comment.
63;;
64;; The intention with this system is to avoid wrapping every leaf
65;; function that do hidden buffer changes inside
66;; `c-save-buffer-state'. It should be used as near the top of the
67;; interactive functions as possible.
68;;
69;; Functions called during font locking are allowed to do hidden
70;; buffer changes since the font-lock package run them in a context
71;; similar to `c-save-buffer-state' (in fact, that function is heavily
72;; inspired by `save-buffer-state' in the font-lock package).
d9e94c22
MS
73
74;; Use of text properties
75;;
76;; CC Mode uses several text properties internally to mark up various
77;; positions, e.g. to improve speed and to eliminate glitches in
78;; interactive refontification.
79;;
7bfc3fdb
MS
80;; Note: This doc is for internal use only. Other packages should not
81;; assume that these text properties are used as described here.
82;;
d9e94c22
MS
83;; 'syntax-table
84;; Used to modify the syntax of some characters. Currently used to
85;; mark the "<" and ">" of angle bracket parens with paren syntax.
86;;
87;; This property is used on single characters and is therefore
88;; always treated as front and rear nonsticky (or start and end open
89;; in XEmacs vocabulary). It's therefore installed on
90;; `text-property-default-nonsticky' if that variable exists (Emacs
91;; >= 21).
92;;
93;; 'c-is-sws and 'c-in-sws
94;; Used by `c-forward-syntactic-ws' and `c-backward-syntactic-ws' to
95;; speed them up. See the comment blurb before `c-put-is-sws'
96;; below for further details.
97;;
98;; 'c-type
99;; This property is used on single characters to mark positions with
0386b551
AM
100;; special syntactic relevance of various sorts. Its primary use is
101;; to avoid glitches when multiline constructs are refontified
d9e94c22
MS
102;; interactively (on font lock decoration level 3). It's cleared in
103;; a region before it's fontified and is then put on relevant chars
104;; in that region as they are encountered during the fontification.
105;; The value specifies the kind of position:
106;;
107;; 'c-decl-arg-start
108;; Put on the last char of the token preceding each declaration
109;; inside a declaration style arglist (typically in a function
110;; prototype).
111;;
112;; 'c-decl-end
113;; Put on the last char of the token preceding a declaration.
114;; This is used in cases where declaration boundaries can't be
115;; recognized simply by looking for a token like ";" or "}".
116;; `c-type-decl-end-used' must be set if this is used (see also
117;; `c-find-decl-spots').
118;;
119;; 'c-<>-arg-sep
120;; Put on the commas that separate arguments in angle bracket
121;; arglists like C++ template arglists.
122;;
123;; 'c-decl-id-start and 'c-decl-type-start
124;; Put on the last char of the token preceding each declarator
125;; in the declarator list of a declaration. They are also used
126;; between the identifiers cases like enum declarations.
127;; 'c-decl-type-start is used when the declarators are types,
128;; 'c-decl-id-start otherwise.
129;;
130;; 'c-awk-NL-prop
131;; Used in AWK mode to mark the various kinds of newlines. See
132;; cc-awk.el.
133
3afbc435
PJ
134;;; Code:
135
0ec8351b 136(eval-when-compile
51f606de 137 (let ((load-path
130c507e
GM
138 (if (and (boundp 'byte-compile-dest-file)
139 (stringp byte-compile-dest-file))
140 (cons (file-name-directory byte-compile-dest-file) load-path)
51f606de 141 load-path)))
d9e94c22 142 (load "cc-bytecomp" nil t)))
130c507e
GM
143
144(cc-require 'cc-defs)
d9e94c22 145(cc-require-when-compile 'cc-langs)
130c507e 146(cc-require 'cc-vars)
d9e94c22 147
130c507e
GM
148;; Silence the compiler.
149(cc-bytecomp-defun buffer-syntactic-context) ; XEmacs
0ec8351b 150
51f606de 151\f
d9e94c22
MS
152;; Make declarations for all the `c-lang-defvar' variables in cc-langs.
153
154(defmacro c-declare-lang-variables ()
155 `(progn
485fe977
RS
156 ,@(apply 'nconc
157 (mapcar (lambda (init)
158 `(,(if (elt init 2)
159 `(defvar ,(car init) nil ,(elt init 2))
160 `(defvar ,(car init) nil))
161 (make-variable-buffer-local ',(car init))))
162 (cdr c-lang-variable-inits)))))
d9e94c22
MS
163(c-declare-lang-variables)
164
165\f
166;;; Internal state variables.
167
168;; Internal state of hungry delete key feature
169(defvar c-hungry-delete-key nil)
170(make-variable-buffer-local 'c-hungry-delete-key)
171
0386b551
AM
172;; The electric flag (toggled by `c-toggle-electric-state').
173;; If t, electric actions (like automatic reindentation, and (if
174;; c-auto-newline is also set) auto newlining) will happen when an electric
175;; key like `{' is pressed (or an electric keyword like `else').
176(defvar c-electric-flag t)
177(make-variable-buffer-local 'c-electric-flag)
178
d9e94c22
MS
179;; Internal state of auto newline feature.
180(defvar c-auto-newline nil)
181(make-variable-buffer-local 'c-auto-newline)
182
0386b551 183;; Included in the mode line to indicate the active submodes.
cb694ab7
AM
184;; (defvar c-submode-indicators nil)
185;; (make-variable-buffer-local 'c-submode-indicators)
d9e94c22 186
a66cd3ee
MS
187(defun c-calculate-state (arg prevstate)
188 ;; Calculate the new state of PREVSTATE, t or nil, based on arg. If
189 ;; arg is nil or zero, toggle the state. If arg is negative, turn
190 ;; the state off, and if arg is positive, turn the state on
191 (if (or (not arg)
192 (zerop (setq arg (prefix-numeric-value arg))))
193 (not prevstate)
194 (> arg 0)))
195
d9e94c22 196;; Dynamically bound cache for `c-in-literal'.
130c507e 197(defvar c-in-literal-cache t)
d9e94c22 198
d9e94c22 199\f
037558bf
MS
200;; Basic handling of preprocessor directives.
201
202;; This is a dynamically bound cache used together with
203;; `c-query-macro-start' and `c-query-and-set-macro-start'. It only
204;; works as long as point doesn't cross a macro boundary.
205(defvar c-macro-start 'unknown)
206
207(defsubst c-query-and-set-macro-start ()
037558bf
MS
208 (if (symbolp c-macro-start)
209 (setq c-macro-start (save-excursion
0386b551
AM
210 (c-save-buffer-state ()
211 (and (c-beginning-of-macro)
212 (point)))))
037558bf
MS
213 c-macro-start))
214
215(defsubst c-query-macro-start ()
037558bf
MS
216 (if (symbolp c-macro-start)
217 (save-excursion
0386b551
AM
218 (c-save-buffer-state ()
219 (and (c-beginning-of-macro)
220 (point))))
037558bf
MS
221 c-macro-start))
222
223(defun c-beginning-of-macro (&optional lim)
224 "Go to the beginning of a preprocessor directive.
225Leave point at the beginning of the directive and return t if in one,
226otherwise return nil and leave point unchanged.
227
0386b551
AM
228Note that this function might do hidden buffer changes. See the
229comment at the start of cc-engine.el for more info."
037558bf
MS
230 (when c-opt-cpp-prefix
231 (let ((here (point)))
232 (save-restriction
233 (if lim (narrow-to-region lim (point-max)))
234 (beginning-of-line)
235 (while (eq (char-before (1- (point))) ?\\)
236 (forward-line -1))
237 (back-to-indentation)
238 (if (and (<= (point) here)
239 (looking-at c-opt-cpp-start))
240 t
241 (goto-char here)
242 nil)))))
243
244(defun c-end-of-macro ()
245 "Go to the end of a preprocessor directive.
0386b551
AM
246More accurately, move the point to the end of the closest following
247line that doesn't end with a line continuation backslash - no check is
248done that the point is inside a cpp directive to begin with.
037558bf 249
0386b551
AM
250Note that this function might do hidden buffer changes. See the
251comment at the start of cc-engine.el for more info."
037558bf
MS
252 (while (progn
253 (end-of-line)
254 (when (and (eq (char-before) ?\\)
255 (not (eobp)))
256 (forward-char)
257 t))))
258
51c9af45
AM
259(defun c-forward-over-cpp-define-id ()
260 ;; Assuming point is at the "#" that introduces a preprocessor
261 ;; directive, it's moved forward to the end of the identifier which is
262 ;; "#define"d (or whatever c-opt-cpp-macro-define specifies). Non-nil
263 ;; is returned in this case, in all other cases nil is returned and
264 ;; point isn't moved.
265 ;;
266 ;; This function might do hidden buffer changes.
267 (when (and c-opt-cpp-macro-define-id
268 (looking-at c-opt-cpp-macro-define-id))
269 (goto-char (match-end 0))))
270
037558bf
MS
271(defun c-forward-to-cpp-define-body ()
272 ;; Assuming point is at the "#" that introduces a preprocessor
273 ;; directive, it's moved forward to the start of the definition body
0386b551
AM
274 ;; if it's a "#define" (or whatever c-opt-cpp-macro-define
275 ;; specifies). Non-nil is returned in this case, in all other cases
276 ;; nil is returned and point isn't moved.
277 ;;
278 ;; This function might do hidden buffer changes.
279 (when (and c-opt-cpp-macro-define-start
280 (looking-at c-opt-cpp-macro-define-start)
037558bf
MS
281 (not (= (match-end 0) (c-point 'eol))))
282 (goto-char (match-end 0))))
283
284\f
d9e94c22
MS
285;;; Basic utility functions.
286
0386b551 287(defun c-syntactic-content (from to paren-level)
d9e94c22
MS
288 ;; Return the given region as a string where all syntactic
289 ;; whitespace is removed or, where necessary, replaced with a single
0386b551
AM
290 ;; space. If PAREN-LEVEL is given then all parens in the region are
291 ;; collapsed to "()", "[]" etc.
292 ;;
293 ;; This function might do hidden buffer changes.
294
d9e94c22 295 (save-excursion
0386b551
AM
296 (save-restriction
297 (narrow-to-region from to)
298 (goto-char from)
299 (let* ((parts (list nil)) (tail parts) pos in-paren)
300
301 (while (re-search-forward c-syntactic-ws-start to t)
302 (goto-char (setq pos (match-beginning 0)))
303 (c-forward-syntactic-ws)
304 (if (= (point) pos)
305 (forward-char)
306
307 (when paren-level
308 (save-excursion
309 (setq in-paren (= (car (parse-partial-sexp from pos 1)) 1)
310 pos (point))))
311
312 (if (and (> pos from)
313 (< (point) to)
314 (looking-at "\\w\\|\\s_")
315 (save-excursion
316 (goto-char (1- pos))
317 (looking-at "\\w\\|\\s_")))
318 (progn
319 (setcdr tail (list (buffer-substring-no-properties from pos)
320 " "))
321 (setq tail (cddr tail)))
322 (setcdr tail (list (buffer-substring-no-properties from pos)))
323 (setq tail (cdr tail)))
324
325 (when in-paren
326 (when (= (car (parse-partial-sexp pos to -1)) -1)
327 (setcdr tail (list (buffer-substring-no-properties
328 (1- (point)) (point))))
329 (setq tail (cdr tail))))
330
331 (setq from (point))))
332
333 (setcdr tail (list (buffer-substring-no-properties from to)))
334 (apply 'concat (cdr parts))))))
335
336(defun c-shift-line-indentation (shift-amt)
337 ;; Shift the indentation of the current line with the specified
338 ;; amount (positive inwards). The buffer is modified only if
339 ;; SHIFT-AMT isn't equal to zero.
340 (let ((pos (- (point-max) (point)))
341 (c-macro-start c-macro-start)
342 tmp-char-inserted)
343 (if (zerop shift-amt)
344 nil
345 ;; If we're on an empty line inside a macro, we take the point
346 ;; to be at the current indentation and shift it to the
347 ;; appropriate column. This way we don't treat the extra
348 ;; whitespace out to the line continuation as indentation.
349 (when (and (c-query-and-set-macro-start)
350 (looking-at "[ \t]*\\\\$")
351 (save-excursion
352 (skip-chars-backward " \t")
353 (bolp)))
354 (insert ?x)
355 (backward-char)
356 (setq tmp-char-inserted t))
357 (unwind-protect
358 (let ((col (current-indentation)))
359 (delete-region (c-point 'bol) (c-point 'boi))
360 (beginning-of-line)
361 (indent-to (+ col shift-amt)))
362 (when tmp-char-inserted
363 (delete-char 1))))
364 ;; If initial point was within line's indentation and we're not on
365 ;; a line with a line continuation in a macro, position after the
366 ;; indentation. Else stay at same point in text.
367 (if (and (< (point) (c-point 'boi))
368 (not tmp-char-inserted))
369 (back-to-indentation)
370 (if (> (- (point-max) pos) (point))
371 (goto-char (- (point-max) pos))))))
d9e94c22
MS
372
373(defsubst c-keyword-sym (keyword)
374 ;; Return non-nil if the string KEYWORD is a known keyword. More
375 ;; precisely, the value is the symbol for the keyword in
376 ;; `c-keywords-obarray'.
377 (intern-soft keyword c-keywords-obarray))
378
379(defsubst c-keyword-member (keyword-sym lang-constant)
380 ;; Return non-nil if the symbol KEYWORD-SYM, as returned by
381 ;; `c-keyword-sym', is a member of LANG-CONSTANT, which is the name
382 ;; of a language constant that ends with "-kwds". If KEYWORD-SYM is
383 ;; nil then the result is nil.
384 (get keyword-sym lang-constant))
385
386;; String syntax chars, suitable for skip-syntax-(forward|backward).
387(defconst c-string-syntax (if (memq 'gen-string-delim c-emacs-features)
388 "\"|"
389 "\""))
390
0386b551 391;; Regexp matching string limit syntax.
d9e94c22
MS
392(defconst c-string-limit-regexp (if (memq 'gen-string-delim c-emacs-features)
393 "\\s\"\\|\\s|"
394 "\\s\""))
395
0386b551
AM
396;; Regexp matching WS followed by string limit syntax.
397(defconst c-ws*-string-limit-regexp
398 (concat "[ \t]*\\(" c-string-limit-regexp "\\)"))
399
d9e94c22
MS
400;; Holds formatted error strings for the few cases where parse errors
401;; are reported.
a66cd3ee 402(defvar c-parsing-error nil)
d9e94c22
MS
403(make-variable-buffer-local 'c-parsing-error)
404
405(defun c-echo-parsing-error (&optional quiet)
d9e94c22
MS
406 (when (and c-report-syntactic-errors c-parsing-error (not quiet))
407 (c-benign-error "%s" c-parsing-error))
408 c-parsing-error)
409
410;; Faces given to comments and string literals. This is used in some
411;; situations to speed up recognition; it isn't mandatory that font
412;; locking is in use. This variable is extended with the face in
413;; `c-doc-face-name' when fontification is activated in cc-fonts.el.
1e330469 414(defvar c-literal-faces
0386b551
AM
415 (append '(font-lock-comment-face font-lock-string-face)
416 (when (facep 'font-lock-comment-delimiter-face)
417 ;; New in Emacs 22.
418 '(font-lock-comment-delimiter-face))))
419
420(defsubst c-put-c-type-property (pos value)
421 ;; Put a c-type property with the given value at POS.
422 (c-put-char-property pos 'c-type value))
423
424(defun c-clear-c-type-property (from to value)
425 ;; Remove all occurences of the c-type property that has the given
426 ;; value in the region between FROM and TO. VALUE is assumed to not
427 ;; be nil.
428 ;;
429 ;; Note: This assumes that c-type is put on single chars only; it's
430 ;; very inefficient if matching properties cover large regions.
431 (save-excursion
432 (goto-char from)
433 (while (progn
434 (when (eq (get-text-property (point) 'c-type) value)
435 (c-clear-char-property (point) 'c-type))
436 (goto-char (next-single-property-change (point) 'c-type nil to))
437 (< (point) to)))))
037558bf 438
d9e94c22
MS
439\f
440;; Some debug tools to visualize various special positions. This
441;; debug code isn't as portable as the rest of CC Mode.
442
443(cc-bytecomp-defun overlays-in)
444(cc-bytecomp-defun overlay-get)
445(cc-bytecomp-defun overlay-start)
446(cc-bytecomp-defun overlay-end)
447(cc-bytecomp-defun delete-overlay)
448(cc-bytecomp-defun overlay-put)
449(cc-bytecomp-defun make-overlay)
450
451(defun c-debug-add-face (beg end face)
452 (c-save-buffer-state ((overlays (overlays-in beg end)) overlay)
453 (while overlays
454 (setq overlay (car overlays)
455 overlays (cdr overlays))
456 (when (eq (overlay-get overlay 'face) face)
457 (setq beg (min beg (overlay-start overlay))
458 end (max end (overlay-end overlay)))
459 (delete-overlay overlay)))
460 (overlay-put (make-overlay beg end) 'face face)))
461
462(defun c-debug-remove-face (beg end face)
463 (c-save-buffer-state ((overlays (overlays-in beg end)) overlay
464 (ol-beg beg) (ol-end end))
465 (while overlays
466 (setq overlay (car overlays)
467 overlays (cdr overlays))
468 (when (eq (overlay-get overlay 'face) face)
469 (setq ol-beg (min ol-beg (overlay-start overlay))
470 ol-end (max ol-end (overlay-end overlay)))
471 (delete-overlay overlay)))
472 (when (< ol-beg beg)
473 (overlay-put (make-overlay ol-beg beg) 'face face))
474 (when (> ol-end end)
475 (overlay-put (make-overlay end ol-end) 'face face))))
476
477\f
478;; `c-beginning-of-statement-1' and accompanying stuff.
130c507e 479
64001211
RS
480;; KLUDGE ALERT: c-maybe-labelp is used to pass information between
481;; c-crosses-statement-barrier-p and c-beginning-of-statement-1. A
482;; better way should be implemented, but this will at least shut up
483;; the byte compiler.
0386b551 484(defvar c-maybe-labelp)
64001211 485
d9e94c22
MS
486;; New awk-compatible version of c-beginning-of-statement-1, ACM 2002/6/22
487
a66cd3ee
MS
488;; Macros used internally in c-beginning-of-statement-1 for the
489;; automaton actions.
490(defmacro c-bos-push-state ()
491 '(setq stack (cons (cons state saved-pos)
492 stack)))
493(defmacro c-bos-pop-state (&optional do-if-done)
494 `(if (setq state (car (car stack))
495 saved-pos (cdr (car stack))
496 stack (cdr stack))
497 t
498 ,do-if-done
499 (throw 'loop nil)))
500(defmacro c-bos-pop-state-and-retry ()
501 '(throw 'loop (setq state (car (car stack))
502 saved-pos (cdr (car stack))
503 ;; Throw nil if stack is empty, else throw non-nil.
504 stack (cdr stack))))
505(defmacro c-bos-save-pos ()
506 '(setq saved-pos (vector pos tok ptok pptok)))
507(defmacro c-bos-restore-pos ()
508 '(unless (eq (elt saved-pos 0) start)
509 (setq pos (elt saved-pos 0)
510 tok (elt saved-pos 1)
511 ptok (elt saved-pos 2)
512 pptok (elt saved-pos 3))
513 (goto-char pos)
514 (setq sym nil)))
515(defmacro c-bos-save-error-info (missing got)
516 `(setq saved-pos (vector pos ,missing ,got)))
517(defmacro c-bos-report-error ()
518 '(unless noerror
519 (setq c-parsing-error
520 (format "No matching `%s' found for `%s' on line %d"
521 (elt saved-pos 1)
522 (elt saved-pos 2)
523 (1+ (count-lines (point-min)
524 (c-point 'bol (elt saved-pos 0))))))))
525
526(defun c-beginning-of-statement-1 (&optional lim ignore-labels
527 noerror comma-delim)
528 "Move to the start of the current statement or declaration, or to
529the previous one if already at the beginning of one. Only
530statements/declarations on the same level are considered, i.e. don't
531move into or out of sexps (not even normal expression parentheses).
532
d9e94c22
MS
533Stop at statement continuation tokens like \"else\", \"catch\",
534\"finally\" and the \"while\" in \"do ... while\" if the start point
535is within the continuation. If starting at such a token, move to the
536corresponding statement start. If at the beginning of a statement,
537move to the closest containing statement if there is any. This might
538also stop at a continuation clause.
a66cd3ee 539
0386b551
AM
540Labels are treated as part of the following statements if
541IGNORE-LABELS is non-nil. (FIXME: Doesn't work if we stop at a known
cb694ab7
AM
542statement start keyword.) Otherwise, each label is treated as a
543separate statement.
a66cd3ee 544
cb694ab7
AM
545Macros are ignored \(i.e. skipped over) unless point is within one, in
546which case the content of the macro is treated as normal code. Aside
547from any normal statement starts found in it, stop at the first token
548of the content in the macro, i.e. the expression of an \"#if\" or the
549start of the definition in a \"#define\". Also stop at start of
550macros before leaving them.
a66cd3ee
MS
551
552Return 'label if stopped at a label, 'same if stopped at the beginning
553of the current statement, 'up if stepped to a containing statement,
554'previous if stepped to a preceding statement, 'beginning if stepped
555from a statement continuation clause to its start clause, or 'macro if
556stepped to a macro start. Note that 'same and not 'label is returned
557if stopped at the same label without crossing the colon character.
558
559LIM may be given to limit the search. If the search hits the limit,
560point will be left at the closest following token, or at the start
561position if that is less ('same is returned in this case).
562
563NOERROR turns off error logging to `c-parsing-error'.
564
cb694ab7
AM
565Normally only ';' and virtual semicolons are considered to delimit
566statements, but if COMMA-DELIM is non-nil then ',' is treated
567as a delimiter too.
0386b551
AM
568
569Note that this function might do hidden buffer changes. See the
570comment at the start of cc-engine.el for more info."
a66cd3ee 571
d9e94c22
MS
572 ;; The bulk of this function is a pushdown automaton that looks at statement
573 ;; boundaries and the tokens (such as "while") in c-opt-block-stmt-key. Its
574 ;; purpose is to keep track of nested statements, ensuring that such
575 ;; statments are skipped over in their entirety (somewhat akin to what C-M-p
576 ;; does with nested braces/brackets/parentheses).
a66cd3ee
MS
577 ;;
578 ;; Note: The position of a boundary is the following token.
579 ;;
d9e94c22
MS
580 ;; Beginning with the current token (the one following point), move back one
581 ;; sexp at a time (where a sexp is, more or less, either a token or the
582 ;; entire contents of a brace/bracket/paren pair). Each time a statement
583 ;; boundary is crossed or a "while"-like token is found, update the state of
584 ;; the PDA. Stop at the beginning of a statement when the stack (holding
585 ;; nested statement info) is empty and the position has been moved.
586 ;;
587 ;; The following variables constitute the PDA:
588 ;;
589 ;; sym: This is either the "while"-like token (e.g. 'for) we've just
590 ;; scanned back over, 'boundary if we've just gone back over a
591 ;; statement boundary, or nil otherwise.
592 ;; state: takes one of the values (nil else else-boundary while
593 ;; while-boundary catch catch-boundary).
594 ;; nil means "no "while"-like token yet scanned".
595 ;; 'else, for example, means "just gone back over an else".
596 ;; 'else-boundary means "just gone back over a statement boundary
597 ;; immediately after having gone back over an else".
598 ;; saved-pos: A vector of either saved positions (tok ptok pptok, etc.) or
599 ;; of error reporting information.
600 ;; stack: The stack onto which the PDA pushes its state. Each entry
601 ;; consists of a saved value of state and saved-pos. An entry is
602 ;; pushed when we move back over a "continuation" token (e.g. else)
603 ;; and popped when we encounter the corresponding opening token
604 ;; (e.g. if).
605 ;;
606 ;;
607 ;; The following diagram briefly outlines the PDA.
a66cd3ee
MS
608 ;;
609 ;; Common state:
d9e94c22
MS
610 ;; "else": Push state, goto state `else'.
611 ;; "while": Push state, goto state `while'.
612 ;; "catch" or "finally": Push state, goto state `catch'.
613 ;; boundary: Pop state.
a66cd3ee
MS
614 ;; other: Do nothing special.
615 ;;
d9e94c22
MS
616 ;; State `else':
617 ;; boundary: Goto state `else-boundary'.
618 ;; other: Error, pop state, retry token.
619 ;;
620 ;; State `else-boundary':
621 ;; "if": Pop state.
622 ;; boundary: Error, pop state.
623 ;; other: See common state.
624 ;;
625 ;; State `while':
626 ;; boundary: Save position, goto state `while-boundary'.
627 ;; other: Pop state, retry token.
628 ;;
629 ;; State `while-boundary':
630 ;; "do": Pop state.
631 ;; boundary: Restore position if it's not at start, pop state. [*see below]
632 ;; other: See common state.
633 ;;
634 ;; State `catch':
635 ;; boundary: Goto state `catch-boundary'.
636 ;; other: Error, pop state, retry token.
637 ;;
638 ;; State `catch-boundary':
639 ;; "try": Pop state.
640 ;; "catch": Goto state `catch'.
641 ;; boundary: Error, pop state.
642 ;; other: See common state.
643 ;;
644 ;; [*] In the `while-boundary' state, we had pushed a 'while state, and were
645 ;; searching for a "do" which would have opened a do-while. If we didn't
646 ;; find it, we discard the analysis done since the "while", go back to this
647 ;; token in the buffer and restart the scanning there, this time WITHOUT
648 ;; pushing the 'while state onto the stack.
649 ;;
a66cd3ee
MS
650 ;; In addition to the above there is some special handling of labels
651 ;; and macros.
652
653 (let ((case-fold-search nil)
654 (start (point))
655 macro-start
656 (delims (if comma-delim '(?\; ?,) '(?\;)))
657 (c-stmt-delim-chars (if comma-delim
658 c-stmt-delim-chars-with-comma
659 c-stmt-delim-chars))
0386b551
AM
660 c-in-literal-cache c-maybe-labelp saved
661 ;; Current position.
662 pos
663 ;; Position of last stmt boundary character (e.g. ;).
664 boundary-pos
665 ;; The position of the last sexp or bound that follows the
666 ;; first found colon, i.e. the start of the nonlabel part of
667 ;; the statement. It's `start' if a colon is found just after
668 ;; the start.
669 after-labels-pos
670 ;; Like `after-labels-pos', but the first such position inside
671 ;; a label, i.e. the start of the last label before the start
672 ;; of the nonlabel part of the statement.
673 last-label-pos
674 ;; The last position where a label is possible provided the
675 ;; statement started there. It's nil as long as no invalid
676 ;; label content has been found (according to
677 ;; `c-nonlabel-token-key'. It's `start' if no valid label
678 ;; content was found in the label. Note that we might still
679 ;; regard it a label if it starts with `c-label-kwds'.
680 label-good-pos
681 ;; Symbol just scanned back over (e.g. 'while or 'boundary).
682 ;; See above.
683 sym
684 ;; Current state in the automaton. See above.
685 state
686 ;; Current saved positions. See above.
687 saved-pos
688 ;; Stack of conses (state . saved-pos).
689 stack
690 ;; Regexp which matches "for", "if", etc.
691 (cond-key (or c-opt-block-stmt-key
a66cd3ee 692 "\\<\\>")) ; Matches nothing.
0386b551
AM
693 ;; Return value.
694 (ret 'same)
695 ;; Positions of the last three sexps or bounds we've stopped at.
696 tok ptok pptok)
a66cd3ee
MS
697
698 (save-restriction
699 (if lim (narrow-to-region lim (point-max)))
700
701 (if (save-excursion
702 (and (c-beginning-of-macro)
703 (/= (point) start)))
704 (setq macro-start (point)))
705
d9e94c22 706 ;; Try to skip back over unary operator characters, to register
a66cd3ee
MS
707 ;; that we've moved.
708 (while (progn
709 (setq pos (point))
0386b551
AM
710 (c-backward-syntactic-ws)
711 ;; Protect post-++/-- operators just before a virtual semicolon.
712 (and (not (c-at-vsemi-p))
713 (/= (skip-chars-backward "-+!*&~@`#") 0))))
d9e94c22
MS
714
715 ;; Skip back over any semicolon here. If it was a bare semicolon, we're
0386b551 716 ;; done. Later on we ignore the boundaries for statements that don't
d9e94c22
MS
717 ;; contain any sexp. The only thing that is affected is that the error
718 ;; checking is a little less strict, and we really don't bother.
a66cd3ee
MS
719 (if (and (memq (char-before) delims)
720 (progn (forward-char -1)
721 (setq saved (point))
0386b551 722 (c-backward-syntactic-ws)
a66cd3ee
MS
723 (or (memq (char-before) delims)
724 (memq (char-before) '(?: nil))
d9e94c22 725 (eq (char-syntax (char-before)) ?\()
0386b551 726 (c-at-vsemi-p))))
a66cd3ee
MS
727 (setq ret 'previous
728 pos saved)
729
730 ;; Begin at start and not pos to detect macros if we stand
731 ;; directly after the #.
732 (goto-char start)
733 (if (looking-at "\\<\\|\\W")
734 ;; Record this as the first token if not starting inside it.
735 (setq tok start))
736
d9e94c22
MS
737 ;; The following while loop goes back one sexp (balanced parens,
738 ;; etc. with contents, or symbol or suchlike) each iteration. This
739 ;; movement is accomplished with a call to scan-sexps approx 130 lines
740 ;; below.
a66cd3ee
MS
741 (while
742 (catch 'loop ;; Throw nil to break, non-nil to continue.
743 (cond
a66cd3ee 744 ((save-excursion
0386b551 745 (and macro-start ; Always NIL for AWK.
a66cd3ee
MS
746 (progn (skip-chars-backward " \t")
747 (eq (char-before) ?#))
748 (progn (setq saved (1- (point)))
749 (beginning-of-line)
750 (not (eq (char-before (1- (point))) ?\\)))
d9e94c22 751 (looking-at c-opt-cpp-start)
a66cd3ee
MS
752 (progn (skip-chars-forward " \t")
753 (eq (point) saved))))
754 (goto-char saved)
755 (if (and (c-forward-to-cpp-define-body)
756 (progn (c-forward-syntactic-ws start)
757 (< (point) start)))
758 ;; Stop at the first token in the content of the macro.
759 (setq pos (point)
760 ignore-labels t) ; Avoid the label check on exit.
761 (setq pos saved
762 ret 'macro
763 ignore-labels t))
764 (throw 'loop nil))
765
d9e94c22
MS
766 ;; Do a round through the automaton if we've just passed a
767 ;; statement boundary or passed a "while"-like token.
a66cd3ee
MS
768 ((or sym
769 (and (looking-at cond-key)
770 (setq sym (intern (match-string 1)))))
771
772 (when (and (< pos start) (null stack))
773 (throw 'loop nil))
774
d9e94c22
MS
775 ;; The PDA state handling.
776 ;;
037558bf 777 ;; Refer to the description of the PDA in the opening
d9e94c22
MS
778 ;; comments. In the following OR form, the first leaf
779 ;; attempts to handles one of the specific actions detailed
780 ;; (e.g., finding token "if" whilst in state `else-boundary').
781 ;; We drop through to the second leaf (which handles common
782 ;; state) if no specific handler is found in the first cond.
783 ;; If a parsing error is detected (e.g. an "else" with no
784 ;; preceding "if"), we throw to the enclosing catch.
785 ;;
786 ;; Note that the (eq state 'else) means
787 ;; "we've just passed an else", NOT "we're looking for an
788 ;; else".
a66cd3ee
MS
789 (or (cond
790 ((eq state 'else)
791 (if (eq sym 'boundary)
792 (setq state 'else-boundary)
793 (c-bos-report-error)
794 (c-bos-pop-state-and-retry)))
795
796 ((eq state 'else-boundary)
797 (cond ((eq sym 'if)
798 (c-bos-pop-state (setq ret 'beginning)))
799 ((eq sym 'boundary)
800 (c-bos-report-error)
801 (c-bos-pop-state))))
802
803 ((eq state 'while)
804 (if (and (eq sym 'boundary)
805 ;; Since this can cause backtracking we do a
806 ;; little more careful analysis to avoid it:
807 ;; If there's a label in front of the while
808 ;; it can't be part of a do-while.
809 (not after-labels-pos))
810 (progn (c-bos-save-pos)
811 (setq state 'while-boundary))
d9e94c22 812 (c-bos-pop-state-and-retry))) ; Can't be a do-while
a66cd3ee
MS
813
814 ((eq state 'while-boundary)
815 (cond ((eq sym 'do)
816 (c-bos-pop-state (setq ret 'beginning)))
d9e94c22
MS
817 ((eq sym 'boundary) ; isn't a do-while
818 (c-bos-restore-pos) ; the position of the while
819 (c-bos-pop-state)))) ; no longer searching for do.
a66cd3ee
MS
820
821 ((eq state 'catch)
822 (if (eq sym 'boundary)
823 (setq state 'catch-boundary)
824 (c-bos-report-error)
825 (c-bos-pop-state-and-retry)))
826
827 ((eq state 'catch-boundary)
828 (cond
829 ((eq sym 'try)
830 (c-bos-pop-state (setq ret 'beginning)))
831 ((eq sym 'catch)
832 (setq state 'catch))
833 ((eq sym 'boundary)
834 (c-bos-report-error)
835 (c-bos-pop-state)))))
836
d9e94c22
MS
837 ;; This is state common. We get here when the previous
838 ;; cond statement found no particular state handler.
a66cd3ee 839 (cond ((eq sym 'boundary)
d9e94c22
MS
840 ;; If we have a boundary at the start
841 ;; position we push a frame to go to the
842 ;; previous statement.
843 (if (>= pos start)
844 (c-bos-push-state)
845 (c-bos-pop-state)))
a66cd3ee
MS
846 ((eq sym 'else)
847 (c-bos-push-state)
848 (c-bos-save-error-info 'if 'else)
849 (setq state 'else))
850 ((eq sym 'while)
0386b551
AM
851 ;; Is this a real while, or a do-while?
852 ;; The next `when' triggers unless we are SURE that
853 ;; the `while' is not the tailend of a `do-while'.
a66cd3ee 854 (when (or (not pptok)
d9e94c22 855 (memq (char-after pptok) delims)
0386b551
AM
856 ;; The following kludge is to prevent
857 ;; infinite recursion when called from
858 ;; c-awk-after-if-for-while-condition-p,
859 ;; or the like.
860 (and (eq (point) start)
861 (c-vsemi-status-unknown-p))
862 (c-at-vsemi-p pptok))
a66cd3ee
MS
863 ;; Since this can cause backtracking we do a
864 ;; little more careful analysis to avoid it: If
0386b551
AM
865 ;; the while isn't followed by a (possibly
866 ;; virtual) semicolon it can't be a do-while.
a66cd3ee
MS
867 (c-bos-push-state)
868 (setq state 'while)))
869 ((memq sym '(catch finally))
870 (c-bos-push-state)
871 (c-bos-save-error-info 'try sym)
872 (setq state 'catch))))
873
874 (when c-maybe-labelp
875 ;; We're either past a statement boundary or at the
876 ;; start of a statement, so throw away any label data
877 ;; for the previous one.
878 (setq after-labels-pos nil
879 last-label-pos nil
880 c-maybe-labelp nil))))
881
d9e94c22
MS
882 ;; Step to the previous sexp, but not if we crossed a
883 ;; boundary, since that doesn't consume an sexp.
a66cd3ee
MS
884 (if (eq sym 'boundary)
885 (setq ret 'previous)
d9e94c22
MS
886
887 ;; HERE IS THE SINGLE PLACE INSIDE THE PDA LOOP WHERE WE MOVE
0386b551
AM
888 ;; BACKWARDS THROUGH THE SOURCE.
889
890 ;; This is typically fast with the caching done by
891 ;; c-(backward|forward)-sws.
892 (c-backward-syntactic-ws)
893
894 (let ((before-sws-pos (point))
895 ;; Set as long as we have to continue jumping by sexps.
896 ;; It's the position to use as end in the next round.
897 sexp-loop-continue-pos
898 ;; The end position of the area to search for statement
899 ;; barriers in this round.
900 (sexp-loop-end-pos pos))
901
cb694ab7 902 ;; The following while goes back one sexp per iteration.
0386b551
AM
903 (while
904 (progn
905 (unless (c-safe (c-backward-sexp) t)
906 ;; Give up if we hit an unbalanced block. Since the
907 ;; stack won't be empty the code below will report a
908 ;; suitable error.
a66cd3ee 909 (throw 'loop nil))
0386b551
AM
910
911 ;; Check if the sexp movement crossed a statement or
912 ;; declaration boundary. But first modify the point
913 ;; so that `c-crosses-statement-barrier-p' only looks
914 ;; at the non-sexp chars following the sexp.
915 (save-excursion
916 (when (setq
917 boundary-pos
918 (cond
919 ((if macro-start
920 nil
921 (save-excursion
922 (when (c-beginning-of-macro)
923 ;; Set continuation position in case
924 ;; `c-crosses-statement-barrier-p'
925 ;; doesn't detect anything below.
926 (setq sexp-loop-continue-pos (point)))))
927 ;; If the sexp movement took us into a
928 ;; macro then there were only some non-sexp
929 ;; chars after it. Skip out of the macro
930 ;; to analyze them but not the non-sexp
931 ;; chars that might be inside the macro.
932 (c-end-of-macro)
933 (c-crosses-statement-barrier-p
934 (point) sexp-loop-end-pos))
935
936 ((and
937 (eq (char-after) ?{)
938 (not (c-looking-at-inexpr-block lim nil t)))
939 ;; Passed a block sexp. That's a boundary
940 ;; alright.
941 (point))
942
943 ((looking-at "\\s\(")
944 ;; Passed some other paren. Only analyze
945 ;; the non-sexp chars after it.
946 (goto-char (1+ (c-down-list-backward
947 before-sws-pos)))
948 ;; We're at a valid token start position
949 ;; (outside the `save-excursion') if
950 ;; `c-crosses-statement-barrier-p' failed.
951 (c-crosses-statement-barrier-p
952 (point) sexp-loop-end-pos))
953
954 (t
955 ;; Passed a symbol sexp or line
956 ;; continuation. It doesn't matter that
957 ;; it's included in the analyzed region.
958 (if (c-crosses-statement-barrier-p
959 (point) sexp-loop-end-pos)
960 t
961 ;; If it was a line continuation then we
962 ;; have to continue looping.
963 (if (looking-at "\\\\$")
964 (setq sexp-loop-continue-pos (point)))
965 nil))))
966
967 (setq pptok ptok
968 ptok tok
969 tok boundary-pos
970 sym 'boundary)
971 ;; Like a C "continue". Analyze the next sexp.
972 (throw 'loop t)))
973
cb694ab7 974 sexp-loop-continue-pos) ; End of "go back a sexp" loop.
0386b551
AM
975 (goto-char sexp-loop-continue-pos)
976 (setq sexp-loop-end-pos sexp-loop-continue-pos
977 sexp-loop-continue-pos nil))))
a66cd3ee
MS
978
979 ;; ObjC method def?
980 (when (and c-opt-method-key
981 (setq saved (c-in-method-def-p)))
982 (setq pos saved
983 ignore-labels t) ; Avoid the label check on exit.
984 (throw 'loop nil))
985
0386b551
AM
986 ;; Handle labels.
987 (unless (eq ignore-labels t)
988 (when (numberp c-maybe-labelp)
cb694ab7
AM
989 ;; `c-crosses-statement-barrier-p' has found a colon, so we
990 ;; might be in a label now. Have we got a real label
991 ;; (including a case label) or something like C++'s "public:"?
992 (if (or (not (looking-at c-nonlabel-token-key)) ; proper label
993 (save-excursion ; e.g. "case 'a':" ?
994 (and (c-safe (c-backward-sexp) t)
995 (looking-at "\\<case\\>")))) ; FIXME!!! this is
996 ; wrong for AWK. 2006/1/14.
997 (progn
998 (if after-labels-pos ; Have we already encountered a label?
999 (if (not last-label-pos)
1000 (setq last-label-pos (or tok start)))
1001 (setq after-labels-pos (or tok start)))
1002 (setq c-maybe-labelp t
1003 label-good-pos nil))
1004 (setq c-maybe-labelp nil))) ; bogus "label"
1005
1006 (when (and (not label-good-pos) ; i.e. no invalid "label"'s yet
1007 ; been found.
1008 (looking-at c-nonlabel-token-key)) ; e.g. "while :"
0386b551
AM
1009 ;; We're in a potential label and it's the first
1010 ;; time we've found something that isn't allowed in
1011 ;; one.
1012 (setq label-good-pos (or tok start))))
1013
1014 ;; We've moved back by a sexp, so update the token positions.
a66cd3ee
MS
1015 (setq sym nil
1016 pptok ptok
1017 ptok tok
1018 tok (point)
d9e94c22 1019 pos tok))) ; Not nil (for the while loop).
a66cd3ee
MS
1020
1021 ;; If the stack isn't empty there might be errors to report.
1022 (while stack
1023 (if (and (vectorp saved-pos) (eq (length saved-pos) 3))
1024 (c-bos-report-error))
1025 (setq saved-pos (cdr (car stack))
1026 stack (cdr stack)))
1027
1028 (when (and (eq ret 'same)
1029 (not (memq sym '(boundary ignore nil))))
1030 ;; Need to investigate closer whether we've crossed
1031 ;; between a substatement and its containing statement.
1032 (if (setq saved (if (looking-at c-block-stmt-1-key)
1033 ptok
1034 pptok))
1035 (cond ((> start saved) (setq pos saved))
1036 ((= start saved) (setq ret 'up)))))
1037
0386b551
AM
1038 (when (and (not ignore-labels)
1039 (eq c-maybe-labelp t)
d9e94c22 1040 (not (eq ret 'beginning))
0386b551
AM
1041 after-labels-pos
1042 (or (not label-good-pos)
1043 (<= label-good-pos pos)
1044 (progn
1045 (goto-char (if (and last-label-pos
1046 (< last-label-pos start))
1047 last-label-pos
1048 pos))
1049 (looking-at c-label-kwds-regexp))))
a66cd3ee
MS
1050 ;; We're in a label. Maybe we should step to the statement
1051 ;; after it.
1052 (if (< after-labels-pos start)
1053 (setq pos after-labels-pos)
1054 (setq ret 'label)
0386b551
AM
1055 (if (and last-label-pos (< last-label-pos start))
1056 ;; Might have jumped over several labels. Go to the last one.
a66cd3ee
MS
1057 (setq pos last-label-pos)))))
1058
1059 ;; Skip over the unary operators that can start the statement.
1060 (goto-char pos)
1061 (while (progn
0386b551
AM
1062 (c-backward-syntactic-ws)
1063 ;; protect AWK post-inc/decrement operators, etc.
1064 (and (not (c-at-vsemi-p (point)))
1065 (/= (skip-chars-backward "-+!*&~@`#") 0)))
a66cd3ee
MS
1066 (setq pos (point)))
1067 (goto-char pos)
1068 ret)))
785eecbb 1069
785eecbb 1070(defun c-crosses-statement-barrier-p (from to)
a66cd3ee
MS
1071 "Return non-nil if buffer positions FROM to TO cross one or more
1072statement or declaration boundaries. The returned value is actually
d9e94c22
MS
1073the position of the earliest boundary char. FROM must not be within
1074a string or comment.
a66cd3ee
MS
1075
1076The variable `c-maybe-labelp' is set to the position of the first `:' that
1077might start a label (i.e. not part of `::' and not preceded by `?'). If a
0386b551
AM
1078single `?' is found, then `c-maybe-labelp' is cleared.
1079
1080For AWK, a statement which is terminated by an EOL (not a \; or a }) is
1081regarded as having a \"virtual semicolon\" immediately after the last token on
1082the line. If this virtual semicolon is _at_ from, the function recognises it.
1083
1084Note that this function might do hidden buffer changes. See the
1085comment at the start of cc-engine.el for more info."
a66cd3ee
MS
1086 (let ((skip-chars c-stmt-delim-chars)
1087 lit-range)
1088 (save-excursion
1089 (catch 'done
1090 (goto-char from)
1091 (while (progn (skip-chars-forward skip-chars to)
785eecbb 1092 (< (point) to))
0386b551
AM
1093 (cond
1094 ((setq lit-range (c-literal-limits from)) ; Have we landed in a string/comment?
1095 (goto-char (cdr lit-range)))
1096 ((eq (char-after) ?:)
1097 (forward-char)
1098 (if (and (eq (char-after) ?:)
1099 (< (point) to))
1100 ;; Ignore scope operators.
1101 (forward-char)
1102 (setq c-maybe-labelp (1- (point)))))
1103 ((eq (char-after) ??)
1104 ;; A question mark. Can't be a label, so stop
1105 ;; looking for more : and ?.
1106 (setq c-maybe-labelp nil
1107 skip-chars (substring c-stmt-delim-chars 0 -2)))
1108 ((memq (char-after) '(?# ?\n ?\r)) ; A virtual semicolon?
1109 (if (and (eq (char-before) ?\\) (memq (char-after) '(?\n ?\r)))
1110 (backward-char))
1111 (skip-chars-backward " \t" from)
1112 (if (c-at-vsemi-p)
1113 (throw 'done (point))
1114 (forward-line)))
1115 (t (throw 'done (point)))))
1116 ;; In trailing space after an as yet undetected virtual semicolon?
1117 (c-backward-syntactic-ws from)
1118 (if (and (< (point) to)
1119 (c-at-vsemi-p))
1120 (point)
1121 nil)))))
1122
1123(defun c-at-statement-start-p ()
1124 "Return non-nil if the point is at the first token in a statement
1125or somewhere in the syntactic whitespace before it.
1126
1127A \"statement\" here is not restricted to those inside code blocks.
1128Any kind of declaration-like construct that occur outside function
1129bodies is also considered a \"statement\".
1130
1131Note that this function might do hidden buffer changes. See the
1132comment at the start of cc-engine.el for more info."
1133
1134 (save-excursion
1135 (let ((end (point))
1136 c-maybe-labelp)
1137 (c-syntactic-skip-backward (substring c-stmt-delim-chars 1) nil t)
1138 (or (bobp)
1139 (eq (char-before) ?})
1140 (and (eq (char-before) ?{)
1141 (not (and c-special-brace-lists
1142 (progn (backward-char)
1143 (c-looking-at-special-brace-list)))))
1144 (c-crosses-statement-barrier-p (point) end)))))
1145
1146(defun c-at-expression-start-p ()
1147 "Return non-nil if the point is at the first token in an expression or
1148statement, or somewhere in the syntactic whitespace before it.
1149
1150An \"expression\" here is a bit different from the normal language
1151grammar sense: It's any sequence of expression tokens except commas,
1152unless they are enclosed inside parentheses of some kind. Also, an
1153expression never continues past an enclosing parenthesis, but it might
1154contain parenthesis pairs of any sort except braces.
1155
1156Since expressions never cross statement boundaries, this function also
1157recognizes statement beginnings, just like `c-at-statement-start-p'.
1158
1159Note that this function might do hidden buffer changes. See the
1160comment at the start of cc-engine.el for more info."
1161
1162 (save-excursion
1163 (let ((end (point))
1164 (c-stmt-delim-chars c-stmt-delim-chars-with-comma)
1165 c-maybe-labelp)
1166 (c-syntactic-skip-backward (substring c-stmt-delim-chars 1) nil t)
1167 (or (bobp)
1168 (memq (char-before) '(?{ ?}))
1169 (save-excursion (backward-char)
1170 (looking-at "\\s("))
1171 (c-crosses-statement-barrier-p (point) end)))))
785eecbb
RS
1172
1173\f
d9e94c22
MS
1174;; A set of functions that covers various idiosyncrasies in
1175;; implementations of `forward-comment'.
1176
1177;; Note: Some emacsen considers incorrectly that any line comment
1178;; ending with a backslash continues to the next line. I can't think
1179;; of any way to work around that in a reliable way without changing
1180;; the buffer, though. Suggestions welcome. ;) (No, temporarily
1181;; changing the syntax for backslash doesn't work since we must treat
1182;; escapes in string literals correctly.)
1183
1184(defun c-forward-single-comment ()
1185 "Move forward past whitespace and the closest following comment, if any.
1186Return t if a comment was found, nil otherwise. In either case, the
1187point is moved past the following whitespace. Line continuations,
1188i.e. a backslashes followed by line breaks, are treated as whitespace.
1189The line breaks that end line comments are considered to be the
1190comment enders, so the point will be put on the beginning of the next
1191line if it moved past a line comment.
1192
1193This function does not do any hidden buffer changes."
1194
1195 (let ((start (point)))
1196 (when (looking-at "\\([ \t\n\r\f\v]\\|\\\\[\n\r]\\)+")
1197 (goto-char (match-end 0)))
1198
1199 (when (forward-comment 1)
1200 (if (eobp)
1201 ;; Some emacsen (e.g. XEmacs 21) return t when moving
1202 ;; forwards at eob.
1203 nil
1204
1205 ;; Emacs includes the ending newline in a b-style (c++)
1206 ;; comment, but XEmacs doesn't. We depend on the Emacs
1207 ;; behavior (which also is symmetric).
1208 (if (and (eolp) (elt (parse-partial-sexp start (point)) 7))
1209 (condition-case nil (forward-char 1)))
1210
1211 t))))
1212
1213(defsubst c-forward-comments ()
1214 "Move forward past all following whitespace and comments.
1215Line continuations, i.e. a backslashes followed by line breaks, are
1216treated as whitespace.
1217
0386b551
AM
1218Note that this function might do hidden buffer changes. See the
1219comment at the start of cc-engine.el for more info."
d9e94c22
MS
1220
1221 (while (or
1222 ;; If forward-comment in at least XEmacs 21 is given a large
1223 ;; positive value, it'll loop all the way through if it hits
1224 ;; eob.
1225 (and (forward-comment 5)
1226 ;; Some emacsen (e.g. XEmacs 21) return t when moving
1227 ;; forwards at eob.
1228 (not (eobp)))
1229
1230 (when (looking-at "\\\\[\n\r]")
1231 (forward-char 2)
1232 t))))
1233
1234(defun c-backward-single-comment ()
1235 "Move backward past whitespace and the closest preceding comment, if any.
1236Return t if a comment was found, nil otherwise. In either case, the
1237point is moved past the preceding whitespace. Line continuations,
1238i.e. a backslashes followed by line breaks, are treated as whitespace.
1239The line breaks that end line comments are considered to be the
1240comment enders, so the point cannot be at the end of the same line to
1241move over a line comment.
1242
1243This function does not do any hidden buffer changes."
1244
1245 (let ((start (point)))
1246 ;; When we got newline terminated comments, forward-comment in all
1247 ;; supported emacsen so far will stop at eol of each line not
1248 ;; ending with a comment when moving backwards. This corrects for
1249 ;; that, and at the same time handles line continuations.
1250 (while (progn
1251 (skip-chars-backward " \t\n\r\f\v")
1252 (and (looking-at "[\n\r]")
0386b551 1253 (eq (char-before) ?\\)))
d9e94c22
MS
1254 (backward-char))
1255
1256 (if (bobp)
1257 ;; Some emacsen (e.g. Emacs 19.34) return t when moving
1258 ;; backwards at bob.
1259 nil
1260
1261 ;; Leave point after the closest following newline if we've
1262 ;; backed up over any above, since forward-comment won't move
1263 ;; backward over a line comment if point is at the end of the
1264 ;; same line.
1265 (re-search-forward "\\=\\s *[\n\r]" start t)
1266
1267 (if (if (forward-comment -1)
1268 (if (eolp)
1269 ;; If forward-comment above succeeded and we're at eol
1270 ;; then the newline we moved over above didn't end a
1271 ;; line comment, so we give it another go.
1272 (forward-comment -1)
1273 t))
1274
1275 ;; Emacs <= 20 and XEmacs move back over the closer of a
1276 ;; block comment that lacks an opener.
1277 (if (looking-at "\\*/")
1278 (progn (forward-char 2) nil)
1279 t)))))
1280
1281(defsubst c-backward-comments ()
1282 "Move backward past all preceding whitespace and comments.
1283Line continuations, i.e. a backslashes followed by line breaks, are
1284treated as whitespace. The line breaks that end line comments are
1285considered to be the comment enders, so the point cannot be at the end
0386b551
AM
1286of the same line to move over a line comment. Unlike
1287c-backward-syntactic-ws, this function doesn't move back over
1288preprocessor directives.
d9e94c22 1289
0386b551
AM
1290Note that this function might do hidden buffer changes. See the
1291comment at the start of cc-engine.el for more info."
d9e94c22
MS
1292
1293 (let ((start (point)))
1294 (while (and
0386b551 1295 ;; `forward-comment' in some emacsen (e.g. XEmacs 21.4)
d9e94c22
MS
1296 ;; return t when moving backwards at bob.
1297 (not (bobp))
1298
1299 (if (forward-comment -1)
1300 (if (looking-at "\\*/")
1301 ;; Emacs <= 20 and XEmacs move back over the
1302 ;; closer of a block comment that lacks an opener.
1303 (progn (forward-char 2) nil)
1304 t)
1305
1306 ;; XEmacs treats line continuations as whitespace but
1307 ;; only in the backward direction, which seems a bit
1308 ;; odd. Anyway, this is necessary for Emacs.
1309 (when (and (looking-at "[\n\r]")
1310 (eq (char-before) ?\\)
1311 (< (point) start))
1312 (backward-char)
1313 t))))))
1314
1315\f
d9e94c22 1316;; Tools for skipping over syntactic whitespace.
a66cd3ee 1317
d9e94c22
MS
1318;; The following functions use text properties to cache searches over
1319;; large regions of syntactic whitespace. It works as follows:
1320;;
1321;; o If a syntactic whitespace region contains anything but simple
1322;; whitespace (i.e. space, tab and line breaks), the text property
1323;; `c-in-sws' is put over it. At places where we have stopped
1324;; within that region there's also a `c-is-sws' text property.
1325;; That since there typically are nested whitespace inside that
1326;; must be handled separately, e.g. whitespace inside a comment or
1327;; cpp directive. Thus, from one point with `c-is-sws' it's safe
1328;; to jump to another point with that property within the same
1329;; `c-in-sws' region. It can be likened to a ladder where
1330;; `c-in-sws' marks the bars and `c-is-sws' the rungs.
1331;;
1332;; o The `c-is-sws' property is put on the simple whitespace chars at
1333;; a "rung position" and also maybe on the first following char.
1334;; As many characters as can be conveniently found in this range
1335;; are marked, but no assumption can be made that the whole range
1336;; is marked (it could be clobbered by later changes, for
1337;; instance).
1338;;
1339;; Note that some part of the beginning of a sequence of simple
1340;; whitespace might be part of the end of a preceding line comment
1341;; or cpp directive and must not be considered part of the "rung".
1342;; Such whitespace is some amount of horizontal whitespace followed
1343;; by a newline. In the case of cpp directives it could also be
1344;; two newlines with horizontal whitespace between them.
1345;;
1346;; The reason to include the first following char is to cope with
1347;; "rung positions" that doesn't have any ordinary whitespace. If
1348;; `c-is-sws' is put on a token character it does not have
1349;; `c-in-sws' set simultaneously. That's the only case when that
1350;; can occur, and the reason for not extending the `c-in-sws'
1351;; region to cover it is that the `c-in-sws' region could then be
1352;; accidentally merged with a following one if the token is only
1353;; one character long.
1354;;
1355;; o On buffer changes the `c-in-sws' and `c-is-sws' properties are
1356;; removed in the changed region. If the change was inside
1357;; syntactic whitespace that means that the "ladder" is broken, but
1358;; a later call to `c-forward-sws' or `c-backward-sws' will use the
1359;; parts on either side and use an ordinary search only to "repair"
1360;; the gap.
1361;;
1362;; Special care needs to be taken if a region is removed: If there
1363;; are `c-in-sws' on both sides of it which do not connect inside
1364;; the region then they can't be joined. If e.g. a marked macro is
1365;; broken, syntactic whitespace inside the new text might be
1366;; marked. If those marks would become connected with the old
1367;; `c-in-sws' range around the macro then we could get a ladder
1368;; with one end outside the macro and the other at some whitespace
1369;; within it.
1370;;
1371;; The main motivation for this system is to increase the speed in
1372;; skipping over the large whitespace regions that can occur at the
1373;; top level in e.g. header files that contain a lot of comments and
1374;; cpp directives. For small comments inside code it's probably
1375;; slower than using `forward-comment' straightforwardly, but speed is
1376;; not a significant factor there anyway.
1377
1378; (defface c-debug-is-sws-face
1379; '((t (:background "GreenYellow")))
1380; "Debug face to mark the `c-is-sws' property.")
1381; (defface c-debug-in-sws-face
1382; '((t (:underline t)))
1383; "Debug face to mark the `c-in-sws' property.")
1384
1385; (defun c-debug-put-sws-faces ()
1386; ;; Put the sws debug faces on all the `c-is-sws' and `c-in-sws'
1387; ;; properties in the buffer.
1388; (interactive)
1389; (save-excursion
0386b551 1390; (c-save-buffer-state (in-face)
d9e94c22
MS
1391; (goto-char (point-min))
1392; (setq in-face (if (get-text-property (point) 'c-is-sws)
1393; (point)))
1394; (while (progn
1395; (goto-char (next-single-property-change
1396; (point) 'c-is-sws nil (point-max)))
1397; (if in-face
1398; (progn
1399; (c-debug-add-face in-face (point) 'c-debug-is-sws-face)
1400; (setq in-face nil))
1401; (setq in-face (point)))
1402; (not (eobp))))
1403; (goto-char (point-min))
1404; (setq in-face (if (get-text-property (point) 'c-in-sws)
1405; (point)))
1406; (while (progn
1407; (goto-char (next-single-property-change
1408; (point) 'c-in-sws nil (point-max)))
1409; (if in-face
1410; (progn
1411; (c-debug-add-face in-face (point) 'c-debug-in-sws-face)
1412; (setq in-face nil))
1413; (setq in-face (point)))
1414; (not (eobp)))))))
1415
1416(defmacro c-debug-sws-msg (&rest args)
1417 ;;`(message ,@args)
1418 )
1419
1420(defmacro c-put-is-sws (beg end)
0386b551 1421 ;; This macro does a hidden buffer change.
d9e94c22
MS
1422 `(let ((beg ,beg) (end ,end))
1423 (put-text-property beg end 'c-is-sws t)
1424 ,@(when (facep 'c-debug-is-sws-face)
1425 `((c-debug-add-face beg end 'c-debug-is-sws-face)))))
1426
1427(defmacro c-put-in-sws (beg end)
0386b551 1428 ;; This macro does a hidden buffer change.
d9e94c22
MS
1429 `(let ((beg ,beg) (end ,end))
1430 (put-text-property beg end 'c-in-sws t)
1431 ,@(when (facep 'c-debug-is-sws-face)
1432 `((c-debug-add-face beg end 'c-debug-in-sws-face)))))
1433
1434(defmacro c-remove-is-sws (beg end)
0386b551 1435 ;; This macro does a hidden buffer change.
d9e94c22
MS
1436 `(let ((beg ,beg) (end ,end))
1437 (remove-text-properties beg end '(c-is-sws nil))
1438 ,@(when (facep 'c-debug-is-sws-face)
1439 `((c-debug-remove-face beg end 'c-debug-is-sws-face)))))
1440
1441(defmacro c-remove-in-sws (beg end)
0386b551 1442 ;; This macro does a hidden buffer change.
d9e94c22
MS
1443 `(let ((beg ,beg) (end ,end))
1444 (remove-text-properties beg end '(c-in-sws nil))
1445 ,@(when (facep 'c-debug-is-sws-face)
1446 `((c-debug-remove-face beg end 'c-debug-in-sws-face)))))
1447
1448(defmacro c-remove-is-and-in-sws (beg end)
0386b551 1449 ;; This macro does a hidden buffer change.
d9e94c22
MS
1450 `(let ((beg ,beg) (end ,end))
1451 (remove-text-properties beg end '(c-is-sws nil c-in-sws nil))
1452 ,@(when (facep 'c-debug-is-sws-face)
1453 `((c-debug-remove-face beg end 'c-debug-is-sws-face)
1454 (c-debug-remove-face beg end 'c-debug-in-sws-face)))))
1455
1456(defsubst c-invalidate-sws-region-after (beg end)
1457 ;; Called from `after-change-functions'. Note that if
1458 ;; `c-forward-sws' or `c-backward-sws' are used outside
1459 ;; `c-save-buffer-state' or similar then this will remove the cache
1460 ;; properties right after they're added.
0386b551
AM
1461 ;;
1462 ;; This function does hidden buffer changes.
d9e94c22
MS
1463
1464 (save-excursion
1465 ;; Adjust the end to remove the properties in any following simple
1466 ;; ws up to and including the next line break, if there is any
1467 ;; after the changed region. This is necessary e.g. when a rung
1468 ;; marked empty line is converted to a line comment by inserting
1469 ;; "//" before the line break. In that case the line break would
1470 ;; keep the rung mark which could make a later `c-backward-sws'
1471 ;; move into the line comment instead of over it.
1472 (goto-char end)
1473 (skip-chars-forward " \t\f\v")
1474 (when (and (eolp) (not (eobp)))
1475 (setq end (1+ (point)))))
1476
1477 (when (and (= beg end)
1478 (get-text-property beg 'c-in-sws)
2a15eb73 1479 (> beg (point-min))
d9e94c22
MS
1480 (get-text-property (1- beg) 'c-in-sws))
1481 ;; Ensure that an `c-in-sws' range gets broken. Note that it isn't
1482 ;; safe to keep a range that was continuous before the change. E.g:
1483 ;;
1484 ;; #define foo
1485 ;; \
1486 ;; bar
1487 ;;
1488 ;; There can be a "ladder" between "#" and "b". Now, if the newline
1489 ;; after "foo" is removed then "bar" will become part of the cpp
1490 ;; directive instead of a syntactically relevant token. In that
1491 ;; case there's no longer syntactic ws from "#" to "b".
1492 (setq beg (1- beg)))
1493
1494 (c-debug-sws-msg "c-invalidate-sws-region-after [%s..%s]" beg end)
1495 (c-remove-is-and-in-sws beg end))
1496
1497(defun c-forward-sws ()
1498 ;; Used by `c-forward-syntactic-ws' to implement the unbounded search.
0386b551
AM
1499 ;;
1500 ;; This function might do hidden buffer changes.
d9e94c22
MS
1501
1502 (let (;; `rung-pos' is set to a position as early as possible in the
1503 ;; unmarked part of the simple ws region.
1504 (rung-pos (point)) next-rung-pos rung-end-pos last-put-in-sws-pos
1505 rung-is-marked next-rung-is-marked simple-ws-end
1506 ;; `safe-start' is set when it's safe to cache the start position.
1507 ;; It's not set if we've initially skipped over comments and line
1508 ;; continuations since we might have gone out through the end of a
1509 ;; macro then. This provision makes `c-forward-sws' not populate the
1510 ;; cache in the majority of cases, but otoh is `c-backward-sws' by far
1511 ;; more common.
1512 safe-start)
1513
1514 ;; Skip simple ws and do a quick check on the following character to see
1515 ;; if it's anything that can't start syntactic ws, so we can bail out
1516 ;; early in the majority of cases when there just are a few ws chars.
1517 (skip-chars-forward " \t\n\r\f\v")
1518 (when (looking-at c-syntactic-ws-start)
1519
1520 (setq rung-end-pos (min (1+ (point)) (point-max)))
1521 (if (setq rung-is-marked (text-property-any rung-pos rung-end-pos
1522 'c-is-sws t))
1523 ;; Find the last rung position to avoid setting properties in all
1524 ;; the cases when the marked rung is complete.
1525 ;; (`next-single-property-change' is certain to move at least one
1526 ;; step forward.)
1527 (setq rung-pos (1- (next-single-property-change
1528 rung-is-marked 'c-is-sws nil rung-end-pos)))
1529 ;; Got no marked rung here. Since the simple ws might have started
1530 ;; inside a line comment or cpp directive we must set `rung-pos' as
1531 ;; high as possible.
1532 (setq rung-pos (point)))
1533
1534 (while
1535 (progn
1536 (while
1537 (when (and rung-is-marked
1538 (get-text-property (point) 'c-in-sws))
1539
1540 ;; The following search is the main reason that `c-in-sws'
1541 ;; and `c-is-sws' aren't combined to one property.
1542 (goto-char (next-single-property-change
1543 (point) 'c-in-sws nil (point-max)))
1544 (unless (get-text-property (point) 'c-is-sws)
1545 ;; If the `c-in-sws' region extended past the last
1546 ;; `c-is-sws' char we have to go back a bit.
1547 (or (get-text-property (1- (point)) 'c-is-sws)
1548 (goto-char (previous-single-property-change
1549 (point) 'c-is-sws)))
1550 (backward-char))
1551
1552 (c-debug-sws-msg
1553 "c-forward-sws cached move %s -> %s (max %s)"
1554 rung-pos (point) (point-max))
1555
1556 (setq rung-pos (point))
1557 (and (> (skip-chars-forward " \t\n\r\f\v") 0)
1558 (not (eobp))))
1559
1560 ;; We'll loop here if there is simple ws after the last rung.
1561 ;; That means that there's been some change in it and it's
1562 ;; possible that we've stepped into another ladder, so extend
1563 ;; the previous one to join with it if there is one, and try to
1564 ;; use the cache again.
1565 (c-debug-sws-msg
1566 "c-forward-sws extending rung with [%s..%s] (max %s)"
1567 (1+ rung-pos) (1+ (point)) (point-max))
1568 (unless (get-text-property (point) 'c-is-sws)
1569 ;; Remove any `c-in-sws' property from the last char of
1570 ;; the rung before we mark it with `c-is-sws', so that we
1571 ;; won't connect with the remains of a broken "ladder".
1572 (c-remove-in-sws (point) (1+ (point))))
1573 (c-put-is-sws (1+ rung-pos)
1574 (1+ (point)))
1575 (c-put-in-sws rung-pos
1576 (setq rung-pos (point)
1577 last-put-in-sws-pos rung-pos)))
1578
1579 (setq simple-ws-end (point))
1580 (c-forward-comments)
1581
1582 (cond
1583 ((/= (point) simple-ws-end)
1584 ;; Skipped over comments. Don't cache at eob in case the buffer
1585 ;; is narrowed.
1586 (not (eobp)))
1587
1588 ((save-excursion
1589 (and c-opt-cpp-prefix
1590 (looking-at c-opt-cpp-start)
1591 (progn (skip-chars-backward " \t")
1592 (bolp))
1593 (or (bobp)
1594 (progn (backward-char)
1595 (not (eq (char-before) ?\\))))))
1596 ;; Skip a preprocessor directive.
1597 (end-of-line)
1598 (while (and (eq (char-before) ?\\)
1599 (= (forward-line 1) 0))
1600 (end-of-line))
1601 (forward-line 1)
1602 (setq safe-start t)
1603 ;; Don't cache at eob in case the buffer is narrowed.
1604 (not (eobp)))))
1605
1606 ;; We've searched over a piece of non-white syntactic ws. See if this
1607 ;; can be cached.
1608 (setq next-rung-pos (point))
1609 (skip-chars-forward " \t\n\r\f\v")
1610 (setq rung-end-pos (min (1+ (point)) (point-max)))
1611
1612 (if (or
1613 ;; Cache if we haven't skipped comments only, and if we started
1614 ;; either from a marked rung or from a completely uncached
1615 ;; position.
1616 (and safe-start
1617 (or rung-is-marked
1618 (not (get-text-property simple-ws-end 'c-in-sws))))
1619
1620 ;; See if there's a marked rung in the encountered simple ws. If
1621 ;; so then we can cache, unless `safe-start' is nil. Even then
1622 ;; we need to do this to check if the cache can be used for the
1623 ;; next step.
1624 (and (setq next-rung-is-marked
1625 (text-property-any next-rung-pos rung-end-pos
1626 'c-is-sws t))
1627 safe-start))
b2acd789 1628
0ec8351b 1629 (progn
d9e94c22
MS
1630 (c-debug-sws-msg
1631 "c-forward-sws caching [%s..%s] - [%s..%s] (max %s)"
1632 rung-pos (1+ simple-ws-end) next-rung-pos rung-end-pos
1633 (point-max))
1634
1635 ;; Remove the properties for any nested ws that might be cached.
1636 ;; Only necessary for `c-is-sws' since `c-in-sws' will be set
1637 ;; anyway.
1638 (c-remove-is-sws (1+ simple-ws-end) next-rung-pos)
1639 (unless (and rung-is-marked (= rung-pos simple-ws-end))
1640 (c-put-is-sws rung-pos
1641 (1+ simple-ws-end))
1642 (setq rung-is-marked t))
1643 (c-put-in-sws rung-pos
1644 (setq rung-pos (point)
1645 last-put-in-sws-pos rung-pos))
1646 (unless (get-text-property (1- rung-end-pos) 'c-is-sws)
1647 ;; Remove any `c-in-sws' property from the last char of
1648 ;; the rung before we mark it with `c-is-sws', so that we
1649 ;; won't connect with the remains of a broken "ladder".
1650 (c-remove-in-sws (1- rung-end-pos) rung-end-pos))
1651 (c-put-is-sws next-rung-pos
1652 rung-end-pos))
1653
1654 (c-debug-sws-msg
1655 "c-forward-sws not caching [%s..%s] - [%s..%s] (max %s)"
1656 rung-pos (1+ simple-ws-end) next-rung-pos rung-end-pos
1657 (point-max))
1658
1659 ;; Set `rung-pos' for the next rung. It's the same thing here as
1660 ;; initially, except that the rung position is set as early as
1661 ;; possible since we can't be in the ending ws of a line comment or
1662 ;; cpp directive now.
1663 (if (setq rung-is-marked next-rung-is-marked)
1664 (setq rung-pos (1- (next-single-property-change
1665 rung-is-marked 'c-is-sws nil rung-end-pos)))
1666 (setq rung-pos next-rung-pos))
1667 (setq safe-start t)))
1668
1669 ;; Make sure that the newly marked `c-in-sws' region doesn't connect to
1670 ;; another one after the point (which might occur when editing inside a
1671 ;; comment or macro).
1672 (when (eq last-put-in-sws-pos (point))
1673 (cond ((< last-put-in-sws-pos (point-max))
1674 (c-debug-sws-msg
1675 "c-forward-sws clearing at %s for cache separation"
1676 last-put-in-sws-pos)
1677 (c-remove-in-sws last-put-in-sws-pos
1678 (1+ last-put-in-sws-pos)))
1679 (t
1680 ;; If at eob we have to clear the last character before the end
1681 ;; instead since the buffer might be narrowed and there might
1682 ;; be a `c-in-sws' after (point-max). In this case it's
1683 ;; necessary to clear both properties.
1684 (c-debug-sws-msg
1685 "c-forward-sws clearing thoroughly at %s for cache separation"
1686 (1- last-put-in-sws-pos))
1687 (c-remove-is-and-in-sws (1- last-put-in-sws-pos)
1688 last-put-in-sws-pos))))
1689 )))
b2acd789 1690
d9e94c22
MS
1691(defun c-backward-sws ()
1692 ;; Used by `c-backward-syntactic-ws' to implement the unbounded search.
0386b551
AM
1693 ;;
1694 ;; This function might do hidden buffer changes.
d9e94c22
MS
1695
1696 (let (;; `rung-pos' is set to a position as late as possible in the unmarked
1697 ;; part of the simple ws region.
1698 (rung-pos (point)) next-rung-pos last-put-in-sws-pos
1699 rung-is-marked simple-ws-beg cmt-skip-pos)
1700
1701 ;; Skip simple horizontal ws and do a quick check on the preceding
1702 ;; character to see if it's anying that can't end syntactic ws, so we can
1703 ;; bail out early in the majority of cases when there just are a few ws
1704 ;; chars. Newlines are complicated in the backward direction, so we can't
1705 ;; skip over them.
1706 (skip-chars-backward " \t\f")
1707 (when (and (not (bobp))
1708 (save-excursion
1709 (backward-char)
1710 (looking-at c-syntactic-ws-end)))
1711
1712 ;; Try to find a rung position in the simple ws preceding point, so that
1713 ;; we can get a cache hit even if the last bit of the simple ws has
1714 ;; changed recently.
1715 (setq simple-ws-beg (point))
1716 (skip-chars-backward " \t\n\r\f\v")
1717 (if (setq rung-is-marked (text-property-any
1718 (point) (min (1+ rung-pos) (point-max))
1719 'c-is-sws t))
1720 ;; `rung-pos' will be the earliest marked position, which means that
1721 ;; there might be later unmarked parts in the simple ws region.
1722 ;; It's not worth the effort to fix that; the last part of the
1723 ;; simple ws is also typically edited often, so it could be wasted.
1724 (goto-char (setq rung-pos rung-is-marked))
1725 (goto-char simple-ws-beg))
1726
1727 (while
1728 (progn
1729 (while
1730 (when (and rung-is-marked
1731 (not (bobp))
1732 (get-text-property (1- (point)) 'c-in-sws))
1733
1734 ;; The following search is the main reason that `c-in-sws'
1735 ;; and `c-is-sws' aren't combined to one property.
1736 (goto-char (previous-single-property-change
1737 (point) 'c-in-sws nil (point-min)))
1738 (unless (get-text-property (point) 'c-is-sws)
1739 ;; If the `c-in-sws' region extended past the first
1740 ;; `c-is-sws' char we have to go forward a bit.
1741 (goto-char (next-single-property-change
1742 (point) 'c-is-sws)))
1743
1744 (c-debug-sws-msg
1745 "c-backward-sws cached move %s <- %s (min %s)"
1746 (point) rung-pos (point-min))
1747
1748 (setq rung-pos (point))
1749 (if (and (< (min (skip-chars-backward " \t\f\v")
1750 (progn
1751 (setq simple-ws-beg (point))
1752 (skip-chars-backward " \t\n\r\f\v")))
1753 0)
1754 (setq rung-is-marked
1755 (text-property-any (point) rung-pos
1756 'c-is-sws t)))
1757 t
1758 (goto-char simple-ws-beg)
1759 nil))
1760
1761 ;; We'll loop here if there is simple ws before the first rung.
1762 ;; That means that there's been some change in it and it's
1763 ;; possible that we've stepped into another ladder, so extend
1764 ;; the previous one to join with it if there is one, and try to
1765 ;; use the cache again.
1766 (c-debug-sws-msg
1767 "c-backward-sws extending rung with [%s..%s] (min %s)"
1768 rung-is-marked rung-pos (point-min))
1769 (unless (get-text-property (1- rung-pos) 'c-is-sws)
1770 ;; Remove any `c-in-sws' property from the last char of
1771 ;; the rung before we mark it with `c-is-sws', so that we
1772 ;; won't connect with the remains of a broken "ladder".
1773 (c-remove-in-sws (1- rung-pos) rung-pos))
1774 (c-put-is-sws rung-is-marked
1775 rung-pos)
1776 (c-put-in-sws rung-is-marked
1777 (1- rung-pos))
1778 (setq rung-pos rung-is-marked
1779 last-put-in-sws-pos rung-pos))
1780
1781 (c-backward-comments)
1782 (setq cmt-skip-pos (point))
a66cd3ee 1783
d9e94c22
MS
1784 (cond
1785 ((and c-opt-cpp-prefix
1786 (/= cmt-skip-pos simple-ws-beg)
1787 (c-beginning-of-macro))
1788 ;; Inside a cpp directive. See if it should be skipped over.
1789 (let ((cpp-beg (point)))
1790
1791 ;; Move back over all line continuations in the region skipped
1792 ;; over by `c-backward-comments'. If we go past it then we
1793 ;; started inside the cpp directive.
1794 (goto-char simple-ws-beg)
1795 (beginning-of-line)
1796 (while (and (> (point) cmt-skip-pos)
1797 (progn (backward-char)
1798 (eq (char-before) ?\\)))
1799 (beginning-of-line))
1800
1801 (if (< (point) cmt-skip-pos)
1802 ;; Don't move past the cpp directive if we began inside
1803 ;; it. Note that the position at the end of the last line
1804 ;; of the macro is also considered to be within it.
1805 (progn (goto-char cmt-skip-pos)
1806 nil)
1807
1808 ;; It's worthwhile to spend a little bit of effort on finding
1809 ;; the end of the macro, to get a good `simple-ws-beg'
1810 ;; position for the cache. Note that `c-backward-comments'
1811 ;; could have stepped over some comments before going into
1812 ;; the macro, and then `simple-ws-beg' must be kept on the
1813 ;; same side of those comments.
1814 (goto-char simple-ws-beg)
1815 (skip-chars-backward " \t\n\r\f\v")
1816 (if (eq (char-before) ?\\)
1817 (forward-char))
1818 (forward-line 1)
1819 (if (< (point) simple-ws-beg)
1820 ;; Might happen if comments after the macro were skipped
1821 ;; over.
1822 (setq simple-ws-beg (point)))
1823
1824 (goto-char cpp-beg)
1825 t)))
1826
1827 ((/= (save-excursion
1828 (skip-chars-forward " \t\n\r\f\v" simple-ws-beg)
1829 (setq next-rung-pos (point)))
1830 simple-ws-beg)
1831 ;; Skipped over comments. Must put point at the end of
1832 ;; the simple ws at point since we might be after a line
1833 ;; comment or cpp directive that's been partially
1834 ;; narrowed out, and we can't risk marking the simple ws
1835 ;; at the end of it.
1836 (goto-char next-rung-pos)
1837 t)))
1838
1839 ;; We've searched over a piece of non-white syntactic ws. See if this
1840 ;; can be cached.
1841 (setq next-rung-pos (point))
1842 (skip-chars-backward " \t\f\v")
1843
1844 (if (or
1845 ;; Cache if we started either from a marked rung or from a
1846 ;; completely uncached position.
1847 rung-is-marked
1848 (not (get-text-property (1- simple-ws-beg) 'c-in-sws))
1849
1850 ;; Cache if there's a marked rung in the encountered simple ws.
1851 (save-excursion
1852 (skip-chars-backward " \t\n\r\f\v")
1853 (text-property-any (point) (min (1+ next-rung-pos) (point-max))
1854 'c-is-sws t)))
a66cd3ee 1855
d9e94c22
MS
1856 (progn
1857 (c-debug-sws-msg
1858 "c-backward-sws caching [%s..%s] - [%s..%s] (min %s)"
1859 (point) (1+ next-rung-pos)
1860 simple-ws-beg (min (1+ rung-pos) (point-max))
1861 (point-min))
1862
1863 ;; Remove the properties for any nested ws that might be cached.
1864 ;; Only necessary for `c-is-sws' since `c-in-sws' will be set
1865 ;; anyway.
1866 (c-remove-is-sws (1+ next-rung-pos) simple-ws-beg)
1867 (unless (and rung-is-marked (= simple-ws-beg rung-pos))
1868 (let ((rung-end-pos (min (1+ rung-pos) (point-max))))
1869 (unless (get-text-property (1- rung-end-pos) 'c-is-sws)
1870 ;; Remove any `c-in-sws' property from the last char of
1871 ;; the rung before we mark it with `c-is-sws', so that we
1872 ;; won't connect with the remains of a broken "ladder".
1873 (c-remove-in-sws (1- rung-end-pos) rung-end-pos))
1874 (c-put-is-sws simple-ws-beg
1875 rung-end-pos)
1876 (setq rung-is-marked t)))
1877 (c-put-in-sws (setq simple-ws-beg (point)
1878 last-put-in-sws-pos simple-ws-beg)
1879 rung-pos)
1880 (c-put-is-sws (setq rung-pos simple-ws-beg)
1881 (1+ next-rung-pos)))
1882
1883 (c-debug-sws-msg
1884 "c-backward-sws not caching [%s..%s] - [%s..%s] (min %s)"
1885 (point) (1+ next-rung-pos)
1886 simple-ws-beg (min (1+ rung-pos) (point-max))
1887 (point-min))
1888 (setq rung-pos next-rung-pos
1889 simple-ws-beg (point))
1890 ))
1891
1892 ;; Make sure that the newly marked `c-in-sws' region doesn't connect to
1893 ;; another one before the point (which might occur when editing inside a
1894 ;; comment or macro).
1895 (when (eq last-put-in-sws-pos (point))
1896 (cond ((< (point-min) last-put-in-sws-pos)
1897 (c-debug-sws-msg
1898 "c-backward-sws clearing at %s for cache separation"
1899 (1- last-put-in-sws-pos))
1900 (c-remove-in-sws (1- last-put-in-sws-pos)
1901 last-put-in-sws-pos))
1902 ((> (point-min) 1)
1903 ;; If at bob and the buffer is narrowed, we have to clear the
1904 ;; character we're standing on instead since there might be a
1905 ;; `c-in-sws' before (point-min). In this case it's necessary
1906 ;; to clear both properties.
1907 (c-debug-sws-msg
1908 "c-backward-sws clearing thoroughly at %s for cache separation"
1909 last-put-in-sws-pos)
1910 (c-remove-is-and-in-sws last-put-in-sws-pos
1911 (1+ last-put-in-sws-pos)))))
1912 )))
785eecbb 1913
d9e94c22 1914\f
580fba94
AM
1915;; Other whitespace tools
1916(defun c-partial-ws-p (beg end)
1917 ;; Is the region (beg end) WS, and is there WS (or BOB/EOB) next to the
1918 ;; region? This is a "heuristic" function. .....
1919 ;;
1920 ;; The motivation for the second bit is to check whether the removal of this
1921 ;; space is to check whether removing this region would coalesce two
1922 ;; symbols.
1923 ;;
1924 ;; FIXME!!! This function doesn't check virtual semicolons in any way. Be
1925 ;; careful about using this function for, e.g. AWK. (2007/3/7)
1926 (save-excursion
1927 (let ((end+1 (min (1+ end) (point-max))))
1928 (or (progn (goto-char (max (point-min) (1- beg)))
1929 (c-skip-ws-forward end)
1930 (eq (point) end))
1931 (progn (goto-char beg)
1932 (c-skip-ws-forward end+1)
1933 (eq (point) end+1))))))
1934\f
0386b551 1935;; A system for finding noteworthy parens before the point.
e1c458ae 1936
d9e94c22
MS
1937(defvar c-state-cache nil)
1938(make-variable-buffer-local 'c-state-cache)
1939;; The state cache used by `c-parse-state' to cut down the amount of
1940;; searching. It's the result from some earlier `c-parse-state' call.
0386b551 1941;;
d9e94c22
MS
1942;; The use of the cached info is more effective if the next
1943;; `c-parse-state' call is on a line close by the one the cached state
1944;; was made at; the cache can actually slow down a little if the
1945;; cached state was made very far back in the buffer. The cache is
1946;; most effective if `c-parse-state' is used on each line while moving
1947;; forward.
e1c458ae 1948
d9e94c22
MS
1949(defvar c-state-cache-start 1)
1950(make-variable-buffer-local 'c-state-cache-start)
1951;; This is (point-min) when `c-state-cache' was calculated, since a
1952;; change of narrowing is likely to affect the parens that are visible
1953;; before the point.
1954
0386b551
AM
1955(defvar c-state-cache-good-pos 1)
1956(make-variable-buffer-local 'c-state-cache-good-pos)
1957;; This is a position where `c-state-cache' is known to be correct.
1958;; It's a position inside one of the recorded unclosed parens or the
1959;; top level, but not further nested inside any literal or subparen
1960;; that is closed before the last recorded position.
1961;;
1962;; The exact position is chosen to try to be close to yet earlier than
1963;; the position where `c-state-cache' will be called next. Right now
1964;; the heuristic is to set it to the position after the last found
1965;; closing paren (of any type) before the line on which
1966;; `c-parse-state' was called. That is chosen primarily to work well
1967;; with refontification of the current line.
1968
d9e94c22
MS
1969(defsubst c-invalidate-state-cache (pos)
1970 ;; Invalidate all info on `c-state-cache' that applies to the buffer
1971 ;; at POS or higher. This is much like `c-whack-state-after', but
1972 ;; it never changes a paren pair element into an open paren element.
1973 ;; Doing that would mean that the new open paren wouldn't have the
1974 ;; required preceding paren pair element.
0386b551
AM
1975 (while (and (or c-state-cache
1976 (when (< pos c-state-cache-good-pos)
1977 (setq c-state-cache-good-pos 1)
1978 nil))
d9e94c22
MS
1979 (let ((elem (car c-state-cache)))
1980 (if (consp elem)
0386b551
AM
1981 (or (< pos (cdr elem))
1982 (when (< pos c-state-cache-good-pos)
1983 (setq c-state-cache-good-pos (cdr elem))
1984 nil))
1985 (or (<= pos elem)
1986 (when (< pos c-state-cache-good-pos)
1987 (setq c-state-cache-good-pos (1+ elem))
1988 nil)))))
d9e94c22 1989 (setq c-state-cache (cdr c-state-cache))))
785eecbb 1990
0386b551
AM
1991(defun c-get-fallback-start-pos (here)
1992 ;; Return the start position for building `c-state-cache' from
1993 ;; scratch.
1994 (save-excursion
1995 ;; Go back 2 bods, but ignore any bogus positions returned by
1996 ;; beginning-of-defun (i.e. open paren in column zero).
1997 (goto-char here)
1998 (let ((cnt 2))
1999 (while (not (or (bobp) (zerop cnt)))
2000 (c-beginning-of-defun-1)
2001 (if (eq (char-after) ?\{)
2002 (setq cnt (1- cnt)))))
2003 (point)))
2004
785eecbb 2005(defun c-parse-state ()
0386b551 2006 ;; Find and record all noteworthy parens between some good point
a66cd3ee
MS
2007 ;; earlier in the file and point. That good point is at least the
2008 ;; beginning of the top-level construct we are in, or the beginning
2009 ;; of the preceding top-level construct if we aren't in one.
785eecbb 2010 ;;
a66cd3ee
MS
2011 ;; The returned value is a list of the noteworthy parens with the
2012 ;; last one first. If an element in the list is an integer, it's
2013 ;; the position of an open paren which has not been closed before
d9e94c22 2014 ;; the point. If an element is a cons, it gives the position of a
a66cd3ee
MS
2015 ;; closed brace paren pair; the car is the start paren position and
2016 ;; the cdr is the position following the closing paren. Only the
0386b551
AM
2017 ;; last closed brace paren pair before each open paren and before
2018 ;; the point is recorded, and thus the state never contains two cons
2019 ;; elements in succession.
d9e94c22
MS
2020 ;;
2021 ;; Currently no characters which are given paren syntax with the
2022 ;; syntax-table property are recorded, i.e. angle bracket arglist
2023 ;; parens are never present here. Note that this might change.
2024 ;;
0386b551
AM
2025 ;; BUG: This function doesn't cope entirely well with unbalanced
2026 ;; parens in macros. E.g. in the following case the brace before
2027 ;; the macro isn't balanced with the one after it:
2028 ;;
2029 ;; {
2030 ;; #define X {
2031 ;; }
2032 ;;
2033 ;; This function might do hidden buffer changes.
d9e94c22 2034
a66cd3ee
MS
2035 (save-restriction
2036 (let* ((here (point))
0386b551 2037 (here-bol (c-point 'bol))
a66cd3ee
MS
2038 (c-macro-start (c-query-macro-start))
2039 (in-macro-start (or c-macro-start (point)))
0386b551
AM
2040 old-state last-pos brace-pair-open brace-pair-close
2041 pos save-pos)
2042 (c-invalidate-state-cache here)
d9e94c22
MS
2043
2044 ;; If the minimum position has changed due to narrowing then we
2045 ;; have to fix the tail of `c-state-cache' accordingly.
2046 (unless (= c-state-cache-start (point-min))
2047 (if (> (point-min) c-state-cache-start)
2048 ;; If point-min has moved forward then we just need to cut
2049 ;; off a bit of the tail.
2050 (let ((ptr (cons nil c-state-cache)) elem)
449a2b0d 2051 (while (and (setq elem (car-safe (cdr ptr)))
d9e94c22
MS
2052 (>= (if (consp elem) (car elem) elem)
2053 (point-min)))
449a2b0d 2054 (setq ptr (cdr ptr)))
d9e94c22
MS
2055 (when (consp ptr)
2056 (if (eq (cdr ptr) c-state-cache)
0386b551
AM
2057 (setq c-state-cache nil
2058 c-state-cache-good-pos 1)
d9e94c22
MS
2059 (setcdr ptr nil))))
2060 ;; If point-min has moved backward then we drop the state
2061 ;; completely. It's possible to do a better job here and
2062 ;; recalculate the top only.
0386b551
AM
2063 (setq c-state-cache nil
2064 c-state-cache-good-pos 1))
d9e94c22
MS
2065 (setq c-state-cache-start (point-min)))
2066
a66cd3ee
MS
2067 ;; Get the latest position we know are directly inside the
2068 ;; closest containing paren of the cached state.
2069 (setq last-pos (and c-state-cache
2070 (if (consp (car c-state-cache))
2071 (cdr (car c-state-cache))
2072 (1+ (car c-state-cache)))))
0386b551
AM
2073 (if (or (not last-pos)
2074 (< last-pos c-state-cache-good-pos))
2075 (setq last-pos c-state-cache-good-pos)
2076 ;; Take the opportunity to move the cached good position
2077 ;; further down.
2078 (if (< last-pos here-bol)
2079 (setq c-state-cache-good-pos last-pos)))
2080
2081 ;; Check if `last-pos' is in a macro. If it is, and we're not
2082 ;; in the same macro, we must discard everything on
2083 ;; `c-state-cache' that is inside the macro before using it.
2084 (save-excursion
2085 (goto-char last-pos)
2086 (when (and (c-beginning-of-macro)
2087 (/= (point) in-macro-start))
2088 (c-invalidate-state-cache (point))
2089 ;; Set `last-pos' again just like above except that there's
2090 ;; no use looking at `c-state-cache-good-pos' here.
2091 (setq last-pos (if c-state-cache
2092 (if (consp (car c-state-cache))
2093 (cdr (car c-state-cache))
2094 (1+ (car c-state-cache)))
2095 1))))
2096
2097 ;; If we've moved very far from the last cached position then
2098 ;; it's probably better to redo it from scratch, otherwise we
2099 ;; might spend a lot of time searching from `last-pos' down to
2100 ;; here.
2101 (when (< last-pos (- here 20000))
2102 ;; First get the fallback start position. If it turns out
2103 ;; that it's so far back that the cached state is closer then
2104 ;; we'll keep it afterall.
2105 (setq pos (c-get-fallback-start-pos here))
2106 (if (<= pos last-pos)
2107 (setq pos nil)
2108 (setq last-pos nil
2109 c-state-cache nil
2110 c-state-cache-good-pos 1)))
2111
2112 ;; Find the start position for the forward search. (Can't
2113 ;; search in the backward direction since the point might be in
2114 ;; some kind of literal.)
2115
2116 (unless pos
2117 (setq old-state c-state-cache)
2118
2119 ;; There's a cached state with a containing paren. Pop off
2120 ;; the stale containing sexps from it by going forward out of
2121 ;; parens as far as possible.
2122 (narrow-to-region (point-min) here)
2123 (let (placeholder pair-beg)
2124 (while (and c-state-cache
2125 (setq placeholder
2126 (c-up-list-forward last-pos)))
2127 (setq last-pos placeholder)
2128 (if (consp (car c-state-cache))
2129 (setq pair-beg (car-safe (cdr c-state-cache))
2130 c-state-cache (cdr-safe (cdr c-state-cache)))
2131 (setq pair-beg (car c-state-cache)
2132 c-state-cache (cdr c-state-cache))))
2133
2134 (when (and pair-beg (eq (char-after pair-beg) ?{))
2135 ;; The last paren pair we moved out from was a brace
2136 ;; pair. Modify the state to record this as a closed
2137 ;; pair now.
2138 (if (consp (car-safe c-state-cache))
2139 (setq c-state-cache (cdr c-state-cache)))
2140 (setq c-state-cache (cons (cons pair-beg last-pos)
2141 c-state-cache))))
2142
2143 ;; Check if the preceding balanced paren is within a
2144 ;; macro; it should be ignored if we're outside the
2145 ;; macro. There's no need to check any further upwards;
2146 ;; if the macro contains an unbalanced opening paren then
2147 ;; we're smoked anyway.
2148 (when (and (<= (point) in-macro-start)
2149 (consp (car c-state-cache)))
2150 (save-excursion
2151 (goto-char (car (car c-state-cache)))
2152 (when (c-beginning-of-macro)
2153 (setq here (point)
2154 c-state-cache (cdr c-state-cache)))))
2155
2156 (unless (eq c-state-cache old-state)
2157 ;; Have to adjust the cached good position if state has been
2158 ;; popped off.
2159 (setq c-state-cache-good-pos
2160 (if c-state-cache
2161 (if (consp (car c-state-cache))
2162 (cdr (car c-state-cache))
2163 (1+ (car c-state-cache)))
2164 1)
2165 old-state c-state-cache))
2166
2167 (when c-state-cache
2168 (setq pos last-pos)))
2169
2170 ;; Get the fallback start position.
2171 (unless pos
2172 (setq pos (c-get-fallback-start-pos here)
2173 c-state-cache nil
2174 c-state-cache-good-pos 1))
d9e94c22 2175
a66cd3ee 2176 (narrow-to-region (point-min) here)
d9e94c22 2177
a66cd3ee 2178 (while pos
e33c01bb 2179 (setq save-pos pos
0386b551
AM
2180 brace-pair-open nil)
2181
2182 ;; Find the balanced brace pairs. This loop is hot, so it
2183 ;; does ugly tricks to go faster.
2184 (c-safe
2185 (let (set-good-pos set-brace-pair)
2186 (while t
2187 (setq last-pos nil
2188 last-pos (scan-lists pos 1 -1)) ; Might signal.
2189 (setq pos (scan-lists last-pos 1 1) ; Might signal.
2190 set-good-pos (< pos here-bol)
2191 set-brace-pair (eq (char-before last-pos) ?{))
2192
2193 ;; Update the cached good position and record the brace
2194 ;; pair, whichever is applicable for the paren we've
2195 ;; just jumped over. But first check that it isn't
2196 ;; inside a macro and the point isn't inside the same
2197 ;; one.
2198 (when (and (or set-good-pos set-brace-pair)
2199 (or (>= pos in-macro-start)
2200 (save-excursion
2201 (goto-char pos)
2202 (not (c-beginning-of-macro)))))
2203 (if set-good-pos
2204 (setq c-state-cache-good-pos pos))
2205 (if set-brace-pair
2206 (setq brace-pair-open last-pos
2207 brace-pair-close pos))))))
d9e94c22 2208
a66cd3ee 2209 ;; Record the last brace pair.
0386b551
AM
2210 (when brace-pair-open
2211 (let ((head (car-safe c-state-cache)))
2212 (if (consp head)
2213 (progn
2214 (setcar head (1- brace-pair-open))
2215 (setcdr head brace-pair-close))
2216 (setq c-state-cache (cons (cons (1- brace-pair-open)
2217 brace-pair-close)
2218 c-state-cache)))))
d9e94c22 2219
a66cd3ee
MS
2220 (if last-pos
2221 ;; Prepare to loop, but record the open paren only if it's
d9e94c22 2222 ;; outside a macro or within the same macro as point, and
2a15eb73 2223 ;; if it is a legitimate open paren and not some character
d9e94c22 2224 ;; that got an open paren syntax-table property.
a66cd3ee
MS
2225 (progn
2226 (setq pos last-pos)
0386b551
AM
2227 (when (and (or (>= last-pos in-macro-start)
2228 (save-excursion
2229 (goto-char last-pos)
2230 (not (c-beginning-of-macro))))
2231 ;; Check for known types of parens that we
2232 ;; want to record. The syntax table is not to
2233 ;; be trusted here since the caller might be
2234 ;; using e.g. `c++-template-syntax-table'.
2235 (memq (char-before last-pos) '(?{ ?\( ?\[)))
2236 (if (< last-pos here-bol)
2237 (setq c-state-cache-good-pos last-pos))
2238 (setq c-state-cache (cons (1- last-pos) c-state-cache))))
d9e94c22 2239
a66cd3ee
MS
2240 (if (setq last-pos (c-up-list-forward pos))
2241 ;; Found a close paren without a corresponding opening
2242 ;; one. Maybe we didn't go back far enough, so try to
2243 ;; scan backward for the start paren and then start over.
2244 (progn
2245 (setq pos (c-up-list-backward pos)
0386b551
AM
2246 c-state-cache nil
2247 c-state-cache-good-pos c-state-cache-start)
e33c01bb
MS
2248 (when (or (not pos)
2249 ;; Emacs (up to at least 21.2) can get confused by
2250 ;; open parens in column zero inside comments: The
2251 ;; sexp functions can then misbehave and bring us
2252 ;; back to the same point again. Check this so that
2253 ;; we don't get an infinite loop.
2254 (>= pos save-pos))
a66cd3ee
MS
2255 (setq pos last-pos
2256 c-parsing-error
2257 (format "Unbalanced close paren at line %d"
2258 (1+ (count-lines (point-min)
2259 (c-point 'bol last-pos)))))))
2260 (setq pos nil))))
d9e94c22 2261
0386b551 2262 ;;(message "c-parse-state: %S end: %S" c-state-cache c-state-cache-good-pos)
a66cd3ee
MS
2263 c-state-cache)))
2264
2265;; Debug tool to catch cache inconsistencies.
2266(defvar c-debug-parse-state nil)
2267(unless (fboundp 'c-real-parse-state)
2268 (fset 'c-real-parse-state (symbol-function 'c-parse-state)))
2269(cc-bytecomp-defun c-real-parse-state)
2270(defun c-debug-parse-state ()
2271 (let ((res1 (c-real-parse-state)) res2)
0386b551
AM
2272 (let ((c-state-cache nil)
2273 (c-state-cache-start 1)
2274 (c-state-cache-good-pos 1))
a66cd3ee
MS
2275 (setq res2 (c-real-parse-state)))
2276 (unless (equal res1 res2)
0386b551
AM
2277 ;; The cache can actually go further back due to the ad-hoc way
2278 ;; the first paren is found, so try to whack off a bit of its
2279 ;; start before complaining.
2280 (save-excursion
2281 (goto-char (or (c-least-enclosing-brace res2) (point)))
2282 (c-beginning-of-defun-1)
2283 (while (not (or (bobp) (eq (char-after) ?{)))
2284 (c-beginning-of-defun-1))
2285 (unless (equal (c-whack-state-before (point) res1) res2)
2286 (message (concat "c-parse-state inconsistency: "
2287 "using cache: %s, from scratch: %s")
2288 res1 res2))))
a66cd3ee
MS
2289 res1))
2290(defun c-toggle-parse-state-debug (&optional arg)
2291 (interactive "P")
2292 (setq c-debug-parse-state (c-calculate-state arg c-debug-parse-state))
2293 (fset 'c-parse-state (symbol-function (if c-debug-parse-state
2294 'c-debug-parse-state
2295 'c-real-parse-state)))
2296 (c-keep-region-active))
0386b551
AM
2297(when c-debug-parse-state
2298 (c-toggle-parse-state-debug 1))
a66cd3ee 2299
d9e94c22
MS
2300(defun c-whack-state-before (bufpos paren-state)
2301 ;; Whack off any state information from PAREN-STATE which lies
2302 ;; before BUFPOS. Not destructive on PAREN-STATE.
d9e94c22
MS
2303 (let* ((newstate (list nil))
2304 (ptr newstate)
2305 car)
2306 (while paren-state
2307 (setq car (car paren-state)
2308 paren-state (cdr paren-state))
2309 (if (< (if (consp car) (car car) car) bufpos)
2310 (setq paren-state nil)
2311 (setcdr ptr (list car))
2312 (setq ptr (cdr ptr))))
2313 (cdr newstate)))
2314
2315(defun c-whack-state-after (bufpos paren-state)
2316 ;; Whack off any state information from PAREN-STATE which lies at or
2317 ;; after BUFPOS. Not destructive on PAREN-STATE.
d9e94c22
MS
2318 (catch 'done
2319 (while paren-state
2320 (let ((car (car paren-state)))
2321 (if (consp car)
2322 ;; just check the car, because in a balanced brace
2323 ;; expression, it must be impossible for the corresponding
2324 ;; close brace to be before point, but the open brace to
2325 ;; be after.
2326 (if (<= bufpos (car car))
2327 nil ; whack it off
2328 (if (< bufpos (cdr car))
2329 ;; its possible that the open brace is before
2330 ;; bufpos, but the close brace is after. In that
2331 ;; case, convert this to a non-cons element. The
2332 ;; rest of the state is before bufpos, so we're
2333 ;; done.
2334 (throw 'done (cons (car car) (cdr paren-state)))
2335 ;; we know that both the open and close braces are
2336 ;; before bufpos, so we also know that everything else
2337 ;; on state is before bufpos.
2338 (throw 'done paren-state)))
2339 (if (<= bufpos car)
2340 nil ; whack it off
2341 ;; it's before bufpos, so everything else should too.
2342 (throw 'done paren-state)))
2343 (setq paren-state (cdr paren-state)))
2344 nil)))
2345
2346(defun c-most-enclosing-brace (paren-state &optional bufpos)
2347 ;; Return the bufpos of the innermost enclosing open paren before
0386b551 2348 ;; bufpos, or nil if none was found.
d9e94c22
MS
2349 (let (enclosingp)
2350 (or bufpos (setq bufpos 134217727))
2351 (while paren-state
2352 (setq enclosingp (car paren-state)
2353 paren-state (cdr paren-state))
2354 (if (or (consp enclosingp)
2355 (>= enclosingp bufpos))
2356 (setq enclosingp nil)
d9e94c22
MS
2357 (setq paren-state nil)))
2358 enclosingp))
2359
0386b551
AM
2360(defun c-least-enclosing-brace (paren-state)
2361 ;; Return the bufpos of the outermost enclosing open paren, or nil
2362 ;; if none was found.
d9e94c22 2363 (let (pos elem)
d9e94c22
MS
2364 (while paren-state
2365 (setq elem (car paren-state)
2366 paren-state (cdr paren-state))
0386b551
AM
2367 (if (integerp elem)
2368 (setq pos elem)))
d9e94c22
MS
2369 pos))
2370
2371(defun c-safe-position (bufpos paren-state)
0386b551
AM
2372 ;; Return the closest "safe" position recorded on PAREN-STATE that
2373 ;; is higher up than BUFPOS. Return nil if PAREN-STATE doesn't
2374 ;; contain any. Return nil if BUFPOS is nil, which is useful to
2375 ;; find the closest limit before a given limit that might be nil.
d9e94c22 2376 ;;
0386b551
AM
2377 ;; A "safe" position is a position at or after a recorded open
2378 ;; paren, or after a recorded close paren. The returned position is
2379 ;; thus either the first position after a close brace, or the first
2380 ;; position after an enclosing paren, or at the enclosing paren in
2381 ;; case BUFPOS is immediately after it.
d9e94c22
MS
2382 (when bufpos
2383 (let (elem)
2384 (catch 'done
2385 (while paren-state
2386 (setq elem (car paren-state))
2387 (if (consp elem)
2388 (cond ((< (cdr elem) bufpos)
2389 (throw 'done (cdr elem)))
2390 ((< (car elem) bufpos)
2391 ;; See below.
2392 (throw 'done (min (1+ (car elem)) bufpos))))
2393 (if (< elem bufpos)
2394 ;; elem is the position at and not after the opening paren, so
2395 ;; we can go forward one more step unless it's equal to
2396 ;; bufpos. This is useful in some cases avoid an extra paren
2397 ;; level between the safe position and bufpos.
2398 (throw 'done (min (1+ elem) bufpos))))
2399 (setq paren-state (cdr paren-state)))))))
2400
2401(defun c-beginning-of-syntax ()
2402 ;; This is used for `font-lock-beginning-of-syntax-function'. It
2403 ;; goes to the closest previous point that is known to be outside
2404 ;; any string literal or comment. `c-state-cache' is used if it has
2405 ;; a position in the vicinity.
2406 (let* ((paren-state c-state-cache)
2407 elem
2408
2409 (pos (catch 'done
2410 ;; Note: Similar code in `c-safe-position'. The
2411 ;; difference is that we accept a safe position at
2412 ;; the point and don't bother to go forward past open
2413 ;; parens.
2414 (while paren-state
2415 (setq elem (car paren-state))
2416 (if (consp elem)
2417 (cond ((<= (cdr elem) (point))
2418 (throw 'done (cdr elem)))
2419 ((<= (car elem) (point))
2420 (throw 'done (car elem))))
2421 (if (<= elem (point))
2422 (throw 'done elem)))
2423 (setq paren-state (cdr paren-state)))
2424 (point-min))))
2425
2426 (if (> pos (- (point) 4000))
2427 (goto-char pos)
2428 ;; The position is far back. Try `c-beginning-of-defun-1'
2429 ;; (although we can't be entirely sure it will go to a position
2430 ;; outside a comment or string in current emacsen). FIXME:
2431 ;; Consult `syntax-ppss' here.
2432 (c-beginning-of-defun-1)
2433 (if (< (point) pos)
2434 (goto-char pos)))))
2435
2436\f
2437;; Tools for scanning identifiers and other tokens.
2438
2439(defun c-on-identifier ()
2440 "Return non-nil if the point is on or directly after an identifier.
2441Keywords are recognized and not considered identifiers. If an
2442identifier is detected, the returned value is its starting position.
0386b551
AM
2443If an identifier ends at the point and another begins at it \(can only
2444happen in Pike) then the point for the preceding one is returned.
d9e94c22 2445
0386b551
AM
2446Note that this function might do hidden buffer changes. See the
2447comment at the start of cc-engine.el for more info."
2448
2449 ;; FIXME: Shouldn't this function handle "operator" in C++?
d9e94c22
MS
2450
2451 (save-excursion
0386b551
AM
2452 (skip-syntax-backward "w_")
2453
2454 (or
2455
2456 ;; Check for a normal (non-keyword) identifier.
2457 (and (looking-at c-symbol-start)
2458 (not (looking-at c-keywords-regexp))
2459 (point))
2460
2461 (when (c-major-mode-is 'pike-mode)
2462 ;; Handle the `<operator> syntax in Pike.
2463 (let ((pos (point)))
2464 (skip-chars-backward "-!%&*+/<=>^|~[]()")
2465 (and (if (< (skip-chars-backward "`") 0)
2466 t
2467 (goto-char pos)
2468 (eq (char-after) ?\`))
2469 (looking-at c-symbol-key)
2470 (>= (match-end 0) pos)
2471 (point))))
2472
2473 ;; Handle the "operator +" syntax in C++.
2474 (when (and c-overloadable-operators-regexp
2475 (= (c-backward-token-2 0) 0))
2476
2477 (cond ((and (looking-at c-overloadable-operators-regexp)
51c9af45 2478 (or (not c-opt-op-identifier-prefix)
0386b551 2479 (and (= (c-backward-token-2 1) 0)
51c9af45 2480 (looking-at c-opt-op-identifier-prefix))))
0386b551
AM
2481 (point))
2482
2483 ((save-excursion
51c9af45
AM
2484 (and c-opt-op-identifier-prefix
2485 (looking-at c-opt-op-identifier-prefix)
0386b551
AM
2486 (= (c-forward-token-2 1) 0)
2487 (looking-at c-overloadable-operators-regexp)))
2488 (point))))
2489
2490 )))
d9e94c22
MS
2491
2492(defsubst c-simple-skip-symbol-backward ()
2493 ;; If the point is at the end of a symbol then skip backward to the
2494 ;; beginning of it. Don't move otherwise. Return non-nil if point
2495 ;; moved.
0386b551
AM
2496 ;;
2497 ;; This function might do hidden buffer changes.
d9e94c22
MS
2498 (or (< (skip-syntax-backward "w_") 0)
2499 (and (c-major-mode-is 'pike-mode)
2500 ;; Handle the `<operator> syntax in Pike.
2501 (let ((pos (point)))
2a15eb73 2502 (if (and (< (skip-chars-backward "-!%&*+/<=>^|~[]()") 0)
d9e94c22
MS
2503 (< (skip-chars-backward "`") 0)
2504 (looking-at c-symbol-key)
2505 (>= (match-end 0) pos))
2506 t
2507 (goto-char pos)
2508 nil)))))
2509
0386b551 2510(defun c-beginning-of-current-token (&optional back-limit)
d9e94c22
MS
2511 ;; Move to the beginning of the current token. Do not move if not
2512 ;; in the middle of one. BACK-LIMIT may be used to bound the
2513 ;; backward search; if given it's assumed to be at the boundary
580fba94
AM
2514 ;; between two tokens. Return non-nil if the point is move, nil
2515 ;; otherwise.
0386b551
AM
2516 ;;
2517 ;; This function might do hidden buffer changes.
d9e94c22 2518 (let ((start (point)))
580fba94
AM
2519 (if (looking-at "\\w\\|\\s_")
2520 (skip-syntax-backward "w_" back-limit)
2521 (when (< (skip-syntax-backward ".()" back-limit) 0)
2522 (while (let ((pos (or (and (looking-at c-nonsymbol-token-regexp)
2523 (match-end 0))
2524 ;; `c-nonsymbol-token-regexp' should always match
2525 ;; since we've skipped backward over punctuator
2526 ;; or paren syntax, but consume one char in case
2527 ;; it doesn't so that we don't leave point before
2528 ;; some earlier incorrect token.
2529 (1+ (point)))))
2530 (if (<= pos start)
2531 (goto-char pos))))))
2532 (< (point) start)))
d9e94c22 2533
ff959bab 2534(defun c-end-of-current-token (&optional back-limit)
d9e94c22
MS
2535 ;; Move to the end of the current token. Do not move if not in the
2536 ;; middle of one. BACK-LIMIT may be used to bound the backward
2537 ;; search; if given it's assumed to be at the boundary between two
ff959bab 2538 ;; tokens. Return non-nil if the point is moved, nil otherwise.
0386b551
AM
2539 ;;
2540 ;; This function might do hidden buffer changes.
d9e94c22
MS
2541 (let ((start (point)))
2542 (cond ((< (skip-syntax-backward "w_" (1- start)) 0)
2543 (skip-syntax-forward "w_"))
2544 ((< (skip-syntax-backward ".()" back-limit) 0)
2545 (while (progn
2546 (if (looking-at c-nonsymbol-token-regexp)
2547 (goto-char (match-end 0))
2548 ;; `c-nonsymbol-token-regexp' should always match since
2549 ;; we've skipped backward over punctuator or paren
2550 ;; syntax, but move forward in case it doesn't so that
2551 ;; we don't leave point earlier than we started with.
2552 (forward-char))
ff959bab
MS
2553 (< (point) start)))))
2554 (> (point) start)))
d9e94c22
MS
2555
2556(defconst c-jump-syntax-balanced
2557 (if (memq 'gen-string-delim c-emacs-features)
2558 "\\w\\|\\s_\\|\\s\(\\|\\s\)\\|\\s\"\\|\\s|"
2559 "\\w\\|\\s_\\|\\s\(\\|\\s\)\\|\\s\""))
2560
2561(defconst c-jump-syntax-unbalanced
2562 (if (memq 'gen-string-delim c-emacs-features)
2563 "\\w\\|\\s_\\|\\s\"\\|\\s|"
2564 "\\w\\|\\s_\\|\\s\""))
2565
2566(defun c-forward-token-2 (&optional count balanced limit)
2567 "Move forward by tokens.
2568A token is defined as all symbols and identifiers which aren't
2569syntactic whitespace \(note that multicharacter tokens like \"==\" are
2570treated properly). Point is always either left at the beginning of a
2571token or not moved at all. COUNT specifies the number of tokens to
2572move; a negative COUNT moves in the opposite direction. A COUNT of 0
2573moves to the next token beginning only if not already at one. If
2574BALANCED is true, move over balanced parens, otherwise move into them.
2575Also, if BALANCED is true, never move out of an enclosing paren.
2576
2577LIMIT sets the limit for the movement and defaults to the point limit.
2578The case when LIMIT is set in the middle of a token, comment or macro
2579is handled correctly, i.e. the point won't be left there.
2580
2581Return the number of tokens left to move \(positive or negative). If
2582BALANCED is true, a move over a balanced paren counts as one. Note
2583that if COUNT is 0 and no appropriate token beginning is found, 1 will
2584be returned. Thus, a return value of 0 guarantees that point is at
2585the requested position and a return value less \(without signs) than
0386b551
AM
2586COUNT guarantees that point is at the beginning of some token.
2587
2588Note that this function might do hidden buffer changes. See the
2589comment at the start of cc-engine.el for more info."
d9e94c22
MS
2590
2591 (or count (setq count 1))
2592 (if (< count 0)
2593 (- (c-backward-token-2 (- count) balanced limit))
2594
2595 (let ((jump-syntax (if balanced
2596 c-jump-syntax-balanced
2597 c-jump-syntax-unbalanced))
2598 (last (point))
2599 (prev (point)))
2600
2601 (if (zerop count)
2602 ;; If count is zero we should jump if in the middle of a token.
2603 (c-end-of-current-token))
2604
2605 (save-restriction
2606 (if limit (narrow-to-region (point-min) limit))
2607 (if (/= (point)
2608 (progn (c-forward-syntactic-ws) (point)))
2609 ;; Skip whitespace. Count this as a move if we did in
2610 ;; fact move.
2611 (setq count (max (1- count) 0)))
2612
2613 (if (eobp)
2614 ;; Moved out of bounds. Make sure the returned count isn't zero.
2615 (progn
2616 (if (zerop count) (setq count 1))
2617 (goto-char last))
2618
2619 ;; Use `condition-case' to avoid having the limit tests
2620 ;; inside the loop.
2621 (condition-case nil
2622 (while (and
2623 (> count 0)
2624 (progn
2625 (setq last (point))
2626 (cond ((looking-at jump-syntax)
2627 (goto-char (scan-sexps (point) 1))
2628 t)
2629 ((looking-at c-nonsymbol-token-regexp)
2630 (goto-char (match-end 0))
2631 t)
2632 ;; `c-nonsymbol-token-regexp' above should always
2633 ;; match if there are correct tokens. Try to
2634 ;; widen to see if the limit was set in the
2635 ;; middle of one, else fall back to treating
2636 ;; the offending thing as a one character token.
2637 ((and limit
2638 (save-restriction
2639 (widen)
2640 (looking-at c-nonsymbol-token-regexp)))
2641 nil)
2642 (t
2643 (forward-char)
2644 t))))
2645 (c-forward-syntactic-ws)
2646 (setq prev last
2647 count (1- count)))
2648 (error (goto-char last)))
2649
2650 (when (eobp)
2651 (goto-char prev)
2652 (setq count (1+ count)))))
2653
2654 count)))
2655
2656(defun c-backward-token-2 (&optional count balanced limit)
2657 "Move backward by tokens.
2658See `c-forward-token-2' for details."
2659
2660 (or count (setq count 1))
2661 (if (< count 0)
2662 (- (c-forward-token-2 (- count) balanced limit))
2663
2664 (or limit (setq limit (point-min)))
2665 (let ((jump-syntax (if balanced
2666 c-jump-syntax-balanced
2667 c-jump-syntax-unbalanced))
2668 (last (point)))
2669
2670 (if (zerop count)
2671 ;; The count is zero so try to skip to the beginning of the
2672 ;; current token.
2673 (if (> (point)
2674 (progn (c-beginning-of-current-token) (point)))
2675 (if (< (point) limit)
2676 ;; The limit is inside the same token, so return 1.
2677 (setq count 1))
2678
2679 ;; We're not in the middle of a token. If there's
2680 ;; whitespace after the point then we must move backward,
2681 ;; so set count to 1 in that case.
2682 (and (looking-at c-syntactic-ws-start)
2683 ;; If we're looking at a '#' that might start a cpp
2684 ;; directive then we have to do a more elaborate check.
2685 (or (/= (char-after) ?#)
2686 (not c-opt-cpp-prefix)
2687 (save-excursion
2688 (and (= (point)
2689 (progn (beginning-of-line)
2690 (looking-at "[ \t]*")
2691 (match-end 0)))
2692 (or (bobp)
2693 (progn (backward-char)
2694 (not (eq (char-before) ?\\)))))))
2695 (setq count 1))))
2696
2697 ;; Use `condition-case' to avoid having to check for buffer
2698 ;; limits in `backward-char', `scan-sexps' and `goto-char' below.
2699 (condition-case nil
2700 (while (and
2701 (> count 0)
2702 (progn
2703 (c-backward-syntactic-ws)
2704 (backward-char)
2705 (if (looking-at jump-syntax)
2706 (goto-char (scan-sexps (1+ (point)) -1))
2707 ;; This can be very inefficient if there's a long
2708 ;; sequence of operator tokens without any separation.
2709 ;; That doesn't happen in practice, anyway.
2710 (c-beginning-of-current-token))
2711 (>= (point) limit)))
2712 (setq last (point)
2713 count (1- count)))
2714 (error (goto-char last)))
2715
2716 (if (< (point) limit)
2717 (goto-char last))
2718
2719 count)))
2720
2721(defun c-forward-token-1 (&optional count balanced limit)
2722 "Like `c-forward-token-2' but doesn't treat multicharacter operator
2723tokens like \"==\" as single tokens, i.e. all sequences of symbol
2724characters are jumped over character by character. This function is
2725for compatibility only; it's only a wrapper over `c-forward-token-2'."
2726 (let ((c-nonsymbol-token-regexp "\\s.\\|\\s\(\\|\\s\)"))
2727 (c-forward-token-2 count balanced limit)))
2728
2729(defun c-backward-token-1 (&optional count balanced limit)
2730 "Like `c-backward-token-2' but doesn't treat multicharacter operator
2731tokens like \"==\" as single tokens, i.e. all sequences of symbol
2732characters are jumped over character by character. This function is
2733for compatibility only; it's only a wrapper over `c-backward-token-2'."
2734 (let ((c-nonsymbol-token-regexp "\\s.\\|\\s\(\\|\\s\)"))
2735 (c-backward-token-2 count balanced limit)))
2736
2737\f
2738;; Tools for doing searches restricted to syntactically relevant text.
2739
2740(defun c-syntactic-re-search-forward (regexp &optional bound noerror
2741 paren-level not-inside-token
2742 lookbehind-submatch)
2743 "Like `re-search-forward', but only report matches that are found
2744in syntactically significant text. I.e. matches in comments, macros
2745or string literals are ignored. The start point is assumed to be
2746outside any comment, macro or string literal, or else the content of
2747that region is taken as syntactically significant text.
2748
2749If PAREN-LEVEL is non-nil, an additional restriction is added to
2a15eb73
MS
2750ignore matches in nested paren sexps. The search will also not go
2751outside the current list sexp, which has the effect that if the point
2752should be moved to BOUND when no match is found \(i.e. NOERROR is
2753neither nil nor t), then it will be at the closing paren if the end of
2754the current list sexp is encountered first.
d9e94c22
MS
2755
2756If NOT-INSIDE-TOKEN is non-nil, matches in the middle of tokens are
2757ignored. Things like multicharacter operators and special symbols
2758\(e.g. \"`()\" in Pike) are handled but currently not floating point
2759constants.
2760
2761If LOOKBEHIND-SUBMATCH is non-nil, it's taken as a number of a
2762subexpression in REGEXP. The end of that submatch is used as the
2763position to check for syntactic significance. If LOOKBEHIND-SUBMATCH
2764isn't used or if that subexpression didn't match then the start
2765position of the whole match is used instead. The \"look behind\"
2766subexpression is never tested before the starting position, so it
2767might be a good idea to include \\=\\= as a match alternative in it.
2768
2769Optimization note: Matches might be missed if the \"look behind\"
2a15eb73 2770subexpression can match the end of nonwhite syntactic whitespace,
d9e94c22 2771i.e. the end of comments or cpp directives. This since the function
2a15eb73
MS
2772skips over such things before resuming the search. It's on the other
2773hand not safe to assume that the \"look behind\" subexpression never
2774matches syntactic whitespace.
2775
2776Bug: Unbalanced parens inside cpp directives are currently not handled
2777correctly \(i.e. they don't get ignored as they should) when
0386b551
AM
2778PAREN-LEVEL is set.
2779
2780Note that this function might do hidden buffer changes. See the
2781comment at the start of cc-engine.el for more info."
d9e94c22
MS
2782
2783 (or bound (setq bound (point-max)))
2784 (if paren-level (setq paren-level -1))
2785
2786 ;;(message "c-syntactic-re-search-forward %s %s %S" (point) bound regexp)
2787
2788 (let ((start (point))
2a15eb73
MS
2789 tmp
2790 ;; Start position for the last search.
2791 search-pos
2792 ;; The `parse-partial-sexp' state between the start position
2793 ;; and the point.
2794 state
2795 ;; The current position after the last state update. The next
2796 ;; `parse-partial-sexp' continues from here.
2797 (state-pos (point))
2798 ;; The position at which to check the state and the state
2799 ;; there. This is separate from `state-pos' since we might
2800 ;; need to back up before doing the next search round.
2801 check-pos check-state
2802 ;; Last position known to end a token.
d9e94c22 2803 (last-token-end-pos (point-min))
2a15eb73
MS
2804 ;; Set when a valid match is found.
2805 found)
d9e94c22
MS
2806
2807 (condition-case err
2808 (while
2809 (and
2a15eb73
MS
2810 (progn
2811 (setq search-pos (point))
2812 (re-search-forward regexp bound noerror))
d9e94c22
MS
2813
2814 (progn
2a15eb73
MS
2815 (setq state (parse-partial-sexp
2816 state-pos (match-beginning 0) paren-level nil state)
2817 state-pos (point))
d9e94c22 2818 (if (setq check-pos (and lookbehind-submatch
2a15eb73
MS
2819 (or (not paren-level)
2820 (>= (car state) 0))
d9e94c22
MS
2821 (match-end lookbehind-submatch)))
2822 (setq check-state (parse-partial-sexp
2a15eb73
MS
2823 state-pos check-pos paren-level nil state))
2824 (setq check-pos state-pos
d9e94c22
MS
2825 check-state state))
2826
2a15eb73
MS
2827 ;; NOTE: If we got a look behind subexpression and get
2828 ;; an insignificant match in something that isn't
d9e94c22
MS
2829 ;; syntactic whitespace (i.e. strings or in nested
2830 ;; parentheses), then we can never skip more than a
2a15eb73
MS
2831 ;; single character from the match start position
2832 ;; (i.e. `state-pos' here) before continuing the
2833 ;; search. That since the look behind subexpression
2834 ;; might match the end of the insignificant region in
2835 ;; the next search.
d9e94c22
MS
2836
2837 (cond
d9e94c22
MS
2838 ((elt check-state 7)
2839 ;; Match inside a line comment. Skip to eol. Use
2840 ;; `re-search-forward' instead of `skip-chars-forward' to get
2841 ;; the right bound behavior.
2842 (re-search-forward "[\n\r]" bound noerror))
2843
2844 ((elt check-state 4)
2845 ;; Match inside a block comment. Skip to the '*/'.
2846 (search-forward "*/" bound noerror))
2847
2848 ((and (not (elt check-state 5))
2849 (eq (char-before check-pos) ?/)
2a15eb73 2850 (not (c-get-char-property (1- check-pos) 'syntax-table))
d9e94c22
MS
2851 (memq (char-after check-pos) '(?/ ?*)))
2852 ;; Match in the middle of the opener of a block or line
2853 ;; comment.
2854 (if (= (char-after check-pos) ?/)
2855 (re-search-forward "[\n\r]" bound noerror)
2856 (search-forward "*/" bound noerror)))
2857
2a15eb73
MS
2858 ;; The last `parse-partial-sexp' above might have
2859 ;; stopped short of the real check position if the end
2860 ;; of the current sexp was encountered in paren-level
2861 ;; mode. The checks above are always false in that
2862 ;; case, and since they can do better skipping in
2863 ;; lookbehind-submatch mode, we do them before
2864 ;; checking the paren level.
2865
2866 ((and paren-level
2867 (/= (setq tmp (car check-state)) 0))
2868 ;; Check the paren level first since we're short of the
2869 ;; syntactic checking position if the end of the
2870 ;; current sexp was encountered by `parse-partial-sexp'.
2871 (if (> tmp 0)
2872
2873 ;; Inside a nested paren sexp.
2874 (if lookbehind-submatch
2875 ;; See the NOTE above.
2876 (progn (goto-char state-pos) t)
2877 ;; Skip out of the paren quickly.
2878 (setq state (parse-partial-sexp state-pos bound 0 nil state)
2879 state-pos (point)))
2880
2881 ;; Have exited the current paren sexp.
2882 (if noerror
2883 (progn
2884 ;; The last `parse-partial-sexp' call above
2885 ;; has left us just after the closing paren
2886 ;; in this case, so we can modify the bound
2887 ;; to leave the point at the right position
2888 ;; upon return.
2889 (setq bound (1- (point)))
2890 nil)
2891 (signal 'search-failed (list regexp)))))
2892
2893 ((setq tmp (elt check-state 3))
2894 ;; Match inside a string.
2895 (if (or lookbehind-submatch
2896 (not (integerp tmp)))
2897 ;; See the NOTE above.
2898 (progn (goto-char state-pos) t)
2899 ;; Skip to the end of the string before continuing.
2900 (let ((ender (make-string 1 tmp)) (continue t))
2901 (while (if (search-forward ender bound noerror)
2902 (progn
2903 (setq state (parse-partial-sexp
2904 state-pos (point) nil nil state)
2905 state-pos (point))
2906 (elt state 3))
2907 (setq continue nil)))
2908 continue)))
d9e94c22
MS
2909
2910 ((save-excursion
2911 (save-match-data
2912 (c-beginning-of-macro start)))
2913 ;; Match inside a macro. Skip to the end of it.
2914 (c-end-of-macro)
2915 (cond ((<= (point) bound) t)
2916 (noerror nil)
2a15eb73 2917 (t (signal 'search-failed (list regexp)))))
d9e94c22 2918
2a15eb73
MS
2919 ((and not-inside-token
2920 (or (< check-pos last-token-end-pos)
2921 (< check-pos
2922 (save-excursion
2923 (goto-char check-pos)
2924 (save-match-data
2925 (c-end-of-current-token last-token-end-pos))
2926 (setq last-token-end-pos (point))))))
2927 ;; Inside a token.
2928 (if lookbehind-submatch
2929 ;; See the NOTE above.
2930 (goto-char state-pos)
2931 (goto-char (min last-token-end-pos bound))))
d9e94c22
MS
2932
2933 (t
2934 ;; A real match.
2935 (setq found t)
2a15eb73
MS
2936 nil)))
2937
2938 ;; Should loop to search again, but take care to avoid
2939 ;; looping on the same spot.
2940 (or (/= search-pos (point))
2941 (if (= (point) bound)
2942 (if noerror
2943 nil
2944 (signal 'search-failed (list regexp)))
2945 (forward-char)
2946 t))))
d9e94c22
MS
2947
2948 (error
2949 (goto-char start)
2950 (signal (car err) (cdr err))))
2951
2a15eb73 2952 ;;(message "c-syntactic-re-search-forward done %s" (or (match-end 0) (point)))
d9e94c22
MS
2953
2954 (if found
2955 (progn
2a15eb73
MS
2956 (goto-char (match-end 0))
2957 (match-end 0))
d9e94c22
MS
2958
2959 ;; Search failed. Set point as appropriate.
2a15eb73
MS
2960 (if (eq noerror t)
2961 (goto-char start)
2962 (goto-char bound))
d9e94c22
MS
2963 nil)))
2964
0386b551 2965(defun c-syntactic-skip-backward (skip-chars &optional limit paren-level)
d9e94c22
MS
2966 "Like `skip-chars-backward' but only look at syntactically relevant chars,
2967i.e. don't stop at positions inside syntactic whitespace or string
2968literals. Preprocessor directives are also ignored, with the exception
2969of the one that the point starts within, if any. If LIMIT is given,
0386b551
AM
2970it's assumed to be at a syntactically relevant position.
2971
2972If PAREN-LEVEL is non-nil, the function won't stop in nested paren
2973sexps, and the search will also not go outside the current paren sexp.
2974However, if LIMIT or the buffer limit is reached inside a nested paren
2975then the point will be left at the limit.
2976
2977Non-nil is returned if the point moved, nil otherwise.
2978
2979Note that this function might do hidden buffer changes. See the
2980comment at the start of cc-engine.el for more info."
d9e94c22
MS
2981
2982 (let ((start (point))
0386b551 2983 state
d9e94c22
MS
2984 ;; A list of syntactically relevant positions in descending
2985 ;; order. It's used to avoid scanning repeatedly over
2986 ;; potentially large regions with `parse-partial-sexp' to verify
2987 ;; each position.
2988 safe-pos-list
0386b551
AM
2989 ;; The position at the beginning of `safe-pos-list'.
2990 safe-pos
d9e94c22
MS
2991 ;; The result from `c-beginning-of-macro' at the start position or the
2992 ;; start position itself if it isn't within a macro. Evaluated on
2993 ;; demand.
0386b551
AM
2994 start-macro-beg
2995 ;; The earliest position after the current one with the same paren
2996 ;; level. Used only when `paren-level' is set.
2997 (paren-level-pos (point)))
d9e94c22
MS
2998
2999 (while (progn
3000 (while (and
3001 (< (skip-chars-backward skip-chars limit) 0)
3002
3003 ;; Use `parse-partial-sexp' from a safe position down to
3004 ;; the point to check if it's outside comments and
3005 ;; strings.
0386b551 3006 (let ((pos (point)) state-2 pps-end-pos)
d9e94c22
MS
3007 ;; Pick a safe position as close to the point as
3008 ;; possible.
3009 ;;
3010 ;; FIXME: Consult `syntax-ppss' here if our
3011 ;; cache doesn't give a good position.
3012 (while (and safe-pos-list
3013 (> (car safe-pos-list) (point)))
3014 (setq safe-pos-list (cdr safe-pos-list)))
3015 (unless (setq safe-pos (car-safe safe-pos-list))
3016 (setq safe-pos (max (or (c-safe-position
3017 (point) (or c-state-cache
3018 (c-parse-state)))
3019 0)
3020 (point-min))
3021 safe-pos-list (list safe-pos)))
3022
0386b551
AM
3023 ;; Cache positions along the way to use if we have to
3024 ;; back up more. We cache every closing paren on the
3025 ;; same level. If the paren cache is relevant in this
3026 ;; region then we're typically already on the same
3027 ;; level as the target position. Note that we might
3028 ;; cache positions after opening parens in case
3029 ;; safe-pos is in a nested list. That's both uncommon
3030 ;; and harmless.
d9e94c22
MS
3031 (while (progn
3032 (setq state (parse-partial-sexp
3033 safe-pos pos 0))
3034 (< (point) pos))
d9e94c22
MS
3035 (setq safe-pos (point)
3036 safe-pos-list (cons safe-pos safe-pos-list)))
3037
3038 (cond
3039 ((or (elt state 3) (elt state 4))
3040 ;; Inside string or comment. Continue search at the
3041 ;; beginning of it.
0386b551 3042 (goto-char (elt state 8))
d9e94c22
MS
3043 t)
3044
0386b551
AM
3045 ((and paren-level
3046 (save-excursion
3047 (setq state-2 (parse-partial-sexp
3048 pos paren-level-pos -1)
3049 pps-end-pos (point))
3050 (/= (car state-2) 0)))
3051 ;; Not at the right level.
3052
3053 (if (and (< (car state-2) 0)
3054 ;; We stop above if we go out of a paren.
3055 ;; Now check whether it precedes or is
3056 ;; nested in the starting sexp.
3057 (save-excursion
3058 (setq state-2
3059 (parse-partial-sexp
3060 pps-end-pos paren-level-pos
3061 nil nil state-2))
3062 (< (car state-2) 0)))
3063
3064 ;; We've stopped short of the starting position
3065 ;; so the hit was inside a nested list. Go up
3066 ;; until we are at the right level.
3067 (condition-case nil
3068 (progn
3069 (goto-char (scan-lists pos -1
3070 (- (car state-2))))
3071 (setq paren-level-pos (point))
3072 (if (and limit (>= limit paren-level-pos))
3073 (progn
3074 (goto-char limit)
3075 nil)
3076 t))
3077 (error
3078 (goto-char (or limit (point-min)))
3079 nil))
3080
3081 ;; The hit was outside the list at the start
3082 ;; position. Go to the start of the list and exit.
3083 (goto-char (1+ (elt state-2 1)))
3084 nil))
3085
d9e94c22
MS
3086 ((c-beginning-of-macro limit)
3087 ;; Inside a macro.
3088 (if (< (point)
3089 (or start-macro-beg
3090 (setq start-macro-beg
3091 (save-excursion
3092 (goto-char start)
3093 (c-beginning-of-macro limit)
3094 (point)))))
3095 t
0386b551 3096
d9e94c22
MS
3097 ;; It's inside the same macro we started in so it's
3098 ;; a relevant match.
3099 (goto-char pos)
0386b551
AM
3100 nil)))))
3101
3102 ;; If the state contains the start of the containing sexp we
3103 ;; cache that position too, so that parse-partial-sexp in the
3104 ;; next run has a bigger chance of starting at the same level
3105 ;; as the target position and thus will get more good safe
3106 ;; positions into the list.
3107 (if (elt state 1)
3108 (setq safe-pos (1+ (elt state 1))
3109 safe-pos-list (cons safe-pos safe-pos-list))))
d9e94c22
MS
3110
3111 (> (point)
3112 (progn
3113 ;; Skip syntactic ws afterwards so that we don't stop at the
3114 ;; end of a comment if `skip-chars' is something like "^/".
3115 (c-backward-syntactic-ws)
3116 (point)))))
3117
0386b551
AM
3118 ;; We might want to extend this with more useful return values in
3119 ;; the future.
3120 (/= (point) start)))
3121
3122;; The following is an alternative implementation of
3123;; `c-syntactic-skip-backward' that uses backward movement to keep
3124;; track of the syntactic context. It turned out to be generally
3125;; slower than the one above which uses forward checks from earlier
3126;; safe positions.
3127;;
3128;;(defconst c-ssb-stop-re
3129;; ;; The regexp matching chars `c-syntactic-skip-backward' needs to
3130;; ;; stop at to avoid going into comments and literals.
3131;; (concat
3132;; ;; Match comment end syntax and string literal syntax. Also match
3133;; ;; '/' for block comment endings (not covered by comment end
3134;; ;; syntax).
3135;; "\\s>\\|/\\|\\s\""
3136;; (if (memq 'gen-string-delim c-emacs-features)
3137;; "\\|\\s|"
3138;; "")
3139;; (if (memq 'gen-comment-delim c-emacs-features)
3140;; "\\|\\s!"
3141;; "")))
3142;;
3143;;(defconst c-ssb-stop-paren-re
3144;; ;; Like `c-ssb-stop-re' but also stops at paren chars.
3145;; (concat c-ssb-stop-re "\\|\\s(\\|\\s)"))
3146;;
3147;;(defconst c-ssb-sexp-end-re
3148;; ;; Regexp matching the ending syntax of a complex sexp.
3149;; (concat c-string-limit-regexp "\\|\\s)"))
3150;;
3151;;(defun c-syntactic-skip-backward (skip-chars &optional limit paren-level)
3152;; "Like `skip-chars-backward' but only look at syntactically relevant chars,
3153;;i.e. don't stop at positions inside syntactic whitespace or string
3154;;literals. Preprocessor directives are also ignored. However, if the
3155;;point is within a comment, string literal or preprocessor directory to
3156;;begin with, its contents is treated as syntactically relevant chars.
3157;;If LIMIT is given, it limits the backward search and the point will be
3158;;left there if no earlier position is found.
3159;;
3160;;If PAREN-LEVEL is non-nil, the function won't stop in nested paren
3161;;sexps, and the search will also not go outside the current paren sexp.
3162;;However, if LIMIT or the buffer limit is reached inside a nested paren
3163;;then the point will be left at the limit.
3164;;
3165;;Non-nil is returned if the point moved, nil otherwise.
3166;;
3167;;Note that this function might do hidden buffer changes. See the
3168;;comment at the start of cc-engine.el for more info."
3169;;
3170;; (save-restriction
3171;; (when limit
3172;; (narrow-to-region limit (point-max)))
3173;;
3174;; (let ((start (point)))
3175;; (catch 'done
3176;; (while (let ((last-pos (point))
3177;; (stop-pos (progn
3178;; (skip-chars-backward skip-chars)
3179;; (point))))
3180;;
3181;; ;; Skip back over the same region as
3182;; ;; `skip-chars-backward' above, but keep to
3183;; ;; syntactically relevant positions.
3184;; (goto-char last-pos)
3185;; (while (and
3186;; ;; `re-search-backward' with a single char regexp
3187;; ;; should be fast.
3188;; (re-search-backward
3189;; (if paren-level c-ssb-stop-paren-re c-ssb-stop-re)
3190;; stop-pos 'move)
3191;;
3192;; (progn
3193;; (cond
3194;; ((looking-at "\\s(")
3195;; ;; `paren-level' is set and we've found the
3196;; ;; start of the containing paren.
3197;; (forward-char)
3198;; (throw 'done t))
3199;;
3200;; ((looking-at c-ssb-sexp-end-re)
3201;; ;; We're at the end of a string literal or paren
3202;; ;; sexp (if `paren-level' is set).
3203;; (forward-char)
3204;; (condition-case nil
3205;; (c-backward-sexp)
3206;; (error
3207;; (goto-char limit)
3208;; (throw 'done t))))
3209;;
3210;; (t
3211;; (forward-char)
3212;; ;; At the end of some syntactic ws or possibly
3213;; ;; after a plain '/' operator.
3214;; (let ((pos (point)))
3215;; (c-backward-syntactic-ws)
3216;; (if (= pos (point))
3217;; ;; Was a plain '/' operator. Go past it.
3218;; (backward-char)))))
3219;;
3220;; (> (point) stop-pos))))
3221;;
3222;; ;; Now the point is either at `stop-pos' or at some
3223;; ;; position further back if `stop-pos' was at a
3224;; ;; syntactically irrelevant place.
3225;;
3226;; ;; Skip additional syntactic ws so that we don't stop
3227;; ;; at the end of a comment if `skip-chars' is
3228;; ;; something like "^/".
3229;; (c-backward-syntactic-ws)
3230;;
3231;; (< (point) stop-pos))))
3232;;
3233;; ;; We might want to extend this with more useful return values
3234;; ;; in the future.
3235;; (/= (point) start))))
d9e94c22
MS
3236
3237\f
3238;; Tools for handling comments and string literals.
3239
3240(defun c-slow-in-literal (&optional lim detect-cpp)
3241 "Return the type of literal point is in, if any.
3242The return value is `c' if in a C-style comment, `c++' if in a C++
3243style comment, `string' if in a string literal, `pound' if DETECT-CPP
3244is non-nil and in a preprocessor line, or nil if somewhere else.
3245Optional LIM is used as the backward limit of the search. If omitted,
3246or nil, `c-beginning-of-defun' is used.
3247
3248The last point calculated is cached if the cache is enabled, i.e. if
3249`c-in-literal-cache' is bound to a two element vector.
3250
0386b551
AM
3251Note that this function might do hidden buffer changes. See the
3252comment at the start of cc-engine.el for more info."
3253
d9e94c22
MS
3254 (if (and (vectorp c-in-literal-cache)
3255 (= (point) (aref c-in-literal-cache 0)))
3256 (aref c-in-literal-cache 1)
3257 (let ((rtn (save-excursion
3258 (let* ((pos (point))
3259 (lim (or lim (progn
3260 (c-beginning-of-syntax)
3261 (point))))
3262 (state (parse-partial-sexp lim pos)))
3263 (cond
3264 ((elt state 3) 'string)
3265 ((elt state 4) (if (elt state 7) 'c++ 'c))
3266 ((and detect-cpp (c-beginning-of-macro lim)) 'pound)
3267 (t nil))))))
3268 ;; cache this result if the cache is enabled
3269 (if (not c-in-literal-cache)
3270 (setq c-in-literal-cache (vector (point) rtn)))
3271 rtn)))
3272
3273;; XEmacs has a built-in function that should make this much quicker.
3274;; I don't think we even need the cache, which makes our lives more
3275;; complicated anyway. In this case, lim is only used to detect
3276;; cpp directives.
3277;;
3278;; Note that there is a bug in Xemacs's buffer-syntactic-context when used in
3279;; conjunction with syntax-table-properties. The bug is present in, e.g.,
3280;; Xemacs 21.4.4. It manifested itself thus:
3281;;
3282;; Starting with an empty AWK Mode buffer, type
3283;; /regexp/ {<C-j>
3284;; Point gets wrongly left at column 0, rather than being indented to tab-width.
3285;;
3286;; AWK Mode is designed such that when the first / is typed, it gets the
3287;; syntax-table property "string fence". When the second / is typed, BOTH /s
3288;; are given the s-t property "string". However, buffer-syntactic-context
3289;; fails to take account of the change of the s-t property on the opening / to
3290;; "string", and reports that the { is within a string started by the second /.
3291;;
3292;; The workaround for this is for the AWK Mode initialisation to switch the
3293;; defalias for c-in-literal to c-slow-in-literal. This will slow down other
3294;; cc-modes in Xemacs whenever an awk-buffer has been initialised.
3295;;
3296;; (Alan Mackenzie, 2003/4/30).
3297
3298(defun c-fast-in-literal (&optional lim detect-cpp)
0386b551 3299 ;; This function might do hidden buffer changes.
d9e94c22
MS
3300 (let ((context (buffer-syntactic-context)))
3301 (cond
3302 ((eq context 'string) 'string)
3303 ((eq context 'comment) 'c++)
3304 ((eq context 'block-comment) 'c)
3305 ((and detect-cpp (save-excursion (c-beginning-of-macro lim))) 'pound))))
3306
3307(defalias 'c-in-literal
3308 (if (fboundp 'buffer-syntactic-context)
7bfc3fdb 3309 'c-fast-in-literal ; XEmacs
d9e94c22
MS
3310 'c-slow-in-literal)) ; GNU Emacs
3311
3312;; The defalias above isn't enough to shut up the byte compiler.
3313(cc-bytecomp-defun c-in-literal)
3314
3315(defun c-literal-limits (&optional lim near not-in-delimiter)
3316 "Return a cons of the beginning and end positions of the comment or
3317string surrounding point (including both delimiters), or nil if point
3318isn't in one. If LIM is non-nil, it's used as the \"safe\" position
3319to start parsing from. If NEAR is non-nil, then the limits of any
3320literal next to point is returned. \"Next to\" means there's only
3321spaces and tabs between point and the literal. The search for such a
3322literal is done first in forward direction. If NOT-IN-DELIMITER is
3323non-nil, the case when point is inside a starting delimiter won't be
3324recognized. This only has effect for comments, which have starting
3325delimiters with more than one character.
3326
0386b551
AM
3327Note that this function might do hidden buffer changes. See the
3328comment at the start of cc-engine.el for more info."
d9e94c22
MS
3329
3330 (save-excursion
3331 (let* ((pos (point))
3332 (lim (or lim (progn
3333 (c-beginning-of-syntax)
3334 (point))))
3335 (state (parse-partial-sexp lim pos)))
3336
0386b551
AM
3337 (cond ((elt state 3) ; String.
3338 (goto-char (elt state 8))
d9e94c22
MS
3339 (cons (point) (or (c-safe (c-forward-sexp 1) (point))
3340 (point-max))))
3341
0386b551
AM
3342 ((elt state 4) ; Comment.
3343 (goto-char (elt state 8))
d9e94c22
MS
3344 (cons (point) (progn (c-forward-single-comment) (point))))
3345
3346 ((and (not not-in-delimiter)
3347 (not (elt state 5))
3348 (eq (char-before) ?/)
3349 (looking-at "[/*]"))
3350 ;; We're standing in a comment starter.
3351 (backward-char 1)
3352 (cons (point) (progn (c-forward-single-comment) (point))))
3353
3354 (near
3355 (goto-char pos)
3356
3357 ;; Search forward for a literal.
3358 (skip-chars-forward " \t")
3359
3360 (cond
3361 ((looking-at c-string-limit-regexp) ; String.
3362 (cons (point) (or (c-safe (c-forward-sexp 1) (point))
3363 (point-max))))
3364
3365 ((looking-at c-comment-start-regexp) ; Line or block comment.
3366 (cons (point) (progn (c-forward-single-comment) (point))))
3367
3368 (t
3369 ;; Search backward.
3370 (skip-chars-backward " \t")
3371
3372 (let ((end (point)) beg)
3373 (cond
3374 ((save-excursion
3375 (< (skip-syntax-backward c-string-syntax) 0)) ; String.
3376 (setq beg (c-safe (c-backward-sexp 1) (point))))
3377
3378 ((and (c-safe (forward-char -2) t)
3379 (looking-at "*/"))
3380 ;; Block comment. Due to the nature of line
3381 ;; comments, they will always be covered by the
3382 ;; normal case above.
3383 (goto-char end)
3384 (c-backward-single-comment)
3385 ;; If LIM is bogus, beg will be bogus.
3386 (setq beg (point))))
3387
3388 (if beg (cons beg end))))))
3389 ))))
3390
0386b551
AM
3391;; In case external callers use this; it did have a docstring.
3392(defalias 'c-literal-limits-fast 'c-literal-limits)
d9e94c22 3393
0386b551
AM
3394(defun c-collect-line-comments (range)
3395 "If the argument is a cons of two buffer positions (such as returned by
3396`c-literal-limits'), and that range contains a C++ style line comment,
3397then an extended range is returned that contains all adjacent line
3398comments (i.e. all comments that starts in the same column with no
3399empty lines or non-whitespace characters between them). Otherwise the
3400argument is returned.
d9e94c22 3401
0386b551
AM
3402Note that this function might do hidden buffer changes. See the
3403comment at the start of cc-engine.el for more info."
d9e94c22
MS
3404
3405 (save-excursion
0386b551
AM
3406 (condition-case nil
3407 (if (and (consp range) (progn
3408 (goto-char (car range))
3409 (looking-at c-line-comment-starter)))
3410 (let ((col (current-column))
3411 (beg (point))
3412 (bopl (c-point 'bopl))
3413 (end (cdr range)))
3414 ;; Got to take care in the backward direction to handle
3415 ;; comments which are preceded by code.
3416 (while (and (c-backward-single-comment)
3417 (>= (point) bopl)
3418 (looking-at c-line-comment-starter)
3419 (= col (current-column)))
3420 (setq beg (point)
3421 bopl (c-point 'bopl)))
3422 (goto-char end)
3423 (while (and (progn (skip-chars-forward " \t")
3424 (looking-at c-line-comment-starter))
3425 (= col (current-column))
3426 (prog1 (zerop (forward-line 1))
3427 (setq end (point)))))
3428 (cons beg end))
3429 range)
3430 (error range))))
d9e94c22
MS
3431
3432(defun c-literal-type (range)
3433 "Convenience function that given the result of `c-literal-limits',
3434returns nil or the type of literal that the range surrounds. It's
3435much faster than using `c-in-literal' and is intended to be used when
3436you need both the type of a literal and its limits.
3437
0386b551
AM
3438Note that this function might do hidden buffer changes. See the
3439comment at the start of cc-engine.el for more info."
3440
d9e94c22
MS
3441 (if (consp range)
3442 (save-excursion
3443 (goto-char (car range))
3444 (cond ((looking-at c-string-limit-regexp) 'string)
3445 ((or (looking-at "//") ; c++ line comment
3446 (and (looking-at "\\s<") ; comment starter
3447 (looking-at "#"))) ; awk comment.
3448 'c++)
3449 (t 'c))) ; Assuming the range is valid.
3450 range))
3451
3452\f
3453;; `c-find-decl-spots' and accompanying stuff.
3454
3455;; Variables used in `c-find-decl-spots' to cache the search done for
3456;; the first declaration in the last call. When that function starts,
3457;; it needs to back up over syntactic whitespace to look at the last
3458;; token before the region being searched. That can sometimes cause
3459;; moves back and forth over a quite large region of comments and
3460;; macros, which would be repeated for each changed character when
3461;; we're called during fontification, since font-lock refontifies the
3462;; current line for each change. Thus it's worthwhile to cache the
3463;; first match.
3464;;
3465;; `c-find-decl-syntactic-pos' is a syntactically relevant position in
3466;; the syntactic whitespace less or equal to some start position.
3467;; There's no cached value if it's nil.
3468;;
3469;; `c-find-decl-match-pos' is the match position if
3470;; `c-find-decl-prefix-search' matched before the syntactic whitespace
3471;; at `c-find-decl-syntactic-pos', or nil if there's no such match.
3472(defvar c-find-decl-syntactic-pos nil)
3473(make-variable-buffer-local 'c-find-decl-syntactic-pos)
3474(defvar c-find-decl-match-pos nil)
3475(make-variable-buffer-local 'c-find-decl-match-pos)
3476
3477(defsubst c-invalidate-find-decl-cache (change-min-pos)
3478 (and c-find-decl-syntactic-pos
3479 (< change-min-pos c-find-decl-syntactic-pos)
3480 (setq c-find-decl-syntactic-pos nil)))
3481
3482; (defface c-debug-decl-spot-face
3483; '((t (:background "Turquoise")))
3484; "Debug face to mark the spots where `c-find-decl-spots' stopped.")
3485; (defface c-debug-decl-sws-face
3486; '((t (:background "Khaki")))
3487; "Debug face to mark the syntactic whitespace between the declaration
3488; spots and the preceding token end.")
3489
3490(defmacro c-debug-put-decl-spot-faces (match-pos decl-pos)
3491 (when (facep 'c-debug-decl-spot-face)
0386b551 3492 `(c-save-buffer-state ((match-pos ,match-pos) (decl-pos ,decl-pos))
d9e94c22
MS
3493 (c-debug-add-face (max match-pos (point-min)) decl-pos
3494 'c-debug-decl-sws-face)
3495 (c-debug-add-face decl-pos (min (1+ decl-pos) (point-max))
3496 'c-debug-decl-spot-face))))
3497(defmacro c-debug-remove-decl-spot-faces (beg end)
3498 (when (facep 'c-debug-decl-spot-face)
0386b551 3499 `(c-save-buffer-state ()
d9e94c22
MS
3500 (c-debug-remove-face ,beg ,end 'c-debug-decl-spot-face)
3501 (c-debug-remove-face ,beg ,end 'c-debug-decl-sws-face))))
3502
3503(defmacro c-find-decl-prefix-search ()
3504 ;; Macro used inside `c-find-decl-spots'. It ought to be a defun,
3505 ;; but it contains lots of free variables that refer to things
3506 ;; inside `c-find-decl-spots'. The point is left at `cfd-match-pos'
3507 ;; if there is a match, otherwise at `cfd-limit'.
0386b551
AM
3508 ;;
3509 ;; This macro might do hidden buffer changes.
d9e94c22
MS
3510
3511 '(progn
3512 ;; Find the next property match position if we haven't got one already.
3513 (unless cfd-prop-match
3514 (save-excursion
3515 (while (progn
3516 (goto-char (next-single-property-change
3517 (point) 'c-type nil cfd-limit))
3518 (and (< (point) cfd-limit)
3519 (not (eq (c-get-char-property (1- (point)) 'c-type)
3520 'c-decl-end)))))
3521 (setq cfd-prop-match (point))))
3522
0386b551
AM
3523 ;; Find the next `c-decl-prefix-or-start-re' match if we haven't
3524 ;; got one already.
d9e94c22 3525 (unless cfd-re-match
0386b551
AM
3526
3527 (if (> cfd-re-match-end (point))
3528 (goto-char cfd-re-match-end))
3529
3530 (while (if (setq cfd-re-match-end
3531 (re-search-forward c-decl-prefix-or-start-re
3532 cfd-limit 'move))
3533
3534 ;; Match. Check if it's inside a comment or string literal.
3535 (c-got-face-at
3536 (if (setq cfd-re-match (match-end 1))
3537 ;; Matched the end of a token preceding a decl spot.
3538 (progn
3539 (goto-char cfd-re-match)
3540 (1- cfd-re-match))
3541 ;; Matched a token that start a decl spot.
3542 (goto-char (match-beginning 0))
3543 (point))
3544 c-literal-faces)
3545
3546 ;; No match. Finish up and exit the loop.
3547 (setq cfd-re-match cfd-limit)
3548 nil)
3549
3550 ;; Skip out of comments and string literals.
d9e94c22
MS
3551 (while (progn
3552 (goto-char (next-single-property-change
0386b551 3553 (point) 'face nil cfd-limit))
d9e94c22 3554 (and (< (point) cfd-limit)
0386b551
AM
3555 (c-got-face-at (point) c-literal-faces)))))
3556
3557 ;; If we matched at the decl start, we have to back up over the
3558 ;; preceding syntactic ws to set `cfd-match-pos' and to catch
3559 ;; any decl spots in the syntactic ws.
d9e94c22 3560 (unless cfd-re-match
0386b551
AM
3561 (c-backward-syntactic-ws)
3562 (setq cfd-re-match (point))))
d9e94c22
MS
3563
3564 ;; Choose whichever match is closer to the start.
3565 (if (< cfd-re-match cfd-prop-match)
3566 (setq cfd-match-pos cfd-re-match
3567 cfd-re-match nil)
3568 (setq cfd-match-pos cfd-prop-match
3569 cfd-prop-match nil))
3570
3571 (goto-char cfd-match-pos)
3572
3573 (when (< cfd-match-pos cfd-limit)
3574 ;; Skip forward past comments only so we don't skip macros.
3575 (c-forward-comments)
3576 ;; Set the position to continue at. We can avoid going over
3577 ;; the comments skipped above a second time, but it's possible
3578 ;; that the comment skipping has taken us past `cfd-prop-match'
3579 ;; since the property might be used inside comments.
3580 (setq cfd-continue-pos (if cfd-prop-match
3581 (min cfd-prop-match (point))
3582 (point))))))
3583
3584(defun c-find-decl-spots (cfd-limit cfd-decl-re cfd-face-checklist cfd-fun)
0386b551
AM
3585 ;; Call CFD-FUN for each possible spot for a declaration, cast or
3586 ;; label from the point to CFD-LIMIT. Such a spot is:
3587 ;;
3588 ;; o The first token after bob.
3589 ;; o The first token after the end of submatch 1 in
3590 ;; `c-decl-prefix-or-start-re' when that submatch matches.
3591 ;; o The start of each `c-decl-prefix-or-start-re' match when
3592 ;; submatch 1 doesn't match.
3593 ;; o The first token after the end of each occurence of the
3594 ;; `c-type' text property with the value `c-decl-end', provided
3595 ;; `c-type-decl-end-used' is set.
3596 ;;
3597 ;; Only a spot that match CFD-DECL-RE and whose face is in the
3598 ;; CFD-FACE-CHECKLIST list causes CFD-FUN to be called. The face
3599 ;; check is disabled if CFD-FACE-CHECKLIST is nil.
d9e94c22
MS
3600 ;;
3601 ;; If the match is inside a macro then the buffer is narrowed to the
3602 ;; end of it, so that CFD-FUN can investigate the following tokens
3603 ;; without matching something that begins inside a macro and ends
3604 ;; outside it. It's to avoid this work that the CFD-DECL-RE and
3605 ;; CFD-FACE-CHECKLIST checks exist.
3606 ;;
3607 ;; CFD-FUN is called with point at the start of the spot. It's
3608 ;; passed two arguments: The first is the end position of the token
0386b551
AM
3609 ;; preceding the spot, or 0 for the implicit match at bob. The
3610 ;; second is a flag that is t when the match is inside a macro. If
3611 ;; CFD-FUN adds `c-decl-end' properties somewhere below the current
3612 ;; spot, it should return non-nil to ensure that the next search
3613 ;; will find them.
d9e94c22 3614 ;;
0386b551
AM
3615 ;; The spots are visited approximately in order from top to bottom.
3616 ;; It's however the positions where `c-decl-prefix-or-start-re'
3617 ;; matches and where `c-decl-end' properties are found that are in
3618 ;; order. Since the spots often are at the following token, they
3619 ;; might be visited out of order insofar as more spots are reported
3620 ;; later on within the syntactic whitespace between the match
3621 ;; positions and their spots.
3622 ;;
3623 ;; It's assumed that comments and strings are fontified in the
d9e94c22
MS
3624 ;; searched range.
3625 ;;
3626 ;; This is mainly used in fontification, and so has an elaborate
3627 ;; cache to handle repeated calls from the same start position; see
3628 ;; the variables above.
3629 ;;
3630 ;; All variables in this function begin with `cfd-' to avoid name
3631 ;; collision with the (dynamically bound) variables used in CFD-FUN.
0386b551
AM
3632 ;;
3633 ;; This function might do hidden buffer changes.
d9e94c22 3634
0386b551
AM
3635 (let ((cfd-start-pos (point))
3636 (cfd-buffer-end (point-max))
3637 ;; The end of the token preceding the decl spot last found
3638 ;; with `c-decl-prefix-or-start-re'. `cfd-limit' if there's
3639 ;; no match.
d9e94c22 3640 cfd-re-match
0386b551
AM
3641 ;; The end position of the last `c-decl-prefix-or-start-re'
3642 ;; match. If this is greater than `cfd-continue-pos', the
3643 ;; next regexp search is started here instead.
3644 (cfd-re-match-end (point-min))
3645 ;; The end of the last `c-decl-end' found by
3646 ;; `c-find-decl-prefix-search'. `cfd-limit' if there's no
3647 ;; match. If searching for the property isn't needed then we
3648 ;; disable it by setting it to `cfd-limit' directly.
d9e94c22 3649 (cfd-prop-match (unless c-type-decl-end-used cfd-limit))
0386b551
AM
3650 ;; The end of the token preceding the decl spot last found by
3651 ;; `c-find-decl-prefix-search'. 0 for the implicit match at
3652 ;; bob. `cfd-limit' if there's no match. In other words,
3653 ;; this is the minimum of `cfd-re-match' and `cfd-prop-match'.
d9e94c22
MS
3654 (cfd-match-pos cfd-limit)
3655 ;; The position to continue searching at.
3656 cfd-continue-pos
3657 ;; The position of the last "real" token we've stopped at.
3658 ;; This can be greater than `cfd-continue-pos' when we get
3659 ;; hits inside macros or at `c-decl-end' positions inside
3660 ;; comments.
3661 (cfd-token-pos 0)
3662 ;; The end position of the last entered macro.
3663 (cfd-macro-end 0))
3664
3665 ;; Initialize by finding a syntactically relevant start position
0386b551
AM
3666 ;; before the point, and do the first `c-decl-prefix-or-start-re'
3667 ;; search unless we're at bob.
d9e94c22 3668
0386b551 3669 (let (start-in-literal start-in-macro syntactic-pos)
d9e94c22
MS
3670 ;; Must back up a bit since we look for the end of the previous
3671 ;; statement or declaration, which is earlier than the first
3672 ;; returned match.
3673
0386b551
AM
3674 (cond
3675 ;; First we need to move to a syntactically relevant position.
3676 ;; Begin by backing out of comment or string literals.
3677 ((and
3678 (when (c-got-face-at (point) c-literal-faces)
3679 ;; Try to use the faces to back up to the start of the
3680 ;; literal. FIXME: What if the point is on a declaration
3681 ;; inside a comment?
3682 (while (and (not (bobp))
3683 (c-got-face-at (1- (point)) c-literal-faces))
3684 (goto-char (previous-single-property-change
3685 (point) 'face nil (point-min))))
3686
3687 ;; XEmacs doesn't fontify the quotes surrounding string
3688 ;; literals.
3689 (and (featurep 'xemacs)
3690 (eq (get-text-property (point) 'face)
3691 'font-lock-string-face)
3692 (not (bobp))
3693 (progn (backward-char)
3694 (not (looking-at c-string-limit-regexp)))
3695 (forward-char))
3696
3697 ;; Don't trust the literal to contain only literal faces
3698 ;; (the font lock package might not have fontified the
3699 ;; start of it at all, for instance) so check that we have
3700 ;; arrived at something that looks like a start or else
3701 ;; resort to `c-literal-limits'.
3702 (unless (looking-at c-literal-start-regexp)
3703 (let ((range (c-literal-limits)))
3704 (if range (goto-char (car range)))))
3705
3706 (setq start-in-literal (point)))
3707
3708 ;; The start is in a literal. If the limit is in the same
3709 ;; one we don't have to find a syntactic position etc. We
3710 ;; only check that if the limit is at or before bonl to save
3711 ;; time; it covers the by far most common case when font-lock
3712 ;; refontifies the current line only.
3713 (<= cfd-limit (c-point 'bonl cfd-start-pos))
3714 (save-excursion
3715 (goto-char cfd-start-pos)
3716 (while (progn
3717 (goto-char (next-single-property-change
3718 (point) 'face nil cfd-limit))
3719 (and (< (point) cfd-limit)
3720 (c-got-face-at (point) c-literal-faces))))
3721 (= (point) cfd-limit)))
3722
3723 ;; Completely inside a literal. Set up variables to trig the
3724 ;; (< cfd-continue-pos cfd-start-pos) case below and it'll
3725 ;; find a suitable start position.
3726 (setq cfd-continue-pos start-in-literal))
3727
3728 ;; Check if the region might be completely inside a macro, to
3729 ;; optimize that like the completely-inside-literal above.
3730 ((save-excursion
3731 (and (= (forward-line 1) 0)
3732 (bolp) ; forward-line has funny behavior at eob.
3733 (>= (point) cfd-limit)
3734 (progn (backward-char)
3735 (eq (char-before) ?\\))))
3736 ;; (Maybe) completely inside a macro. Only need to trig the
3737 ;; (< cfd-continue-pos cfd-start-pos) case below to make it
3738 ;; set things up.
3739 (setq cfd-continue-pos (1- cfd-start-pos)
3740 start-in-macro t))
d9e94c22 3741
0386b551
AM
3742 (t
3743 ;; Back out of any macro so we don't miss any declaration
3744 ;; that could follow after it.
3745 (when (c-beginning-of-macro)
3746 (setq start-in-macro t))
3747
3748 ;; Now we're at a proper syntactically relevant position so we
3749 ;; can use the cache. But first clear it if it applied
3750 ;; further down.
3751 (c-invalidate-find-decl-cache cfd-start-pos)
3752
3753 (setq syntactic-pos (point))
3754 (unless (eq syntactic-pos c-find-decl-syntactic-pos)
3755 ;; Don't have to do this if the cache is relevant here,
3756 ;; typically if the same line is refontified again. If
3757 ;; we're just some syntactic whitespace further down we can
3758 ;; still use the cache to limit the skipping.
3759 (c-backward-syntactic-ws c-find-decl-syntactic-pos))
3760
3761 ;; If we hit `c-find-decl-syntactic-pos' and
3762 ;; `c-find-decl-match-pos' is set then we install the cached
3763 ;; values. If we hit `c-find-decl-syntactic-pos' and
3764 ;; `c-find-decl-match-pos' is nil then we know there's no decl
3765 ;; prefix in the whitespace before `c-find-decl-syntactic-pos'
3766 ;; and so we can continue the search from this point. If we
3767 ;; didn't hit `c-find-decl-syntactic-pos' then we're now in
3768 ;; the right spot to begin searching anyway.
3769 (if (and (eq (point) c-find-decl-syntactic-pos)
3770 c-find-decl-match-pos)
d9e94c22
MS
3771 (setq cfd-match-pos c-find-decl-match-pos
3772 cfd-continue-pos syntactic-pos)
0386b551
AM
3773
3774 (setq c-find-decl-syntactic-pos syntactic-pos)
3775
3776 (when (if (bobp)
3777 ;; Always consider bob a match to get the first
3778 ;; declaration in the file. Do this separately instead of
3779 ;; letting `c-decl-prefix-or-start-re' match bob, so that
3780 ;; regexp always can consume at least one character to
3781 ;; ensure that we won't get stuck in an infinite loop.
3782 (setq cfd-re-match 0)
3783 (backward-char)
3784 (c-beginning-of-current-token)
3785 (< (point) cfd-limit))
3786 ;; Do an initial search now. In the bob case above it's
3787 ;; only done to search for a `c-decl-end' spot.
3788 (c-find-decl-prefix-search))
3789
3790 (setq c-find-decl-match-pos (and (< cfd-match-pos cfd-start-pos)
3791 cfd-match-pos)))))
3792
3793 ;; Advance `cfd-continue-pos' if it's before the start position.
3794 ;; The closest continue position that might have effect at or
3795 ;; after the start depends on what we started in. This also
3796 ;; finds a suitable start position in the special cases when the
3797 ;; region is completely within a literal or macro.
3798 (when (and cfd-continue-pos (< cfd-continue-pos cfd-start-pos))
3799
3800 (cond
3801 (start-in-macro
3802 ;; If we're in a macro then it's the closest preceding token
3803 ;; in the macro. Check this before `start-in-literal',
3804 ;; since if we're inside a literal in a macro, the preceding
3805 ;; token is earlier than any `c-decl-end' spot inside the
3806 ;; literal (comment).
3807 (goto-char (or start-in-literal cfd-start-pos))
3808 ;; The only syntactic ws in macros are comments.
d9e94c22 3809 (c-backward-comments)
0386b551
AM
3810 (backward-char)
3811 (c-beginning-of-current-token))
3812
3813 (start-in-literal
3814 ;; If we're in a comment it can only be the closest
3815 ;; preceding `c-decl-end' position within that comment, if
3816 ;; any. Go back to the beginning of such a property so that
3817 ;; `c-find-decl-prefix-search' will find the end of it.
3818 ;; (Can't stop at the end and install it directly on
3819 ;; `cfd-prop-match' since that variable might be cleared
3820 ;; after `cfd-fun' below.)
3821 ;;
3822 ;; Note that if the literal is a string then the property
3823 ;; search will simply skip to the beginning of it right
3824 ;; away.
3825 (if (not c-type-decl-end-used)
3826 (goto-char start-in-literal)
3827 (goto-char cfd-start-pos)
3828 (while (progn
3829 (goto-char (previous-single-property-change
3830 (point) 'c-type nil start-in-literal))
3831 (and (> (point) start-in-literal)
3832 (not (eq (c-get-char-property (point) 'c-type)
3833 'c-decl-end))))))
3834
3835 (when (= (point) start-in-literal)
3836 ;; Didn't find any property inside the comment, so we can
3837 ;; skip it entirely. (This won't skip past a string, but
3838 ;; that'll be handled quickly by the next
3839 ;; `c-find-decl-prefix-search' anyway.)
3840 (c-forward-single-comment)
3841 (if (> (point) cfd-limit)
3842 (goto-char cfd-limit))))
d9e94c22 3843
0386b551
AM
3844 (t
3845 ;; If we started in normal code, the only match that might
3846 ;; apply before the start is what we already got in
3847 ;; `cfd-match-pos' so we can continue at the start position.
3848 ;; (Note that we don't get here if the first match is below
3849 ;; it.)
3850 (goto-char cfd-start-pos)))
3851
3852 ;; Delete found matches if they are before our new continue
3853 ;; position, so that `c-find-decl-prefix-search' won't back up
3854 ;; to them later on.
3855 (setq cfd-continue-pos (point))
3856 (when (and cfd-re-match (< cfd-re-match cfd-continue-pos))
3857 (setq cfd-re-match nil))
3858 (when (and cfd-prop-match (< cfd-prop-match cfd-continue-pos))
3859 (setq cfd-prop-match nil)))
3860
3861 (if syntactic-pos
3862 ;; This is the normal case and we got a proper syntactic
3863 ;; position. If there's a match then it's always outside
3864 ;; macros and comments, so advance to the next token and set
3865 ;; `cfd-token-pos'. The loop below will later go back using
3866 ;; `cfd-continue-pos' to fix declarations inside the
3867 ;; syntactic ws.
3868 (when (and cfd-match-pos (< cfd-match-pos syntactic-pos))
3869 (goto-char syntactic-pos)
3870 (c-forward-syntactic-ws)
3871 (and cfd-continue-pos
3872 (< cfd-continue-pos (point))
3873 (setq cfd-token-pos (point))))
3874
3875 ;; Have one of the special cases when the region is completely
3876 ;; within a literal or macro. `cfd-continue-pos' is set to a
3877 ;; good start position for the search, so do it.
3878 (c-find-decl-prefix-search)))
d9e94c22 3879
51c9af45 3880 ;; Now loop. Round what? (ACM, 2006/7/5). We already got the first match.
d9e94c22
MS
3881
3882 (while (progn
3883 (while (and
3884 (< cfd-match-pos cfd-limit)
3885
3886 (or
3887 ;; Kludge to filter out matches on the "<" that
3888 ;; aren't open parens, for the sake of languages
3889 ;; that got `c-recognize-<>-arglists' set.
3890 (and (eq (char-before cfd-match-pos) ?<)
3891 (not (c-get-char-property (1- cfd-match-pos)
3892 'syntax-table)))
3893
3894 ;; If `cfd-continue-pos' is less or equal to
3895 ;; `cfd-token-pos', we've got a hit inside a macro
3896 ;; that's in the syntactic whitespace before the last
3897 ;; "real" declaration we've checked. If they're equal
3898 ;; we've arrived at the declaration a second time, so
3899 ;; there's nothing to do.
3900 (= cfd-continue-pos cfd-token-pos)
3901
3902 (progn
3903 ;; If `cfd-continue-pos' is less than `cfd-token-pos'
3904 ;; we're still searching for declarations embedded in
3905 ;; the syntactic whitespace. In that case we need
3906 ;; only to skip comments and not macros, since they
3907 ;; can't be nested, and that's already been done in
3908 ;; `c-find-decl-prefix-search'.
3909 (when (> cfd-continue-pos cfd-token-pos)
3910 (c-forward-syntactic-ws)
3911 (setq cfd-token-pos (point)))
3912
3913 ;; Continue if the following token fails the
3914 ;; CFD-DECL-RE and CFD-FACE-CHECKLIST checks.
3915 (when (or (>= (point) cfd-limit)
3916 (not (looking-at cfd-decl-re))
3917 (and cfd-face-checklist
3918 (not (c-got-face-at
3919 (point) cfd-face-checklist))))
3920 (goto-char cfd-continue-pos)
3921 t)))
3922
3923 (< (point) cfd-limit))
3924 (c-find-decl-prefix-search))
3925
3926 (< (point) cfd-limit))
3927
0386b551
AM
3928 (when (and
3929 (>= (point) cfd-start-pos)
d9e94c22 3930
0386b551
AM
3931 (progn
3932 ;; Narrow to the end of the macro if we got a hit inside
3933 ;; one, to avoid recognizing things that start inside the
3934 ;; macro and end outside it.
3935 (when (> cfd-match-pos cfd-macro-end)
3936 ;; Not in the same macro as in the previous round.
3937 (save-excursion
3938 (goto-char cfd-match-pos)
3939 (setq cfd-macro-end
3940 (if (save-excursion (and (c-beginning-of-macro)
3941 (< (point) cfd-match-pos)))
3942 (progn (c-end-of-macro)
3943 (point))
3944 0))))
3945
3946 (if (zerop cfd-macro-end)
3947 t
3948 (if (> cfd-macro-end (point))
3949 (progn (narrow-to-region (point-min) cfd-macro-end)
3950 t)
3951 ;; The matched token was the last thing in the macro,
3952 ;; so the whole match is bogus.
3953 (setq cfd-macro-end 0)
3954 nil))))
d9e94c22
MS
3955
3956 (c-debug-put-decl-spot-faces cfd-match-pos (point))
0386b551
AM
3957 (if (funcall cfd-fun cfd-match-pos (/= cfd-macro-end 0))
3958 (setq cfd-prop-match nil))
d9e94c22
MS
3959
3960 (when (/= cfd-macro-end 0)
3961 ;; Restore limits if we did macro narrowment above.
3962 (narrow-to-region (point-min) cfd-buffer-end)))
3963
3964 (goto-char cfd-continue-pos)
3965 (if (= cfd-continue-pos cfd-limit)
3966 (setq cfd-match-pos cfd-limit)
3967 (c-find-decl-prefix-search)))))
3968
3969\f
3970;; A cache for found types.
3971
3972;; Buffer local variable that contains an obarray with the types we've
3973;; found. If a declaration is recognized somewhere we record the
3974;; fully qualified identifier in it to recognize it as a type
3975;; elsewhere in the file too. This is not accurate since we do not
3976;; bother with the scoping rules of the languages, but in practice the
3977;; same name is seldom used as both a type and something else in a
3978;; file, and we only use this as a last resort in ambiguous cases (see
0386b551
AM
3979;; `c-forward-decl-or-cast-1').
3980;;
580fba94
AM
3981;; Not every type need be in this cache. However, things which have
3982;; ceased to be types must be removed from it.
3983;;
0386b551
AM
3984;; Template types in C++ are added here too but with the template
3985;; arglist replaced with "<>" in references or "<" for the one in the
3986;; primary type. E.g. the type "Foo<A,B>::Bar<C>" is stored as
3987;; "Foo<>::Bar<". This avoids storing very long strings (since C++
3988;; template specs can be fairly sized programs in themselves) and
3989;; improves the hit ratio (it's a type regardless of the template
3990;; args; it's just not the same type, but we're only interested in
3991;; recognizing types, not telling distinct types apart). Note that
3992;; template types in references are added here too; from the example
3993;; above there will also be an entry "Foo<".
d9e94c22
MS
3994(defvar c-found-types nil)
3995(make-variable-buffer-local 'c-found-types)
3996
3997(defsubst c-clear-found-types ()
3998 ;; Clears `c-found-types'.
d9e94c22
MS
3999 (setq c-found-types (make-vector 53 0)))
4000
4001(defun c-add-type (from to)
4002 ;; Add the given region as a type in `c-found-types'. If the region
4003 ;; doesn't match an existing type but there is a type which is equal
4004 ;; to the given one except that the last character is missing, then
4005 ;; the shorter type is removed. That's done to avoid adding all
4006 ;; prefixes of a type as it's being entered and font locked. This
4007 ;; doesn't cover cases like when characters are removed from a type
4008 ;; or added in the middle. We'd need the position of point when the
4009 ;; font locking is invoked to solve this well.
0386b551
AM
4010 ;;
4011 ;; This function might do hidden buffer changes.
4012 (let ((type (c-syntactic-content from to c-recognize-<>-arglists)))
4013 (unless (intern-soft type c-found-types)
4014 (unintern (substring type 0 -1) c-found-types)
4015 (intern type c-found-types))))
d9e94c22 4016
580fba94
AM
4017(defun c-unfind-type (name)
4018 ;; Remove the "NAME" from c-found-types, if present.
4019 (unintern name c-found-types))
4020
d9e94c22
MS
4021(defsubst c-check-type (from to)
4022 ;; Return non-nil if the given region contains a type in
4023 ;; `c-found-types'.
0386b551
AM
4024 ;;
4025 ;; This function might do hidden buffer changes.
4026 (intern-soft (c-syntactic-content from to c-recognize-<>-arglists)
4027 c-found-types))
d9e94c22
MS
4028
4029(defun c-list-found-types ()
4030 ;; Return all the types in `c-found-types' as a sorted list of
4031 ;; strings.
4032 (let (type-list)
4033 (mapatoms (lambda (type)
4034 (setq type-list (cons (symbol-name type)
4035 type-list)))
4036 c-found-types)
4037 (sort type-list 'string-lessp)))
a66cd3ee 4038
580fba94
AM
4039(defun c-trim-found-types (beg end old-len)
4040 ;; An after change function which, in conjunction with the info in
4041 ;; c-maybe-stale-found-type (set in c-before-change), removes a type
4042 ;; from `c-found-types', should this type have become stale. For
4043 ;; example, this happens to "foo" when "foo \n bar();" becomes
4044 ;; "foo(); \n bar();". Such stale types, if not removed, foul up
4045 ;; the fontification.
4046 ;;
4047 ;; Have we, perhaps, added non-ws characters to the front/back of a found
4048 ;; type?
4049 (when (> end beg)
4050 (save-excursion
4051 (when (< end (point-max))
4052 (goto-char end)
4053 (if (and (c-beginning-of-current-token) ; only moves when we started in the middle
4054 (progn (goto-char end)
4055 (c-end-of-current-token)))
4056 (c-unfind-type (buffer-substring-no-properties
4057 end (point)))))
4058 (when (> beg (point-min))
4059 (goto-char beg)
4060 (if (and (c-end-of-current-token) ; only moves when we started in the middle
4061 (progn (goto-char beg)
4062 (c-beginning-of-current-token)))
4063 (c-unfind-type (buffer-substring-no-properties
4064 (point) beg))))))
4065
4066 (if c-maybe-stale-found-type ; e.g. (c-decl-id-start "foo" 97 107 " (* ooka) " "o")
4067 (cond
4068 ;; Changing the amount of (already existing) whitespace - don't do anything.
4069 ((and (c-partial-ws-p beg end)
4070 (or (= beg end) ; removal of WS
4071 ; (string-match "\\s *\\'" (nth 5 c-maybe-stale-found-type))
4072 (string-match "^[ \t\n\r\f\v]*$" (nth 5 c-maybe-stale-found-type)))))
4073
4074 ;; The syntactic relationship which defined a "found type" has been
4075 ;; destroyed.
4076 ((eq (car c-maybe-stale-found-type) 'c-decl-id-start)
4077 (c-unfind-type (cadr c-maybe-stale-found-type)))
4078;; ((eq (car c-maybe-stale-found-type) 'c-decl-type-start) FIXME!!!
4079 )))
4080
d9e94c22
MS
4081\f
4082;; Handling of small scale constructs like types and names.
4083
0386b551
AM
4084(defun c-after-change-check-<>-operators (beg end)
4085 ;; This is called from `after-change-functions' when
4086 ;; c-recognize-<>-arglists' is set. It ensures that no "<" or ">"
4087 ;; chars with paren syntax become part of another operator like "<<"
4088 ;; or ">=".
4089 ;;
4090 ;; This function might do hidden buffer changes.
4091
cb694ab7
AM
4092 (save-excursion
4093 (goto-char beg)
4094 (when (or (looking-at "[<>]")
4095 (< (skip-chars-backward "<>") 0))
4096
0386b551 4097 (goto-char beg)
cb694ab7
AM
4098 (c-beginning-of-current-token)
4099 (when (and (< (point) beg)
4100 (looking-at c-<>-multichar-token-regexp)
4101 (< beg (setq beg (match-end 0))))
4102 (while (progn (skip-chars-forward "^<>" beg)
4103 (< (point) beg))
4104 (c-clear-char-property (point) 'syntax-table)
4105 (forward-char))))
4106
4107 (when (< beg end)
4108 (goto-char end)
0386b551
AM
4109 (when (or (looking-at "[<>]")
4110 (< (skip-chars-backward "<>") 0))
4111
cb694ab7 4112 (goto-char end)
0386b551 4113 (c-beginning-of-current-token)
cb694ab7 4114 (when (and (< (point) end)
0386b551 4115 (looking-at c-<>-multichar-token-regexp)
cb694ab7
AM
4116 (< end (setq end (match-end 0))))
4117 (while (progn (skip-chars-forward "^<>" end)
4118 (< (point) end))
0386b551 4119 (c-clear-char-property (point) 'syntax-table)
cb694ab7 4120 (forward-char)))))))
d9e94c22
MS
4121
4122;; Dynamically bound variable that instructs `c-forward-type' to also
4123;; treat possible types (i.e. those that it normally returns 'maybe or
4124;; 'found for) as actual types (and always return 'found for them).
4125;; This means that it records them in `c-record-type-identifiers' if
4126;; that is set, and that it adds them to `c-found-types'.
4127(defvar c-promote-possible-types nil)
4128
0386b551
AM
4129;; Dynamically bound variable that instructs `c-forward-<>-arglist' to
4130;; mark up successfully parsed arglists with paren syntax properties on
4131;; the surrounding angle brackets and with `c-<>-arg-sep' in the
4132;; `c-type' property of each argument separating comma.
4133;;
4134;; Setting this variable also makes `c-forward-<>-arglist' recurse into
4135;; all arglists for side effects (i.e. recording types), otherwise it
4136;; exploits any existing paren syntax properties to quickly jump to the
4137;; end of already parsed arglists.
4138;;
4139;; Marking up the arglists is not the default since doing that correctly
4140;; depends on a proper value for `c-restricted-<>-arglists'.
4141(defvar c-parse-and-markup-<>-arglists nil)
4142
d9e94c22 4143;; Dynamically bound variable that instructs `c-forward-<>-arglist' to
037558bf
MS
4144;; not accept arglists that contain binary operators.
4145;;
4146;; This is primarily used to handle C++ template arglists. C++
4147;; disambiguates them by checking whether the preceding name is a
4148;; template or not. We can't do that, so we assume it is a template
4149;; if it can be parsed as one. That usually works well since
4150;; comparison expressions on the forms "a < b > c" or "a < b, c > d"
4151;; in almost all cases would be pointless.
4152;;
4153;; However, in function arglists, e.g. in "foo (a < b, c > d)", we
4154;; should let the comma separate the function arguments instead. And
4155;; in a context where the value of the expression is taken, e.g. in
4156;; "if (a < b || c > d)", it's probably not a template.
4157(defvar c-restricted-<>-arglists nil)
d9e94c22 4158
0386b551
AM
4159;; Dynamically bound variables that instructs
4160;; `c-forward-keyword-clause', `c-forward-<>-arglist',
4161;; `c-forward-name', `c-forward-type', `c-forward-decl-or-cast-1', and
4162;; `c-forward-label' to record the ranges of all the type and
4163;; reference identifiers they encounter. They will build lists on
4164;; these variables where each element is a cons of the buffer
4165;; positions surrounding each identifier. This recording is only
4166;; activated when `c-record-type-identifiers' is non-nil.
d9e94c22
MS
4167;;
4168;; All known types that can't be identifiers are recorded, and also
4169;; other possible types if `c-promote-possible-types' is set.
4170;; Recording is however disabled inside angle bracket arglists that
4171;; are encountered inside names and other angle bracket arglists.
0386b551 4172;; Such occurrences are taken care of by `c-font-lock-<>-arglists'
d9e94c22
MS
4173;; instead.
4174;;
4175;; Only the names in C++ template style references (e.g. "tmpl" in
4176;; "tmpl<a,b>::foo") are recorded as references, other references
4177;; aren't handled here.
0386b551
AM
4178;;
4179;; `c-forward-label' records the label identifier(s) on
4180;; `c-record-ref-identifiers'.
d9e94c22
MS
4181(defvar c-record-type-identifiers nil)
4182(defvar c-record-ref-identifiers nil)
4183
0386b551
AM
4184;; This variable will receive a cons cell of the range of the last
4185;; single identifier symbol stepped over by `c-forward-name' if it's
4186;; successful. This is the range that should be put on one of the
4187;; record lists above by the caller. It's assigned nil if there's no
4188;; such symbol in the name.
d9e94c22
MS
4189(defvar c-last-identifier-range nil)
4190
4191(defmacro c-record-type-id (range)
4192 (if (eq (car-safe range) 'cons)
4193 ;; Always true.
4194 `(setq c-record-type-identifiers
4195 (cons ,range c-record-type-identifiers))
4196 `(let ((range ,range))
4197 (if range
4198 (setq c-record-type-identifiers
4199 (cons range c-record-type-identifiers))))))
4200
4201(defmacro c-record-ref-id (range)
4202 (if (eq (car-safe range) 'cons)
4203 ;; Always true.
4204 `(setq c-record-ref-identifiers
4205 (cons ,range c-record-ref-identifiers))
4206 `(let ((range ,range))
4207 (if range
4208 (setq c-record-ref-identifiers
4209 (cons range c-record-ref-identifiers))))))
4210
4211;; Dynamically bound variable that instructs `c-forward-type' to
4212;; record the ranges of types that only are found. Behaves otherwise
4213;; like `c-record-type-identifiers'.
4214(defvar c-record-found-types nil)
4215
4216(defmacro c-forward-keyword-prefixed-id (type)
4217 ;; Used internally in `c-forward-keyword-clause' to move forward
4218 ;; over a type (if TYPE is 'type) or a name (otherwise) which
4219 ;; possibly is prefixed by keywords and their associated clauses.
4220 ;; Try with a type/name first to not trip up on those that begin
4221 ;; with a keyword. Return t if a known or found type is moved
4222 ;; over. The point is clobbered if nil is returned. If range
4223 ;; recording is enabled, the identifier is recorded on as a type
4224 ;; if TYPE is 'type or as a reference if TYPE is 'ref.
0386b551
AM
4225 ;;
4226 ;; This macro might do hidden buffer changes.
d9e94c22
MS
4227 `(let (res)
4228 (while (if (setq res ,(if (eq type 'type)
4229 `(c-forward-type)
4230 `(c-forward-name)))
4231 nil
4232 (and (looking-at c-keywords-regexp)
0386b551 4233 (c-forward-keyword-clause 1))))
d9e94c22
MS
4234 (when (memq res '(t known found prefix))
4235 ,(when (eq type 'ref)
4236 `(when c-record-type-identifiers
4237 (c-record-ref-id c-last-identifier-range)))
4238 t)))
4239
0386b551 4240(defmacro c-forward-id-comma-list (type update-safe-pos)
d9e94c22
MS
4241 ;; Used internally in `c-forward-keyword-clause' to move forward
4242 ;; over a comma separated list of types or names using
4243 ;; `c-forward-keyword-prefixed-id'.
0386b551
AM
4244 ;;
4245 ;; This macro might do hidden buffer changes.
d9e94c22 4246 `(while (and (progn
0386b551
AM
4247 ,(when update-safe-pos
4248 `(setq safe-pos (point)))
d9e94c22
MS
4249 (eq (char-after) ?,))
4250 (progn
4251 (forward-char)
4252 (c-forward-syntactic-ws)
4253 (c-forward-keyword-prefixed-id ,type)))))
4254
0386b551
AM
4255(defun c-forward-keyword-clause (match)
4256 ;; Submatch MATCH in the current match data is assumed to surround a
4257 ;; token. If it's a keyword, move over it and any immediately
4258 ;; following clauses associated with it, stopping at the start of
4259 ;; the next token. t is returned in that case, otherwise the point
d9e94c22
MS
4260 ;; stays and nil is returned. The kind of clauses that are
4261 ;; recognized are those specified by `c-type-list-kwds',
4262 ;; `c-ref-list-kwds', `c-colon-type-list-kwds',
4263 ;; `c-paren-nontype-kwds', `c-paren-type-kwds', `c-<>-type-kwds',
4264 ;; and `c-<>-arglist-kwds'.
0386b551
AM
4265 ;;
4266 ;; This function records identifier ranges on
4267 ;; `c-record-type-identifiers' and `c-record-ref-identifiers' if
4268 ;; `c-record-type-identifiers' is non-nil.
4269 ;;
4270 ;; Note that for `c-colon-type-list-kwds', which doesn't necessary
4271 ;; apply directly after the keyword, the type list is moved over
4272 ;; only when there is no unaccounted token before it (i.e. a token
4273 ;; that isn't moved over due to some other keyword list). The
4274 ;; identifier ranges in the list are still recorded if that should
4275 ;; be done, though.
4276 ;;
4277 ;; This function might do hidden buffer changes.
4278
4279 (let ((kwd-sym (c-keyword-sym (match-string match))) safe-pos pos
4280 ;; The call to `c-forward-<>-arglist' below is made after
4281 ;; `c-<>-sexp-kwds' keywords, so we're certain they actually
4282 ;; are angle bracket arglists and `c-restricted-<>-arglists'
4283 ;; should therefore be nil.
4284 (c-parse-and-markup-<>-arglists t)
4285 c-restricted-<>-arglists)
d9e94c22 4286
d9e94c22 4287 (when kwd-sym
0386b551 4288 (goto-char (match-end match))
d9e94c22
MS
4289 (c-forward-syntactic-ws)
4290 (setq safe-pos (point))
a66cd3ee 4291
d9e94c22
MS
4292 (cond
4293 ((and (c-keyword-member kwd-sym 'c-type-list-kwds)
4294 (c-forward-keyword-prefixed-id type))
4295 ;; There's a type directly after a keyword in `c-type-list-kwds'.
0386b551 4296 (c-forward-id-comma-list type t))
d9e94c22
MS
4297
4298 ((and (c-keyword-member kwd-sym 'c-ref-list-kwds)
4299 (c-forward-keyword-prefixed-id ref))
4300 ;; There's a name directly after a keyword in `c-ref-list-kwds'.
0386b551 4301 (c-forward-id-comma-list ref t))
d9e94c22
MS
4302
4303 ((and (c-keyword-member kwd-sym 'c-paren-any-kwds)
4304 (eq (char-after) ?\())
4305 ;; There's an open paren after a keyword in `c-paren-any-kwds'.
4306
4307 (forward-char)
4308 (when (and (setq pos (c-up-list-forward))
4309 (eq (char-before pos) ?\)))
4310 (when (and c-record-type-identifiers
4311 (c-keyword-member kwd-sym 'c-paren-type-kwds))
4312 ;; Use `c-forward-type' on every identifier we can find
4313 ;; inside the paren, to record the types.
4314 (while (c-syntactic-re-search-forward c-symbol-start pos t)
4315 (goto-char (match-beginning 0))
4316 (unless (c-forward-type)
4317 (looking-at c-symbol-key) ; Always matches.
4318 (goto-char (match-end 0)))))
4319
4320 (goto-char pos)
4321 (c-forward-syntactic-ws)
4322 (setq safe-pos (point))))
4323
4324 ((and (c-keyword-member kwd-sym 'c-<>-sexp-kwds)
4325 (eq (char-after) ?<)
0386b551 4326 (c-forward-<>-arglist (c-keyword-member kwd-sym 'c-<>-type-kwds)))
d9e94c22
MS
4327 (c-forward-syntactic-ws)
4328 (setq safe-pos (point)))
4329
4330 ((and (c-keyword-member kwd-sym 'c-nonsymbol-sexp-kwds)
449a2b0d
MS
4331 (not (looking-at c-symbol-start))
4332 (c-safe (c-forward-sexp) t))
d9e94c22
MS
4333 (c-forward-syntactic-ws)
4334 (setq safe-pos (point))))
4335
0386b551
AM
4336 (when (c-keyword-member kwd-sym 'c-colon-type-list-kwds)
4337 (if (eq (char-after) ?:)
4338 ;; If we are at the colon already, we move over the type
4339 ;; list after it.
4340 (progn
4341 (forward-char)
4342 (c-forward-syntactic-ws)
4343 (when (c-forward-keyword-prefixed-id type)
4344 (c-forward-id-comma-list type t)))
4345 ;; Not at the colon, so stop here. But the identifier
4346 ;; ranges in the type list later on should still be
4347 ;; recorded.
4348 (and c-record-type-identifiers
4349 (progn
4350 ;; If a keyword matched both one of the types above and
4351 ;; this one, we match `c-colon-type-list-re' after the
4352 ;; clause matched above.
4353 (goto-char safe-pos)
4354 (looking-at c-colon-type-list-re))
4355 (progn
4356 (goto-char (match-end 0))
4357 (c-forward-syntactic-ws)
4358 (c-forward-keyword-prefixed-id type))
4359 ;; There's a type after the `c-colon-type-list-re' match
4360 ;; after a keyword in `c-colon-type-list-kwds'.
4361 (c-forward-id-comma-list type nil))))
d9e94c22
MS
4362
4363 (goto-char safe-pos)
4364 t)))
4365
0386b551
AM
4366(defun c-forward-<>-arglist (all-types)
4367 ;; The point is assumed to be at a "<". Try to treat it as the open
d9e94c22 4368 ;; paren of an angle bracket arglist and move forward to the the
0386b551
AM
4369 ;; corresponding ">". If successful, the point is left after the
4370 ;; ">" and t is returned, otherwise the point isn't moved and nil is
d9e94c22
MS
4371 ;; returned. If ALL-TYPES is t then all encountered arguments in
4372 ;; the arglist that might be types are treated as found types.
4373 ;;
0386b551
AM
4374 ;; The variable `c-parse-and-markup-<>-arglists' controls how this
4375 ;; function handles text properties on the angle brackets and argument
4376 ;; separating commas.
d9e94c22 4377 ;;
0386b551
AM
4378 ;; `c-restricted-<>-arglists' controls how lenient the template
4379 ;; arglist recognition should be.
4380 ;;
4381 ;; This function records identifier ranges on
4382 ;; `c-record-type-identifiers' and `c-record-ref-identifiers' if
4383 ;; `c-record-type-identifiers' is non-nil.
4384 ;;
4385 ;; This function might do hidden buffer changes.
d9e94c22
MS
4386
4387 (let ((start (point))
4388 ;; If `c-record-type-identifiers' is set then activate
4389 ;; recording of any found types that constitute an argument in
4390 ;; the arglist.
4391 (c-record-found-types (if c-record-type-identifiers t)))
4392 (if (catch 'angle-bracket-arglist-escape
4393 (setq c-record-found-types
0386b551 4394 (c-forward-<>-arglist-recur all-types)))
d9e94c22
MS
4395 (progn
4396 (when (consp c-record-found-types)
4397 (setq c-record-type-identifiers
4398 ;; `nconc' doesn't mind that the tail of
4399 ;; `c-record-found-types' is t.
4400 (nconc c-record-found-types c-record-type-identifiers)))
4401 t)
4402
4403 (goto-char start)
a66cd3ee 4404 nil)))
785eecbb 4405
0386b551 4406(defun c-forward-<>-arglist-recur (all-types)
d9e94c22 4407 ;; Recursive part of `c-forward-<>-arglist'.
0386b551
AM
4408 ;;
4409 ;; This function might do hidden buffer changes.
d9e94c22
MS
4410
4411 (let ((start (point)) res pos tmp
4412 ;; Cover this so that any recorded found type ranges are
4413 ;; automatically lost if it turns out to not be an angle
4414 ;; bracket arglist. It's propagated through the return value
4415 ;; on successful completion.
4416 (c-record-found-types c-record-found-types)
4417 ;; List that collects the positions after the argument
4418 ;; separating ',' in the arglist.
4419 arg-start-pos)
4420
0386b551
AM
4421 ;; If the '<' has paren open syntax then we've marked it as an angle
4422 ;; bracket arglist before, so skip to the end.
4423 (if (and (not c-parse-and-markup-<>-arglists)
4424 (c-get-char-property (point) 'syntax-table))
4425
4426 (progn
4427 (forward-char)
4428 (if (and (c-go-up-list-forward)
4429 (eq (char-before) ?>))
4430 t
4431
4432 ;; Got unmatched paren angle brackets. We don't clear the paren
4433 ;; syntax properties and retry, on the basis that it's very
4434 ;; unlikely that paren angle brackets become operators by code
4435 ;; manipulation. It's far more likely that it doesn't match due
4436 ;; to narrowing or some temporary change.
4437 (goto-char start)
4438 nil))
d9e94c22
MS
4439
4440 (forward-char)
4441 (unless (looking-at c-<-op-cont-regexp)
4442 (while (and
4443 (progn
4444
4445 (when c-record-type-identifiers
4446 (if all-types
4447
4448 ;; All encountered identifiers are types, so set the
4449 ;; promote flag and parse the type.
4450 (progn
4451 (c-forward-syntactic-ws)
4452 (when (looking-at c-identifier-start)
4453 (let ((c-promote-possible-types t))
4454 (c-forward-type))))
4455
4456 ;; Check if this arglist argument is a sole type. If
4457 ;; it's known then it's recorded in
4458 ;; `c-record-type-identifiers'. If it only is found
4459 ;; then it's recorded in `c-record-found-types' which we
4460 ;; might roll back if it turns out that this isn't an
4461 ;; angle bracket arglist afterall.
4462 (when (memq (char-before) '(?, ?<))
4463 (let ((orig-record-found-types c-record-found-types))
4464 (c-forward-syntactic-ws)
4465 (and (memq (c-forward-type) '(known found))
4466 (not (looking-at "[,>]"))
4467 ;; A found type was recorded but it's not the
4468 ;; only thing in the arglist argument, so reset
4469 ;; `c-record-found-types'.
4470 (setq c-record-found-types
4471 orig-record-found-types))))))
4472
4473 (setq pos (point))
4474 (or (when (eq (char-after) ?>)
4475 ;; Must check for '>' at the very start separately,
4476 ;; since the regexp below has to avoid ">>" without
4477 ;; using \\=.
4478 (forward-char)
4479 t)
4480
037558bf
MS
4481 ;; Note: These regexps exploit the match order in \| so
4482 ;; that "<>" is matched by "<" rather than "[^>:-]>".
d9e94c22 4483 (c-syntactic-re-search-forward
037558bf
MS
4484 (if c-restricted-<>-arglists
4485 ;; Stop on ',', '|', '&', '+' and '-' to catch
4486 ;; common binary operators that could be between
4487 ;; two comparison expressions "a<b" and "c>d".
4488 "[<;{},|&+-]\\|\\([^>:-]>\\)"
4489 ;; Otherwise we still stop on ',' to find the
4490 ;; argument start positions.
4491 "[<;{},]\\|\\([^>:-]>\\)")
4492 nil 'move t t 1)
d9e94c22
MS
4493
4494 ;; If the arglist starter has lost its open paren
4495 ;; syntax but not the closer, we won't find the
4496 ;; closer above since we only search in the
4497 ;; balanced sexp. In that case we stop just short
4498 ;; of it so check if the following char is the closer.
4499 (when (eq (char-after) ?>)
d9e94c22
MS
4500 (forward-char)
4501 t)))
4502
4503 (cond
4504 ((eq (char-before) ?>)
4505 ;; Either an operator starting with '>' or the end of
4506 ;; the angle bracket arglist.
4507
0386b551 4508 (if (looking-at c->-op-cont-regexp)
d9e94c22 4509 (progn
0386b551
AM
4510 (goto-char (match-end 0))
4511 t) ; Continue the loop.
d9e94c22 4512
0386b551
AM
4513 ;; The angle bracket arglist is finished.
4514 (when c-parse-and-markup-<>-arglists
d9e94c22 4515 (while arg-start-pos
0386b551
AM
4516 (c-put-c-type-property (1- (car arg-start-pos))
4517 'c-<>-arg-sep)
d9e94c22
MS
4518 (setq arg-start-pos (cdr arg-start-pos)))
4519 (c-mark-<-as-paren start)
0386b551
AM
4520 (c-mark->-as-paren (1- (point))))
4521 (setq res t)
4522 nil)) ; Exit the loop.
d9e94c22
MS
4523
4524 ((eq (char-before) ?<)
4525 ;; Either an operator starting with '<' or a nested arglist.
4526
4527 (setq pos (point))
4528 (let (id-start id-end subres keyword-match)
4529 (if (if (looking-at c-<-op-cont-regexp)
4530 (setq tmp (match-end 0))
4531 (setq tmp pos)
4532 (backward-char)
4533 (not
4534 (and
4535
4536 (save-excursion
0386b551 4537 ;; There's always an identifier before an angle
d9e94c22
MS
4538 ;; bracket arglist, or a keyword in
4539 ;; `c-<>-type-kwds' or `c-<>-arglist-kwds'.
4540 (c-backward-syntactic-ws)
4541 (setq id-end (point))
4542 (c-simple-skip-symbol-backward)
4543 (when (or (setq keyword-match
4544 (looking-at c-opt-<>-sexp-key))
4545 (not (looking-at c-keywords-regexp)))
4546 (setq id-start (point))))
4547
4548 (setq subres
4549 (let ((c-record-type-identifiers nil)
4550 (c-record-found-types nil))
4551 (c-forward-<>-arglist-recur
4552 (and keyword-match
4553 (c-keyword-member
4554 (c-keyword-sym (match-string 1))
0386b551 4555 'c-<>-type-kwds)))))
d9e94c22
MS
4556 )))
4557
4558 ;; It was not an angle bracket arglist.
0386b551 4559 (goto-char tmp)
d9e94c22
MS
4560
4561 ;; It was an angle bracket arglist.
4562 (setq c-record-found-types subres)
4563
4564 ;; Record the identifier before the template as a type
4565 ;; or reference depending on whether the arglist is last
4566 ;; in a qualified identifier.
4567 (when (and c-record-type-identifiers
4568 (not keyword-match))
4569 (if (and c-opt-identifier-concat-key
4570 (progn
4571 (c-forward-syntactic-ws)
4572 (looking-at c-opt-identifier-concat-key)))
4573 (c-record-ref-id (cons id-start id-end))
4574 (c-record-type-id (cons id-start id-end))))))
4575 t)
4576
4577 ((and (eq (char-before) ?,)
037558bf 4578 (not c-restricted-<>-arglists))
d9e94c22
MS
4579 ;; Just another argument. Record the position. The
4580 ;; type check stuff that made us stop at it is at
4581 ;; the top of the loop.
4582 (setq arg-start-pos (cons (point) arg-start-pos)))
4583
4584 (t
4585 ;; Got a character that can't be in an angle bracket
4586 ;; arglist argument. Abort using `throw', since
4587 ;; it's useless to try to find a surrounding arglist
4588 ;; if we're nested.
4589 (throw 'angle-bracket-arglist-escape nil))))))
4590
4591 (if res
4592 (or c-record-found-types t)))))
4593
0386b551
AM
4594(defun c-backward-<>-arglist (all-types &optional limit)
4595 ;; The point is assumed to be directly after a ">". Try to treat it
4596 ;; as the close paren of an angle bracket arglist and move back to
4597 ;; the corresponding "<". If successful, the point is left at
4598 ;; the "<" and t is returned, otherwise the point isn't moved and
4599 ;; nil is returned. ALL-TYPES is passed on to
4600 ;; `c-forward-<>-arglist'.
4601 ;;
4602 ;; If the optional LIMIT is given, it bounds the backward search.
4603 ;; It's then assumed to be at a syntactically relevant position.
4604 ;;
4605 ;; This is a wrapper around `c-forward-<>-arglist'. See that
4606 ;; function for more details.
4607
4608 (let ((start (point)))
4609 (backward-char)
4610 (if (and (not c-parse-and-markup-<>-arglists)
4611 (c-get-char-property (point) 'syntax-table))
4612
4613 (if (and (c-go-up-list-backward)
4614 (eq (char-after) ?<))
4615 t
4616 ;; See corresponding note in `c-forward-<>-arglist'.
4617 (goto-char start)
4618 nil)
4619
51c9af45 4620 (while (progn
0386b551
AM
4621 (c-syntactic-skip-backward "^<;{}" limit t)
4622
51c9af45
AM
4623 (and
4624 (if (eq (char-before) ?<)
4625 t
4626 ;; Stopped at bob or a char that isn't allowed in an
4627 ;; arglist, so we've failed.
4628 (goto-char start)
4629 nil)
0386b551 4630
51c9af45
AM
4631 (if (> (point)
4632 (progn (c-beginning-of-current-token)
4633 (point)))
4634 ;; If we moved then the "<" was part of some
4635 ;; multicharacter token.
4636 t
0386b551 4637
51c9af45
AM
4638 (backward-char)
4639 (let ((beg-pos (point)))
4640 (if (c-forward-<>-arglist all-types)
4641 (cond ((= (point) start)
4642 ;; Matched the arglist. Break the while.
4643 (goto-char beg-pos)
4644 nil)
4645 ((> (point) start)
4646 ;; We started from a non-paren ">" inside an
4647 ;; arglist.
4648 (goto-char start)
4649 nil)
4650 (t
4651 ;; Matched a shorter arglist. Can be a nested
4652 ;; one so continue looking.
4653 (goto-char beg-pos)
4654 t))
4655 t))))))
0386b551
AM
4656
4657 (/= (point) start))))
4658
d9e94c22
MS
4659(defun c-forward-name ()
4660 ;; Move forward over a complete name if at the beginning of one,
4661 ;; stopping at the next following token. If the point is not at
4662 ;; something that are recognized as name then it stays put. A name
4663 ;; could be something as simple as "foo" in C or something as
4664 ;; complex as "X<Y<class A<int>::B, BIT_MAX >> b>, ::operator<> ::
4665 ;; Z<(a>b)> :: operator const X<&foo>::T Q::G<unsigned short
4666 ;; int>::*volatile const" in C++ (this function is actually little
4667 ;; more than a `looking-at' call in all modes except those that,
4668 ;; like C++, have `c-recognize-<>-arglists' set). Return nil if no
4669 ;; name is found, 'template if it's an identifier ending with an
4670 ;; angle bracket arglist, 'operator of it's an operator identifier,
4671 ;; or t if it's some other kind of name.
0386b551
AM
4672 ;;
4673 ;; This function records identifier ranges on
4674 ;; `c-record-type-identifiers' and `c-record-ref-identifiers' if
4675 ;; `c-record-type-identifiers' is non-nil.
4676 ;;
4677 ;; This function might do hidden buffer changes.
d9e94c22 4678
0386b551 4679 (let ((pos (point)) (start (point)) res id-start id-end
d9e94c22
MS
4680 ;; Turn off `c-promote-possible-types' here since we might
4681 ;; call `c-forward-<>-arglist' and we don't want it to promote
4682 ;; every suspect thing in the arglist to a type. We're
4683 ;; typically called from `c-forward-type' in this case, and
4684 ;; the caller only wants the top level type that it finds to
4685 ;; be promoted.
4686 c-promote-possible-types)
4687 (while
4688 (and
4689 (looking-at c-identifier-key)
4690
4691 (progn
4692 ;; Check for keyword. We go to the last symbol in
4693 ;; `c-identifier-key' first.
0386b551
AM
4694 (goto-char (setq id-end (match-end 0)))
4695 (c-simple-skip-symbol-backward)
4696 (setq id-start (point))
d9e94c22
MS
4697
4698 (if (looking-at c-keywords-regexp)
4699 (when (and (c-major-mode-is 'c++-mode)
4700 (looking-at
4701 (cc-eval-when-compile
4702 (concat "\\(operator\\|\\(template\\)\\)"
4703 "\\(" (c-lang-const c-nonsymbol-key c++)
4704 "\\|$\\)")))
4705 (if (match-beginning 2)
4706 ;; "template" is only valid inside an
4707 ;; identifier if preceded by "::".
4708 (save-excursion
4709 (c-backward-syntactic-ws)
4710 (and (c-safe (backward-char 2) t)
4711 (looking-at "::")))
4712 t))
4713
4714 ;; Handle a C++ operator or template identifier.
4715 (goto-char id-end)
4716 (c-forward-syntactic-ws)
4717 (cond ((eq (char-before id-end) ?e)
4718 ;; Got "... ::template".
4719 (let ((subres (c-forward-name)))
4720 (when subres
4721 (setq pos (point)
4722 res subres))))
4723
4724 ((looking-at c-identifier-start)
4725 ;; Got a cast operator.
4726 (when (c-forward-type)
4727 (setq pos (point)
4728 res 'operator)
4729 ;; Now we should match a sequence of either
4730 ;; '*', '&' or a name followed by ":: *",
4731 ;; where each can be followed by a sequence
4732 ;; of `c-opt-type-modifier-key'.
4733 (while (cond ((looking-at "[*&]")
4734 (goto-char (match-end 0))
4735 t)
4736 ((looking-at c-identifier-start)
4737 (and (c-forward-name)
4738 (looking-at "::")
4739 (progn
4740 (goto-char (match-end 0))
4741 (c-forward-syntactic-ws)
4742 (eq (char-after) ?*))
4743 (progn
4744 (forward-char)
4745 t))))
4746 (while (progn
4747 (c-forward-syntactic-ws)
4748 (setq pos (point))
4749 (looking-at c-opt-type-modifier-key))
4750 (goto-char (match-end 1))))))
4751
4752 ((looking-at c-overloadable-operators-regexp)
4753 ;; Got some other operator.
0386b551
AM
4754 (setq c-last-identifier-range
4755 (cons (point) (match-end 0)))
d9e94c22
MS
4756 (goto-char (match-end 0))
4757 (c-forward-syntactic-ws)
4758 (setq pos (point)
4759 res 'operator)))
4760
4761 nil)
4762
0386b551
AM
4763 ;; `id-start' is equal to `id-end' if we've jumped over
4764 ;; an identifier that doesn't end with a symbol token.
4765 ;; That can occur e.g. for Java import directives on the
4766 ;; form "foo.bar.*".
4767 (when (and id-start (/= id-start id-end))
d9e94c22
MS
4768 (setq c-last-identifier-range
4769 (cons id-start id-end)))
4770 (goto-char id-end)
4771 (c-forward-syntactic-ws)
4772 (setq pos (point)
4773 res t)))
4774
4775 (progn
4776 (goto-char pos)
4777 (when (or c-opt-identifier-concat-key
4778 c-recognize-<>-arglists)
4779
4780 (cond
4781 ((and c-opt-identifier-concat-key
4782 (looking-at c-opt-identifier-concat-key))
4783 ;; Got a concatenated identifier. This handles the
4784 ;; cases with tricky syntactic whitespace that aren't
4785 ;; covered in `c-identifier-key'.
4786 (goto-char (match-end 0))
4787 (c-forward-syntactic-ws)
4788 t)
4789
4790 ((and c-recognize-<>-arglists
4791 (eq (char-after) ?<))
4792 ;; Maybe an angle bracket arglist.
0386b551
AM
4793
4794 (when (let (c-record-type-identifiers
4795 c-record-found-types)
4796 (c-forward-<>-arglist nil))
4797
4798 (c-add-type start (1+ pos))
d9e94c22 4799 (c-forward-syntactic-ws)
0386b551
AM
4800 (setq pos (point)
4801 c-last-identifier-range nil)
4802
d9e94c22
MS
4803 (if (and c-opt-identifier-concat-key
4804 (looking-at c-opt-identifier-concat-key))
0386b551 4805
d9e94c22
MS
4806 ;; Continue if there's an identifier concatenation
4807 ;; operator after the template argument.
4808 (progn
0386b551
AM
4809 (when (and c-record-type-identifiers id-start)
4810 (c-record-ref-id (cons id-start id-end)))
d9e94c22
MS
4811 (forward-char 2)
4812 (c-forward-syntactic-ws)
4813 t)
0386b551
AM
4814
4815 (when (and c-record-type-identifiers id-start)
4816 (c-record-type-id (cons id-start id-end)))
d9e94c22
MS
4817 (setq res 'template)
4818 nil)))
4819 )))))
4820
4821 (goto-char pos)
4822 res))
4823
4824(defun c-forward-type ()
4825 ;; Move forward over a type spec if at the beginning of one,
4826 ;; stopping at the next following token. Return t if it's a known
2a15eb73
MS
4827 ;; type that can't be a name or other expression, 'known if it's an
4828 ;; otherwise known type (according to `*-font-lock-extra-types'),
4829 ;; 'prefix if it's a known prefix of a type, 'found if it's a type
4830 ;; that matches one in `c-found-types', 'maybe if it's an identfier
4831 ;; that might be a type, or nil if it can't be a type (the point
4832 ;; isn't moved then). The point is assumed to be at the beginning
4833 ;; of a token.
d9e94c22
MS
4834 ;;
4835 ;; Note that this function doesn't skip past the brace definition
4836 ;; that might be considered part of the type, e.g.
4837 ;; "enum {a, b, c} foo".
0386b551
AM
4838 ;;
4839 ;; This function records identifier ranges on
4840 ;; `c-record-type-identifiers' and `c-record-ref-identifiers' if
4841 ;; `c-record-type-identifiers' is non-nil.
4842 ;;
4843 ;; This function might do hidden buffer changes.
4844
4845 (let ((start (point)) pos res name-res id-start id-end id-range)
d9e94c22
MS
4846
4847 ;; Skip leading type modifiers. If any are found we know it's a
4848 ;; prefix of a type.
4849 (when c-opt-type-modifier-key
4850 (while (looking-at c-opt-type-modifier-key)
4851 (goto-char (match-end 1))
4852 (c-forward-syntactic-ws)
4853 (setq res 'prefix)))
4854
4855 (cond
4856 ((looking-at c-type-prefix-key)
4857 ;; Looking at a keyword that prefixes a type identifier,
4858 ;; e.g. "class".
4859 (goto-char (match-end 1))
4860 (c-forward-syntactic-ws)
4861 (setq pos (point))
0386b551 4862 (if (memq (setq name-res (c-forward-name)) '(t template))
d9e94c22 4863 (progn
0386b551 4864 (when (eq name-res t)
d9e94c22
MS
4865 ;; In many languages the name can be used without the
4866 ;; prefix, so we add it to `c-found-types'.
4867 (c-add-type pos (point))
0386b551
AM
4868 (when (and c-record-type-identifiers
4869 c-last-identifier-range)
d9e94c22
MS
4870 (c-record-type-id c-last-identifier-range)))
4871 (setq res t))
4872 ;; Invalid syntax.
4873 (goto-char start)
4874 (setq res nil)))
4875
4876 ((progn
4877 (setq pos nil)
4878 (if (looking-at c-identifier-start)
4879 (save-excursion
4880 (setq id-start (point)
0386b551
AM
4881 name-res (c-forward-name))
4882 (when name-res
d9e94c22
MS
4883 (setq id-end (point)
4884 id-range c-last-identifier-range))))
4885 (and (cond ((looking-at c-primitive-type-key)
4886 (setq res t))
4887 ((c-with-syntax-table c-identifier-syntax-table
4888 (looking-at c-known-type-key))
4889 (setq res 'known)))
4890 (or (not id-end)
4891 (>= (save-excursion
4892 (save-match-data
4893 (goto-char (match-end 1))
4894 (c-forward-syntactic-ws)
4895 (setq pos (point))))
4896 id-end)
4897 (setq res nil))))
4898 ;; Looking at a primitive or known type identifier. We've
4899 ;; checked for a name first so that we don't go here if the
4900 ;; known type match only is a prefix of another name.
4901
4902 (setq id-end (match-end 1))
4903
4904 (when (and c-record-type-identifiers
4905 (or c-promote-possible-types (eq res t)))
4906 (c-record-type-id (cons (match-beginning 1) (match-end 1))))
4907
4908 (if (and c-opt-type-component-key
4909 (save-match-data
4910 (looking-at c-opt-type-component-key)))
4911 ;; There might be more keywords for the type.
4912 (let (safe-pos)
0386b551 4913 (c-forward-keyword-clause 1)
d9e94c22
MS
4914 (while (progn
4915 (setq safe-pos (point))
4916 (looking-at c-opt-type-component-key))
4917 (when (and c-record-type-identifiers
4918 (looking-at c-primitive-type-key))
4919 (c-record-type-id (cons (match-beginning 1)
4920 (match-end 1))))
0386b551 4921 (c-forward-keyword-clause 1))
d9e94c22
MS
4922 (if (looking-at c-primitive-type-key)
4923 (progn
4924 (when c-record-type-identifiers
4925 (c-record-type-id (cons (match-beginning 1)
4926 (match-end 1))))
0386b551 4927 (c-forward-keyword-clause 1)
d9e94c22
MS
4928 (setq res t))
4929 (goto-char safe-pos)
4930 (setq res 'prefix)))
0386b551 4931 (unless (save-match-data (c-forward-keyword-clause 1))
d9e94c22
MS
4932 (if pos
4933 (goto-char pos)
4934 (goto-char (match-end 1))
4935 (c-forward-syntactic-ws)))))
4936
0386b551
AM
4937 (name-res
4938 (cond ((eq name-res t)
d9e94c22
MS
4939 ;; A normal identifier.
4940 (goto-char id-end)
4941 (if (or res c-promote-possible-types)
4942 (progn
4943 (c-add-type id-start id-end)
0386b551 4944 (when (and c-record-type-identifiers id-range)
d9e94c22
MS
4945 (c-record-type-id id-range))
4946 (unless res
4947 (setq res 'found)))
4948 (setq res (if (c-check-type id-start id-end)
4949 ;; It's an identifier that has been used as
4950 ;; a type somewhere else.
4951 'found
4952 ;; It's an identifier that might be a type.
4953 'maybe))))
0386b551 4954 ((eq name-res 'template)
d9e94c22
MS
4955 ;; A template is a type.
4956 (goto-char id-end)
4957 (setq res t))
4958 (t
4959 ;; Otherwise it's an operator identifier, which is not a type.
4960 (goto-char start)
4961 (setq res nil)))))
4962
4963 (when res
4964 ;; Skip trailing type modifiers. If any are found we know it's
4965 ;; a type.
4966 (when c-opt-type-modifier-key
4967 (while (looking-at c-opt-type-modifier-key)
4968 (goto-char (match-end 1))
4969 (c-forward-syntactic-ws)
4970 (setq res t)))
4971
4972 ;; Step over any type suffix operator. Do not let the existence
4973 ;; of these alter the classification of the found type, since
4974 ;; these operators typically are allowed in normal expressions
4975 ;; too.
4976 (when c-opt-type-suffix-key
4977 (while (looking-at c-opt-type-suffix-key)
4978 (goto-char (match-end 1))
4979 (c-forward-syntactic-ws)))
4980
4981 (when c-opt-type-concat-key
0386b551
AM
4982 ;; Look for a trailing operator that concatenates the type
4983 ;; with a following one, and if so step past that one through
4984 ;; a recursive call. Note that we don't record concatenated
4985 ;; types in `c-found-types' - it's the component types that
4986 ;; are recorded when appropriate.
d9e94c22
MS
4987 (setq pos (point))
4988 (let* ((c-promote-possible-types (or (memq res '(t known))
4989 c-promote-possible-types))
4990 ;; If we can't promote then set `c-record-found-types' so that
4991 ;; we can merge in the types from the second part afterwards if
4992 ;; it turns out to be a known type there.
4993 (c-record-found-types (and c-record-type-identifiers
0386b551
AM
4994 (not c-promote-possible-types)))
4995 subres)
d9e94c22
MS
4996 (if (and (looking-at c-opt-type-concat-key)
4997
4998 (progn
4999 (goto-char (match-end 1))
5000 (c-forward-syntactic-ws)
0386b551 5001 (setq subres (c-forward-type))))
d9e94c22
MS
5002
5003 (progn
5004 ;; If either operand certainly is a type then both are, but we
5005 ;; don't let the existence of the operator itself promote two
5006 ;; uncertain types to a certain one.
5007 (cond ((eq res t))
0386b551
AM
5008 ((eq subres t)
5009 (unless (eq name-res 'template)
5010 (c-add-type id-start id-end))
5011 (when (and c-record-type-identifiers id-range)
d9e94c22
MS
5012 (c-record-type-id id-range))
5013 (setq res t))
2a15eb73 5014 ((eq res 'known))
0386b551 5015 ((eq subres 'known)
2a15eb73 5016 (setq res 'known))
d9e94c22 5017 ((eq res 'found))
0386b551 5018 ((eq subres 'found)
d9e94c22
MS
5019 (setq res 'found))
5020 (t
5021 (setq res 'maybe)))
5022
5023 (when (and (eq res t)
5024 (consp c-record-found-types))
5025 ;; Merge in the ranges of any types found by the second
5026 ;; `c-forward-type'.
5027 (setq c-record-type-identifiers
5028 ;; `nconc' doesn't mind that the tail of
5029 ;; `c-record-found-types' is t.
5030 (nconc c-record-found-types
5031 c-record-type-identifiers))))
5032
5033 (goto-char pos))))
5034
5035 (when (and c-record-found-types (memq res '(known found)) id-range)
5036 (setq c-record-found-types
5037 (cons id-range c-record-found-types))))
5038
5039 ;;(message "c-forward-type %s -> %s: %s" start (point) res)
5040
5041 res))
5042
785eecbb 5043\f
d9e94c22
MS
5044;; Handling of large scale constructs like statements and declarations.
5045
0386b551
AM
5046;; Macro used inside `c-forward-decl-or-cast-1'. It ought to be a
5047;; defsubst or perhaps even a defun, but it contains lots of free
5048;; variables that refer to things inside `c-forward-decl-or-cast-1'.
5049(defmacro c-fdoc-shift-type-backward (&optional short)
5050 ;; `c-forward-decl-or-cast-1' can consume an arbitrary length list
5051 ;; of types when parsing a declaration, which means that it
5052 ;; sometimes consumes the identifier in the declaration as a type.
5053 ;; This is used to "backtrack" and make the last type be treated as
5054 ;; an identifier instead.
5055 `(progn
5056 ,(unless short
5057 ;; These identifiers are bound only in the inner let.
5058 '(setq identifier-type at-type
5059 identifier-start type-start
5060 got-parens nil
5061 got-identifier t
5062 got-suffix t
5063 got-suffix-after-parens id-start
5064 paren-depth 0))
5065
5066 (if (setq at-type (if (eq backup-at-type 'prefix)
5067 t
5068 backup-at-type))
5069 (setq type-start backup-type-start
5070 id-start backup-id-start)
5071 (setq type-start start-pos
5072 id-start start-pos))
5073
5074 ;; When these flags already are set we've found specifiers that
5075 ;; unconditionally signal these attributes - backtracking doesn't
5076 ;; change that. So keep them set in that case.
5077 (or at-type-decl
5078 (setq at-type-decl backup-at-type-decl))
5079 (or maybe-typeless
5080 (setq maybe-typeless backup-maybe-typeless))
5081
5082 ,(unless short
5083 ;; This identifier is bound only in the inner let.
5084 '(setq start id-start))))
5085
5086(defun c-forward-decl-or-cast-1 (preceding-token-end context last-cast-end)
5087 ;; Move forward over a declaration or a cast if at the start of one.
5088 ;; The point is assumed to be at the start of some token. Nil is
5089 ;; returned if no declaration or cast is recognized, and the point
5090 ;; is clobbered in that case.
5091 ;;
5092 ;; If a declaration is parsed:
5093 ;;
5094 ;; The point is left at the first token after the first complete
5095 ;; declarator, if there is one. The return value is a cons where
5096 ;; the car is the position of the first token in the declarator.
5097 ;; Some examples:
5098 ;;
5099 ;; void foo (int a, char *b) stuff ...
5100 ;; car ^ ^ point
5101 ;; float (*a)[], b;
5102 ;; car ^ ^ point
5103 ;; unsigned int a = c_style_initializer, b;
5104 ;; car ^ ^ point
5105 ;; unsigned int a (cplusplus_style_initializer), b;
5106 ;; car ^ ^ point (might change)
5107 ;; class Foo : public Bar {}
5108 ;; car ^ ^ point
5109 ;; class PikeClass (int a, string b) stuff ...
5110 ;; car ^ ^ point
5111 ;; enum bool;
5112 ;; car ^ ^ point
5113 ;; enum bool flag;
5114 ;; car ^ ^ point
5115 ;; void cplusplus_function (int x) throw (Bad);
5116 ;; car ^ ^ point
5117 ;; Foo::Foo (int b) : Base (b) {}
5118 ;; car ^ ^ point
5119 ;;
5120 ;; The cdr of the return value is non-nil iff a
5121 ;; `c-typedef-decl-kwds' specifier is found in the declaration,
5122 ;; i.e. the declared identifier(s) are types.
5123 ;;
5124 ;; If a cast is parsed:
5125 ;;
5126 ;; The point is left at the first token after the closing paren of
5127 ;; the cast. The return value is `cast'. Note that the start
5128 ;; position must be at the first token inside the cast parenthesis
5129 ;; to recognize it.
5130 ;;
5131 ;; PRECEDING-TOKEN-END is the first position after the preceding
5132 ;; token, i.e. on the other side of the syntactic ws from the point.
5133 ;; Use a value less than or equal to (point-min) if the point is at
5134 ;; the first token in (the visible part of) the buffer.
5135 ;;
5136 ;; CONTEXT is a symbol that describes the context at the point:
5137 ;; 'decl In a comma-separatded declaration context (typically
5138 ;; inside a function declaration arglist).
5139 ;; '<> In an angle bracket arglist.
5140 ;; 'arglist Some other type of arglist.
5141 ;; nil Some other context or unknown context.
5142 ;;
5143 ;; LAST-CAST-END is the first token after the closing paren of a
5144 ;; preceding cast, or nil if none is known. If
5145 ;; `c-forward-decl-or-cast-1' is used in succession, it should be
5146 ;; the position after the closest preceding call where a cast was
5147 ;; matched. In that case it's used to discover chains of casts like
5148 ;; "(a) (b) c".
5149 ;;
5150 ;; This function records identifier ranges on
5151 ;; `c-record-type-identifiers' and `c-record-ref-identifiers' if
5152 ;; `c-record-type-identifiers' is non-nil.
5153 ;;
5154 ;; This function might do hidden buffer changes.
5155
5156 (let (;; `start-pos' is used below to point to the start of the
5157 ;; first type, i.e. after any leading specifiers. It might
5158 ;; also point at the beginning of the preceding syntactic
5159 ;; whitespace.
5160 (start-pos (point))
5161 ;; Set to the result of `c-forward-type'.
5162 at-type
5163 ;; The position of the first token in what we currently
5164 ;; believe is the type in the declaration or cast, after any
5165 ;; specifiers and their associated clauses.
5166 type-start
5167 ;; The position of the first token in what we currently
5168 ;; believe is the declarator for the first identifier. Set
5169 ;; when the type is found, and moved forward over any
5170 ;; `c-decl-hangon-kwds' and their associated clauses that
5171 ;; occurs after the type.
5172 id-start
5173 ;; These store `at-type', `type-start' and `id-start' of the
5174 ;; identifier before the one in those variables. The previous
5175 ;; identifier might turn out to be the real type in a
5176 ;; declaration if the last one has to be the declarator in it.
5177 ;; If `backup-at-type' is nil then the other variables have
5178 ;; undefined values.
5179 backup-at-type backup-type-start backup-id-start
5180 ;; Set if we've found a specifier that makes the defined
5181 ;; identifier(s) types.
5182 at-type-decl
5183 ;; Set if we've found a specifier that can start a declaration
5184 ;; where there's no type.
5185 maybe-typeless
5186 ;; If a specifier is found that also can be a type prefix,
5187 ;; these flags are set instead of those above. If we need to
5188 ;; back up an identifier, they are copied to the real flag
5189 ;; variables. Thus they only take effect if we fail to
5190 ;; interpret it as a type.
5191 backup-at-type-decl backup-maybe-typeless
5192 ;; Whether we've found a declaration or a cast. We might know
5193 ;; this before we've found the type in it. It's 'ids if we've
5194 ;; found two consecutive identifiers (usually a sure sign, but
5195 ;; we should allow that in labels too), and t if we've found a
5196 ;; specifier keyword (a 100% sure sign).
5197 at-decl-or-cast
5198 ;; Set when we need to back up to parse this as a declaration
5199 ;; but not as a cast.
5200 backup-if-not-cast
5201 ;; For casts, the return position.
5202 cast-end
5203 ;; Save `c-record-type-identifiers' and
5204 ;; `c-record-ref-identifiers' since ranges are recorded
5205 ;; speculatively and should be thrown away if it turns out
5206 ;; that it isn't a declaration or cast.
5207 (save-rec-type-ids c-record-type-identifiers)
5208 (save-rec-ref-ids c-record-ref-identifiers))
5209
5210 ;; Check for a type. Unknown symbols are treated as possible
5211 ;; types, but they could also be specifiers disguised through
5212 ;; macros like __INLINE__, so we recognize both types and known
5213 ;; specifiers after them too.
5214 (while
5215 (let* ((start (point)) kwd-sym kwd-clause-end found-type)
5216
5217 ;; Look for a specifier keyword clause.
5218 (when (looking-at c-prefix-spec-kwds-re)
5219 (setq kwd-sym (c-keyword-sym (match-string 1)))
5220 (save-excursion
5221 (c-forward-keyword-clause 1)
5222 (setq kwd-clause-end (point))))
5223
5224 (when (setq found-type (c-forward-type))
5225 ;; Found a known or possible type or a prefix of a known type.
5226
5227 (when at-type
5228 ;; Got two identifiers with nothing but whitespace
5229 ;; between them. That can only happen in declarations.
5230 (setq at-decl-or-cast 'ids)
5231
5232 (when (eq at-type 'found)
5233 ;; If the previous identifier is a found type we
5234 ;; record it as a real one; it might be some sort of
5235 ;; alias for a prefix like "unsigned".
5236 (save-excursion
5237 (goto-char type-start)
5238 (let ((c-promote-possible-types t))
5239 (c-forward-type)))))
5240
5241 (setq backup-at-type at-type
5242 backup-type-start type-start
5243 backup-id-start id-start
5244 at-type found-type
5245 type-start start
5246 id-start (point)
5247 ;; The previous ambiguous specifier/type turned out
5248 ;; to be a type since we've parsed another one after
5249 ;; it, so clear these backup flags.
5250 backup-at-type-decl nil
5251 backup-maybe-typeless nil))
5252
5253 (if kwd-sym
5254 (progn
5255 ;; Handle known specifier keywords and
5256 ;; `c-decl-hangon-kwds' which can occur after known
5257 ;; types.
5258
5259 (if (c-keyword-member kwd-sym 'c-decl-hangon-kwds)
5260 ;; It's a hang-on keyword that can occur anywhere.
5261 (progn
5262 (setq at-decl-or-cast t)
5263 (if at-type
5264 ;; Move the identifier start position if
5265 ;; we've passed a type.
5266 (setq id-start kwd-clause-end)
5267 ;; Otherwise treat this as a specifier and
5268 ;; move the fallback position.
5269 (setq start-pos kwd-clause-end))
5270 (goto-char kwd-clause-end))
5271
5272 ;; It's an ordinary specifier so we know that
5273 ;; anything before this can't be the type.
5274 (setq backup-at-type nil
5275 start-pos kwd-clause-end)
5276
5277 (if found-type
5278 ;; It's ambiguous whether this keyword is a
5279 ;; specifier or a type prefix, so set the backup
5280 ;; flags. (It's assumed that `c-forward-type'
5281 ;; moved further than `c-forward-keyword-clause'.)
5282 (progn
5283 (when (c-keyword-member kwd-sym 'c-typedef-decl-kwds)
5284 (setq backup-at-type-decl t))
5285 (when (c-keyword-member kwd-sym 'c-typeless-decl-kwds)
5286 (setq backup-maybe-typeless t)))
5287
5288 (when (c-keyword-member kwd-sym 'c-typedef-decl-kwds)
5289 (setq at-type-decl t))
5290 (when (c-keyword-member kwd-sym 'c-typeless-decl-kwds)
5291 (setq maybe-typeless t))
5292
5293 ;; Haven't matched a type so it's an umambiguous
5294 ;; specifier keyword and we know we're in a
5295 ;; declaration.
5296 (setq at-decl-or-cast t)
5297
5298 (goto-char kwd-clause-end))))
5299
5300 ;; If the type isn't known we continue so that we'll jump
5301 ;; over all specifiers and type identifiers. The reason
5302 ;; to do this for a known type prefix is to make things
5303 ;; like "unsigned INT16" work.
5304 (and found-type (not (eq found-type t))))))
5305
5306 (cond
5307 ((eq at-type t)
5308 ;; If a known type was found, we still need to skip over any
5309 ;; hangon keyword clauses after it. Otherwise it has already
5310 ;; been done in the loop above.
5311 (while (looking-at c-decl-hangon-key)
5312 (c-forward-keyword-clause 1))
5313 (setq id-start (point)))
5314
5315 ((eq at-type 'prefix)
5316 ;; A prefix type is itself a primitive type when it's not
5317 ;; followed by another type.
5318 (setq at-type t))
5319
5320 ((not at-type)
5321 ;; Got no type but set things up to continue anyway to handle
5322 ;; the various cases when a declaration doesn't start with a
5323 ;; type.
5324 (setq id-start start-pos))
5325
5326 ((and (eq at-type 'maybe)
5327 (c-major-mode-is 'c++-mode))
5328 ;; If it's C++ then check if the last "type" ends on the form
5329 ;; "foo::foo" or "foo::~foo", i.e. if it's the name of a
5330 ;; (con|de)structor.
5331 (save-excursion
5332 (let (name end-2 end-1)
5333 (goto-char id-start)
5334 (c-backward-syntactic-ws)
5335 (setq end-2 (point))
5336 (when (and
5337 (c-simple-skip-symbol-backward)
5338 (progn
5339 (setq name
5340 (buffer-substring-no-properties (point) end-2))
5341 ;; Cheating in the handling of syntactic ws below.
5342 (< (skip-chars-backward ":~ \t\n\r\v\f") 0))
5343 (progn
5344 (setq end-1 (point))
5345 (c-simple-skip-symbol-backward))
5346 (>= (point) type-start)
5347 (equal (buffer-substring-no-properties (point) end-1)
5348 name))
5349 ;; It is a (con|de)structor name. In that case the
5350 ;; declaration is typeless so zap out any preceding
5351 ;; identifier(s) that we might have taken as types.
5352 (goto-char type-start)
5353 (setq at-type nil
5354 backup-at-type nil
5355 id-start type-start))))))
5356
5357 ;; Check for and step over a type decl expression after the thing
5358 ;; that is or might be a type. This can't be skipped since we
5359 ;; need the correct end position of the declarator for
5360 ;; `max-type-decl-end-*'.
5361 (let ((start (point)) (paren-depth 0) pos
5362 ;; True if there's a non-open-paren match of
5363 ;; `c-type-decl-prefix-key'.
5364 got-prefix
5365 ;; True if the declarator is surrounded by a parenthesis pair.
5366 got-parens
5367 ;; True if there is an identifier in the declarator.
5368 got-identifier
5369 ;; True if there's a non-close-paren match of
5370 ;; `c-type-decl-suffix-key'.
5371 got-suffix
5372 ;; True if there's a prefix match outside the outermost
5373 ;; paren pair that surrounds the declarator.
5374 got-prefix-before-parens
5375y ;; True if there's a suffix match outside the outermost
5376 ;; paren pair that surrounds the declarator. The value is
5377 ;; the position of the first suffix match.
5378 got-suffix-after-parens
5379 ;; True if we've parsed the type decl to a token that is
5380 ;; known to end declarations in this context.
5381 at-decl-end
5382 ;; The earlier values of `at-type' and `type-start' if we've
5383 ;; shifted the type backwards.
5384 identifier-type identifier-start
5385 ;; If `c-parse-and-markup-<>-arglists' is set we need to
5386 ;; turn it off during the name skipping below to avoid
5387 ;; getting `c-type' properties that might be bogus. That
5388 ;; can happen since we don't know if
5389 ;; `c-restricted-<>-arglists' will be correct inside the
5390 ;; arglist paren that gets entered.
5391 c-parse-and-markup-<>-arglists)
5392
5393 (goto-char id-start)
5394
5395 ;; Skip over type decl prefix operators. (Note similar code in
5396 ;; `c-font-lock-declarators'.)
5397 (while (and (looking-at c-type-decl-prefix-key)
5398 (if (and (c-major-mode-is 'c++-mode)
5399 (match-beginning 2))
5400 ;; If the second submatch matches in C++ then
5401 ;; we're looking at an identifier that's a
5402 ;; prefix only if it specifies a member pointer.
5403 (when (setq got-identifier (c-forward-name))
5404 (if (looking-at "\\(::\\)")
5405 ;; We only check for a trailing "::" and
5406 ;; let the "*" that should follow be
5407 ;; matched in the next round.
5408 (progn (setq got-identifier nil) t)
5409 ;; It turned out to be the real identifier,
5410 ;; so stop.
5411 nil))
5412 t))
5413
5414 (if (eq (char-after) ?\()
5415 (progn
5416 (setq paren-depth (1+ paren-depth))
5417 (forward-char))
5418 (unless got-prefix-before-parens
5419 (setq got-prefix-before-parens (= paren-depth 0)))
5420 (setq got-prefix t)
5421 (goto-char (match-end 1)))
5422 (c-forward-syntactic-ws))
5423
5424 (setq got-parens (> paren-depth 0))
5425
5426 ;; Skip over an identifier.
5427 (or got-identifier
5428 (and (looking-at c-identifier-start)
5429 (setq got-identifier (c-forward-name))))
5430
5431 ;; Skip over type decl suffix operators.
5432 (while (if (looking-at c-type-decl-suffix-key)
5433
5434 (if (eq (char-after) ?\))
5435 (when (> paren-depth 0)
5436 (setq paren-depth (1- paren-depth))
5437 (forward-char)
5438 t)
5439 (when (if (save-match-data (looking-at "\\s\("))
5440 (c-safe (c-forward-sexp 1) t)
5441 (goto-char (match-end 1))
5442 t)
5443 (when (and (not got-suffix-after-parens)
5444 (= paren-depth 0))
5445 (setq got-suffix-after-parens (match-beginning 0)))
5446 (setq got-suffix t)))
5447
5448 ;; No suffix matched. We might have matched the
5449 ;; identifier as a type and the open paren of a
5450 ;; function arglist as a type decl prefix. In that
5451 ;; case we should "backtrack": Reinterpret the last
5452 ;; type as the identifier, move out of the arglist and
5453 ;; continue searching for suffix operators.
5454 ;;
5455 ;; Do this even if there's no preceding type, to cope
5456 ;; with old style function declarations in K&R C,
5457 ;; (con|de)structors in C++ and `c-typeless-decl-kwds'
5458 ;; style declarations. That isn't applicable in an
5459 ;; arglist context, though.
5460 (when (and (= paren-depth 1)
5461 (not got-prefix-before-parens)
5462 (not (eq at-type t))
5463 (or backup-at-type
5464 maybe-typeless
5465 backup-maybe-typeless
5466 (when c-recognize-typeless-decls
5467 (not context)))
5468 (setq pos (c-up-list-forward (point)))
5469 (eq (char-before pos) ?\)))
5470 (c-fdoc-shift-type-backward)
5471 (goto-char pos)
5472 t))
5473
5474 (c-forward-syntactic-ws))
5475
5476 (when (and (or maybe-typeless backup-maybe-typeless)
5477 (not got-identifier)
5478 (not got-prefix)
5479 at-type)
5480 ;; Have found no identifier but `c-typeless-decl-kwds' has
5481 ;; matched so we know we're inside a declaration. The
5482 ;; preceding type must be the identifier instead.
5483 (c-fdoc-shift-type-backward))
5484
5485 (setq
5486 at-decl-or-cast
5487 (catch 'at-decl-or-cast
5488
5489 (when (> paren-depth 0)
5490 ;; Encountered something inside parens that isn't matched by
5491 ;; the `c-type-decl-*' regexps, so it's not a type decl
5492 ;; expression. Try to skip out to the same paren depth to
5493 ;; not confuse the cast check below.
5494 (c-safe (goto-char (scan-lists (point) 1 paren-depth)))
5495 ;; If we've found a specifier keyword then it's a
5496 ;; declaration regardless.
5497 (throw 'at-decl-or-cast (eq at-decl-or-cast t)))
5498
5499 (setq at-decl-end
5500 (looking-at (cond ((eq context '<>) "[,>]")
5501 (context "[,\)]")
5502 (t "[,;]"))))
5503
5504 ;; Now we've collected info about various characteristics of
5505 ;; the construct we're looking at. Below follows a decision
5506 ;; tree based on that. It's ordered to check more certain
5507 ;; signs before less certain ones.
5508
5509 (if got-identifier
5510 (progn
5511
5512 (when (and (or at-type maybe-typeless)
5513 (not (or got-prefix got-parens)))
5514 ;; Got another identifier directly after the type, so it's a
5515 ;; declaration.
5516 (throw 'at-decl-or-cast t))
5517
5518 (when (and got-parens
5519 (not got-prefix)
5520 (not got-suffix-after-parens)
5521 (or backup-at-type
5522 maybe-typeless
5523 backup-maybe-typeless))
5524 ;; Got a declaration of the form "foo bar (gnu);" where we've
5525 ;; recognized "bar" as the type and "gnu" as the declarator.
5526 ;; In this case it's however more likely that "bar" is the
5527 ;; declarator and "gnu" a function argument or initializer (if
5528 ;; `c-recognize-paren-inits' is set), since the parens around
5529 ;; "gnu" would be superfluous if it's a declarator. Shift the
5530 ;; type one step backward.
5531 (c-fdoc-shift-type-backward)))
5532
5533 ;; Found no identifier.
5534
5535 (if backup-at-type
5536 (progn
5537
5538 (when (= (point) start)
5539 ;; Got a plain list of identifiers. If a colon follows it's
5540 ;; a valid label. Otherwise the last one probably is the
5541 ;; declared identifier and we should back up to the previous
5542 ;; type, providing it isn't a cast.
5543 (if (eq (char-after) ?:)
5544 ;; If we've found a specifier keyword then it's a
5545 ;; declaration regardless.
5546 (throw 'at-decl-or-cast (eq at-decl-or-cast t))
5547 (setq backup-if-not-cast t)
5548 (throw 'at-decl-or-cast t)))
5549
5550 (when (and got-suffix
5551 (not got-prefix)
5552 (not got-parens))
5553 ;; Got a plain list of identifiers followed by some suffix.
5554 ;; If this isn't a cast then the last identifier probably is
5555 ;; the declared one and we should back up to the previous
5556 ;; type.
5557 (setq backup-if-not-cast t)
5558 (throw 'at-decl-or-cast t)))
5559
5560 (when (eq at-type t)
5561 ;; If the type is known we know that there can't be any
5562 ;; identifier somewhere else, and it's only in declarations in
5563 ;; e.g. function prototypes and in casts that the identifier may
5564 ;; be left out.
5565 (throw 'at-decl-or-cast t))
5566
5567 (when (= (point) start)
5568 ;; Only got a single identifier (parsed as a type so far).
5569 (if (and
5570 ;; Check that the identifier isn't at the start of an
5571 ;; expression.
5572 at-decl-end
5573 (cond
5574 ((eq context 'decl)
5575 ;; Inside an arglist that contains declarations. If K&R
5576 ;; style declarations and parenthesis style initializers
5577 ;; aren't allowed then the single identifier must be a
5578 ;; type, else we require that it's known or found
5579 ;; (primitive types are handled above).
5580 (or (and (not c-recognize-knr-p)
5581 (not c-recognize-paren-inits))
5582 (memq at-type '(known found))))
5583 ((eq context '<>)
5584 ;; Inside a template arglist. Accept known and found
5585 ;; types; other identifiers could just as well be
5586 ;; constants in C++.
5587 (memq at-type '(known found)))))
5588 (throw 'at-decl-or-cast t)
5589 ;; Can't be a valid declaration or cast, but if we've found a
5590 ;; specifier it can't be anything else either, so treat it as
5591 ;; an invalid/unfinished declaration or cast.
5592 (throw 'at-decl-or-cast at-decl-or-cast))))
5593
5594 (if (and got-parens
5595 (not got-prefix)
5596 (not context)
5597 (not (eq at-type t))
5598 (or backup-at-type
5599 maybe-typeless
5600 backup-maybe-typeless
5601 (when c-recognize-typeless-decls
5602 (or (not got-suffix)
5603 (not (looking-at
5604 c-after-suffixed-type-maybe-decl-key))))))
5605 ;; Got an empty paren pair and a preceding type that probably
5606 ;; really is the identifier. Shift the type backwards to make
5607 ;; the last one the identifier. This is analogous to the
5608 ;; "backtracking" done inside the `c-type-decl-suffix-key' loop
5609 ;; above.
5610 ;;
5611 ;; Exception: In addition to the conditions in that
5612 ;; "backtracking" code, do not shift backward if we're not
5613 ;; looking at either `c-after-suffixed-type-decl-key' or "[;,]".
5614 ;; Since there's no preceding type, the shift would mean that
5615 ;; the declaration is typeless. But if the regexp doesn't match
5616 ;; then we will simply fall through in the tests below and not
5617 ;; recognize it at all, so it's better to try it as an abstract
5618 ;; declarator instead.
5619 (c-fdoc-shift-type-backward)
5620
5621 ;; Still no identifier.
5622
5623 (when (and got-prefix (or got-parens got-suffix))
5624 ;; Require `got-prefix' together with either `got-parens' or
5625 ;; `got-suffix' to recognize it as an abstract declarator:
5626 ;; `got-parens' only is probably an empty function call.
5627 ;; `got-suffix' only can build an ordinary expression together
5628 ;; with the preceding identifier which we've taken as a type.
5629 ;; We could actually accept on `got-prefix' only, but that can
5630 ;; easily occur temporarily while writing an expression so we
5631 ;; avoid that case anyway. We could do a better job if we knew
5632 ;; the point when the fontification was invoked.
5633 (throw 'at-decl-or-cast t))
5634
5635 (when (and at-type
5636 (not got-prefix)
5637 (not got-parens)
5638 got-suffix-after-parens
5639 (eq (char-after got-suffix-after-parens) ?\())
5640 ;; Got a type, no declarator but a paren suffix. I.e. it's a
5641 ;; normal function call afterall (or perhaps a C++ style object
5642 ;; instantiation expression).
5643 (throw 'at-decl-or-cast nil))))
5644
5645 (when at-decl-or-cast
5646 ;; By now we've located the type in the declaration that we know
5647 ;; we're in.
5648 (throw 'at-decl-or-cast t))
5649
5650 (when (and got-identifier
5651 (not context)
5652 (looking-at c-after-suffixed-type-decl-key)
5653 (if (and got-parens
5654 (not got-prefix)
5655 (not got-suffix)
5656 (not (eq at-type t)))
5657 ;; Shift the type backward in the case that there's a
5658 ;; single identifier inside parens. That can only
5659 ;; occur in K&R style function declarations so it's
5660 ;; more likely that it really is a function call.
5661 ;; Therefore we only do this after
5662 ;; `c-after-suffixed-type-decl-key' has matched.
5663 (progn (c-fdoc-shift-type-backward) t)
5664 got-suffix-after-parens))
5665 ;; A declaration according to `c-after-suffixed-type-decl-key'.
5666 (throw 'at-decl-or-cast t))
5667
5668 (when (and (or got-prefix (not got-parens))
5669 (memq at-type '(t known)))
5670 ;; It's a declaration if a known type precedes it and it can't be a
5671 ;; function call.
5672 (throw 'at-decl-or-cast t))
5673
5674 ;; If we get here we can't tell if this is a type decl or a normal
5675 ;; expression by looking at it alone. (That's under the assumption
5676 ;; that normal expressions always can look like type decl expressions,
5677 ;; which isn't really true but the cases where it doesn't hold are so
5678 ;; uncommon (e.g. some placements of "const" in C++) it's not worth
5679 ;; the effort to look for them.)
5680
5681 (unless (or at-decl-end (looking-at "=[^=]"))
5682 ;; If this is a declaration it should end here or its initializer(*)
5683 ;; should start here, so check for allowed separation tokens. Note
5684 ;; that this rule doesn't work e.g. with a K&R arglist after a
5685 ;; function header.
5686 ;;
5687 ;; *) Don't check for C++ style initializers using parens
5688 ;; since those already have been matched as suffixes.
5689 ;;
5690 ;; If `at-decl-or-cast' is then we've found some other sign that
5691 ;; it's a declaration or cast, so then it's probably an
5692 ;; invalid/unfinished one.
5693 (throw 'at-decl-or-cast at-decl-or-cast))
5694
5695 ;; Below are tests that only should be applied when we're certain to
5696 ;; not have parsed halfway through an expression.
5697
5698 (when (memq at-type '(t known))
5699 ;; The expression starts with a known type so treat it as a
5700 ;; declaration.
5701 (throw 'at-decl-or-cast t))
5702
5703 (when (and (c-major-mode-is 'c++-mode)
5704 ;; In C++ we check if the identifier is a known type, since
5705 ;; (con|de)structors use the class name as identifier.
5706 ;; We've always shifted over the identifier as a type and
5707 ;; then backed up again in this case.
5708 identifier-type
5709 (or (memq identifier-type '(found known))
5710 (and (eq (char-after identifier-start) ?~)
5711 ;; `at-type' probably won't be 'found for
5712 ;; destructors since the "~" is then part of the
5713 ;; type name being checked against the list of
5714 ;; known types, so do a check without that
5715 ;; operator.
5716 (or (save-excursion
5717 (goto-char (1+ identifier-start))
5718 (c-forward-syntactic-ws)
5719 (c-with-syntax-table
5720 c-identifier-syntax-table
5721 (looking-at c-known-type-key)))
5722 (save-excursion
5723 (goto-char (1+ identifier-start))
5724 ;; We have already parsed the type earlier,
5725 ;; so it'd be possible to cache the end
5726 ;; position instead of redoing it here, but
5727 ;; then we'd need to keep track of another
5728 ;; position everywhere.
5729 (c-check-type (point)
5730 (progn (c-forward-type)
5731 (point))))))))
5732 (throw 'at-decl-or-cast t))
5733
5734 (if got-identifier
5735 (progn
5736 (when (and got-prefix-before-parens
5737 at-type
5738 (or at-decl-end (looking-at "=[^=]"))
5739 (not context)
5740 (not got-suffix))
5741 ;; Got something like "foo * bar;". Since we're not inside an
5742 ;; arglist it would be a meaningless expression because the
5743 ;; result isn't used. We therefore choose to recognize it as
5744 ;; a declaration. Do not allow a suffix since it could then
5745 ;; be a function call.
5746 (throw 'at-decl-or-cast t))
5747
5748 (when (and (or got-suffix-after-parens
5749 (looking-at "=[^=]"))
5750 (eq at-type 'found)
5751 (not (eq context 'arglist)))
5752 ;; Got something like "a (*b) (c);" or "a (b) = c;". It could
5753 ;; be an odd expression or it could be a declaration. Treat
5754 ;; it as a declaration if "a" has been used as a type
5755 ;; somewhere else (if it's a known type we won't get here).
5756 (throw 'at-decl-or-cast t)))
5757
5758 (when (and context
5759 (or got-prefix
5760 (and (eq context 'decl)
5761 (not c-recognize-paren-inits)
5762 (or got-parens got-suffix))))
5763 ;; Got a type followed by an abstract declarator. If `got-prefix'
5764 ;; is set it's something like "a *" without anything after it. If
5765 ;; `got-parens' or `got-suffix' is set it's "a()", "a[]", "a()[]",
5766 ;; or similar, which we accept only if the context rules out
5767 ;; expressions.
5768 (throw 'at-decl-or-cast t)))
5769
5770 ;; If we had a complete symbol table here (which rules out
5771 ;; `c-found-types') we should return t due to the disambiguation rule
5772 ;; (in at least C++) that anything that can be parsed as a declaration
5773 ;; is a declaration. Now we're being more defensive and prefer to
5774 ;; highlight things like "foo (bar);" as a declaration only if we're
5775 ;; inside an arglist that contains declarations.
5776 (eq context 'decl))))
5777
5778 ;; The point is now after the type decl expression.
5779
5780 (cond
5781 ;; Check for a cast.
5782 ((save-excursion
5783 (and
5784 c-cast-parens
5785
5786 ;; Should be the first type/identifier in a cast paren.
5787 (> preceding-token-end (point-min))
5788 (memq (char-before preceding-token-end) c-cast-parens)
5789
5790 ;; The closing paren should follow.
5791 (progn
5792 (c-forward-syntactic-ws)
5793 (looking-at "\\s\)"))
5794
5795 ;; There should be a primary expression after it.
5796 (let (pos)
5797 (forward-char)
5798 (c-forward-syntactic-ws)
5799 (setq cast-end (point))
5800 (and (looking-at c-primary-expr-regexp)
5801 (progn
5802 (setq pos (match-end 0))
5803 (or
5804 ;; Check if the expression begins with a prefix keyword.
5805 (match-beginning 2)
5806 (if (match-beginning 1)
5807 ;; Expression begins with an ambiguous operator. Treat
5808 ;; it as a cast if it's a type decl or if we've
5809 ;; recognized the type somewhere else.
5810 (or at-decl-or-cast
5811 (memq at-type '(t known found)))
5812 ;; Unless it's a keyword, it's the beginning of a primary
5813 ;; expression.
5814 (not (looking-at c-keywords-regexp)))))
5815 ;; If `c-primary-expr-regexp' matched a nonsymbol token, check
5816 ;; that it matched a whole one so that we don't e.g. confuse
5817 ;; the operator '-' with '->'. It's ok if it matches further,
5818 ;; though, since it e.g. can match the float '.5' while the
5819 ;; operator regexp only matches '.'.
5820 (or (not (looking-at c-nonsymbol-token-regexp))
5821 (<= (match-end 0) pos))))
5822
5823 ;; There should either be a cast before it or something that isn't an
5824 ;; identifier or close paren.
5825 (> preceding-token-end (point-min))
5826 (progn
5827 (goto-char (1- preceding-token-end))
5828 (or (eq (point) last-cast-end)
5829 (progn
5830 (c-backward-syntactic-ws)
5831 (if (< (skip-syntax-backward "w_") 0)
5832 ;; It's a symbol. Accept it only if it's one of the
5833 ;; keywords that can precede an expression (without
5834 ;; surrounding parens).
5835 (looking-at c-simple-stmt-key)
5836 (and
5837 ;; Check that it isn't a close paren (block close is ok,
5838 ;; though).
5839 (not (memq (char-before) '(?\) ?\])))
5840 ;; Check that it isn't a nonsymbol identifier.
5841 (not (c-on-identifier)))))))))
5842
5843 ;; Handle the cast.
5844 (when (and c-record-type-identifiers at-type (not (eq at-type t)))
5845 (let ((c-promote-possible-types t))
5846 (goto-char type-start)
5847 (c-forward-type)))
5848
5849 (goto-char cast-end)
5850 'cast)
5851
5852 (at-decl-or-cast
5853 ;; We're at a declaration. Highlight the type and the following
5854 ;; declarators.
5855
5856 (when backup-if-not-cast
5857 (c-fdoc-shift-type-backward t))
5858
5859 (when (and (eq context 'decl) (looking-at ","))
5860 ;; Make sure to propagate the `c-decl-arg-start' property to
5861 ;; the next argument if it's set in this one, to cope with
5862 ;; interactive refontification.
5863 (c-put-c-type-property (point) 'c-decl-arg-start))
5864
5865 (when (and c-record-type-identifiers at-type (not (eq at-type t)))
5866 (let ((c-promote-possible-types t))
5867 (save-excursion
5868 (goto-char type-start)
5869 (c-forward-type))))
5870
5871 (cons id-start at-type-decl))
5872
5873 (t
5874 ;; False alarm. Restore the recorded ranges.
5875 (setq c-record-type-identifiers save-rec-type-ids
5876 c-record-ref-identifiers save-rec-ref-ids)
5877 nil))))
5878
5879(defun c-forward-label (&optional assume-markup preceding-token-end limit)
51c9af45
AM
5880 ;; Assuming that point is at the beginning of a token, check if it starts a
5881 ;; label and if so move over it and return t, otherwise don't move and
5882 ;; return nil. "Label" here means "most things with a colon".
5883 ;;
5884 ;; More precisely, a "label" is regarded as one of:
5885 ;; (i) a goto target like "foo:";
5886 ;; (ii) A case label - either the entire construct "case FOO:" or just the
5887 ;; bare "case", should the colon be missing;
5888 ;; (iii) a keyword which needs a colon, like "default:" or "private:";
5889 ;; (iv) One of QT's "extended" C++ variants of
5890 ;; "private:"/"protected:"/"public:"/"more:" looking like "public slots:".
5891 ;; (v) One of the keywords matched by `c-opt-extra-label-key' (without any
5892 ;; colon). Currently (2006-03), this applies only to Objective C's
5893 ;; keywords "@private", "@protected", and "@public".
5894 ;;
5895 ;; One of the things which will NOT be recognised as a label is a bit-field
5896 ;; element of a struct, something like "int foo:5".
5897 ;;
5898 ;; The end of the label is taken to be just after the colon, or the end of
5899 ;; the first submatch in `c-opt-extra-label-key'. The point is directly
5900 ;; after the end on return. The terminating char gets marked with
5901 ;; `c-decl-end' to improve recognition of the following declaration or
5902 ;; statement.
0386b551
AM
5903 ;;
5904 ;; If ASSUME-MARKUP is non-nil, it's assumed that the preceding
51c9af45 5905 ;; label, if any, has already been marked up like that.
0386b551
AM
5906 ;;
5907 ;; If PRECEDING-TOKEN-END is given, it should be the first position
5908 ;; after the preceding token, i.e. on the other side of the
5909 ;; syntactic ws from the point. Use a value less than or equal to
5910 ;; (point-min) if the point is at the first token in (the visible
5911 ;; part of) the buffer.
5912 ;;
5913 ;; The optional LIMIT limits the forward scan for the colon.
5914 ;;
5915 ;; This function records the ranges of the label symbols on
5916 ;; `c-record-ref-identifiers' if `c-record-type-identifiers' (!) is
5917 ;; non-nil.
5918 ;;
5919 ;; This function might do hidden buffer changes.
5920
51c9af45
AM
5921 (let ((start (point))
5922 qt-symbol-idx
5923 macro-start) ; if we're in one.
0386b551 5924 (cond
51c9af45 5925 ;; "case" or "default" (Doesn't apply to AWK).
0386b551
AM
5926 ((looking-at c-label-kwds-regexp)
5927 (let ((kwd-end (match-end 1)))
5928 ;; Record only the keyword itself for fontification, since in
5929 ;; case labels the following is a constant expression and not
5930 ;; a label.
5931 (when c-record-type-identifiers
5932 (c-record-ref-id (cons (match-beginning 1) kwd-end)))
5933
5934 ;; Find the label end.
5935 (goto-char kwd-end)
5936 (if (and (c-syntactic-re-search-forward
5937 ;; Stop on chars that aren't allowed in expressions,
5938 ;; and on operator chars that would be meaningless
5939 ;; there. FIXME: This doesn't cope with ?: operators.
5940 "[;{=,@]\\|\\(\\=\\|[^:]\\):\\([^:]\\|\\'\\)"
5941 limit t t nil 1)
5942 (match-beginning 2))
5943
5944 (progn
51c9af45 5945 (goto-char (match-beginning 2)) ; just after the :
0386b551
AM
5946 (c-put-c-type-property (1- (point)) 'c-decl-end)
5947 t)
5948
5949 ;; It's an unfinished label. We consider the keyword enough
5950 ;; to recognize it as a label, so that it gets fontified.
5951 ;; Leave the point at the end of it, but don't put any
5952 ;; `c-decl-end' marker.
5953 (goto-char kwd-end)
5954 t)))
5955
51c9af45 5956 ;; @private, @protected, @public, in Objective C, or similar.
0386b551
AM
5957 ((and c-opt-extra-label-key
5958 (looking-at c-opt-extra-label-key))
5959 ;; For a `c-opt-extra-label-key' match, we record the whole
5960 ;; thing for fontification. That's to get the leading '@' in
5961 ;; Objective-C protection labels fontified.
5962 (goto-char (match-end 1))
5963 (when c-record-type-identifiers
5964 (c-record-ref-id (cons (match-beginning 1) (point))))
5965 (c-put-c-type-property (1- (point)) 'c-decl-end)
5966 t)
5967
51c9af45
AM
5968 ;; All other cases of labels.
5969 ((and c-recognize-colon-labels ; nil for AWK and IDL, otherwise t.
0386b551
AM
5970
5971 ;; A colon label must have something before the colon.
5972 (not (eq (char-after) ?:))
5973
5974 ;; Check that we're not after a token that can't precede a label.
5975 (or
5976 ;; Trivially succeeds when there's no preceding token.
5977 (if preceding-token-end
5978 (<= preceding-token-end (point-min))
5979 (save-excursion
5980 (c-backward-syntactic-ws)
5981 (setq preceding-token-end (point))
5982 (bobp)))
5983
5984 ;; Check if we're after a label, if we're after a closing
5985 ;; paren that belong to statement, and with
5986 ;; `c-label-prefix-re'. It's done in different order
5987 ;; depending on `assume-markup' since the checks have
5988 ;; different expensiveness.
5989 (if assume-markup
5990 (or
5991 (eq (c-get-char-property (1- preceding-token-end) 'c-type)
5992 'c-decl-end)
5993
5994 (save-excursion
5995 (goto-char (1- preceding-token-end))
5996 (c-beginning-of-current-token)
51c9af45
AM
5997 (or (looking-at c-label-prefix-re)
5998 (looking-at c-block-stmt-1-key)))
0386b551
AM
5999
6000 (and (eq (char-before preceding-token-end) ?\))
6001 (c-after-conditional)))
6002
6003 (or
6004 (save-excursion
6005 (goto-char (1- preceding-token-end))
6006 (c-beginning-of-current-token)
51c9af45
AM
6007 (or (looking-at c-label-prefix-re)
6008 (looking-at c-block-stmt-1-key)))
0386b551
AM
6009
6010 (cond
6011 ((eq (char-before preceding-token-end) ?\))
6012 (c-after-conditional))
6013
6014 ((eq (char-before preceding-token-end) ?:)
6015 ;; Might be after another label, so check it recursively.
51c9af45
AM
6016 (save-restriction
6017 (save-excursion
6018 (goto-char (1- preceding-token-end))
6019 ;; Essentially the same as the
6020 ;; `c-syntactic-re-search-forward' regexp below.
6021 (setq macro-start
6022 (save-excursion (and (c-beginning-of-macro)
6023 (point))))
6024 (if macro-start (narrow-to-region macro-start (point-max)))
6025 (c-syntactic-skip-backward "^-]:?;}=*/%&|,<>!@+" nil t)
6026 ;; Note: the following should work instead of the
6027 ;; narrow-to-region above. Investigate why not,
6028 ;; sometime. ACM, 2006-03-31.
6029 ;; (c-syntactic-skip-backward "^-]:?;}=*/%&|,<>!@+"
6030 ;; macro-start t)
6031 (let ((pte (point))
6032 ;; If the caller turned on recording for us,
6033 ;; it shouldn't apply when we check the
6034 ;; preceding label.
6035 c-record-type-identifiers)
6036 ;; A label can't start at a cpp directive. Check for
6037 ;; this, since c-forward-syntactic-ws would foul up on it.
6038 (unless (and c-opt-cpp-prefix (looking-at c-opt-cpp-prefix))
6039 (c-forward-syntactic-ws)
6040 (c-forward-label nil pte start))))))))))
6041
6042 ;; Check that the next nonsymbol token is ":", or that we're in one
6043 ;; of QT's "slots" declarations. Allow '(' for the sake of macro
6044 ;; arguments. FIXME: Should build this regexp from the language
6045 ;; constants.
6046 (when (c-syntactic-re-search-forward
6047 "[ \t[:?;{=*/%&|,<>!@+-]" limit t t) ; not at EOB
6048 (backward-char)
6049 (setq qt-symbol-idx
6050 (and (c-major-mode-is 'c++-mode)
6051 (string-match
6052 "\\(p\\(r\\(ivate\\|otected\\)\\|ublic\\)\\|more\\)\\>"
6053 (buffer-substring start (point)))))
6054 (c-forward-syntactic-ws limit)
6055 (when (or (looking-at ":\\([^:]\\|\\'\\)") ; A single colon.
6056 (and qt-symbol-idx
6057 (search-forward-regexp "\\=slots\\>" limit t)
6058 (progn (c-forward-syntactic-ws limit)
6059 (looking-at ":\\([^:]\\|\\'\\)")))) ; A single colon
6060 (forward-char) ; to after the colon.
6061 t)))
0386b551
AM
6062
6063 (save-restriction
6064 (narrow-to-region start (point))
6065
6066 ;; Check that `c-nonlabel-token-key' doesn't match anywhere.
6067 (catch 'check-label
6068 (goto-char start)
6069 (while (progn
6070 (when (looking-at c-nonlabel-token-key)
6071 (goto-char start)
6072 (throw 'check-label nil))
6073 (and (c-safe (c-forward-sexp)
6074 (c-forward-syntactic-ws)
6075 t)
6076 (not (eobp)))))
6077
6078 ;; Record the identifiers in the label for fontification, unless
6079 ;; it begins with `c-label-kwds' in which case the following
6080 ;; identifiers are part of a (constant) expression that
6081 ;; shouldn't be fontified.
6082 (when (and c-record-type-identifiers
6083 (progn (goto-char start)
6084 (not (looking-at c-label-kwds-regexp))))
6085 (while (c-syntactic-re-search-forward c-symbol-key nil t)
6086 (c-record-ref-id (cons (match-beginning 0)
6087 (match-end 0)))))
6088
6089 (c-put-c-type-property (1- (point-max)) 'c-decl-end)
6090 (goto-char (point-max))
6091 t)))
6092
6093 (t
6094 ;; Not a label.
6095 (goto-char start)
6096 nil))))
6097
6098(defun c-forward-objc-directive ()
6099 ;; Assuming the point is at the beginning of a token, try to move
6100 ;; forward to the end of the Objective-C directive that starts
6101 ;; there. Return t if a directive was fully recognized, otherwise
6102 ;; the point is moved as far as one could be successfully parsed and
6103 ;; nil is returned.
6104 ;;
6105 ;; This function records identifier ranges on
6106 ;; `c-record-type-identifiers' and `c-record-ref-identifiers' if
6107 ;; `c-record-type-identifiers' is non-nil.
6108 ;;
6109 ;; This function might do hidden buffer changes.
6110
6111 (let ((start (point))
6112 start-char
6113 (c-promote-possible-types t)
6114 ;; Turn off recognition of angle bracket arglists while parsing
6115 ;; types here since the protocol reference list might then be
6116 ;; considered part of the preceding name or superclass-name.
6117 c-recognize-<>-arglists)
6118
6119 (if (or
6120 (when (looking-at
6121 (eval-when-compile
6122 (c-make-keywords-re t
6123 (append (c-lang-const c-protection-kwds objc)
6124 '("@end"))
6125 'objc-mode)))
6126 (goto-char (match-end 1))
6127 t)
6128
6129 (and
6130 (looking-at
6131 (eval-when-compile
6132 (c-make-keywords-re t
6133 '("@interface" "@implementation" "@protocol")
6134 'objc-mode)))
6135
6136 ;; Handle the name of the class itself.
6137 (progn
cb694ab7
AM
6138; (c-forward-token-2) ; 2006/1/13 This doesn't move if the token's
6139; at EOB.
6140 (goto-char (match-end 0))
6141 (c-skip-ws-forward)
0386b551
AM
6142 (c-forward-type))
6143
6144 (catch 'break
6145 ;; Look for ": superclass-name" or "( category-name )".
6146 (when (looking-at "[:\(]")
6147 (setq start-char (char-after))
6148 (forward-char)
6149 (c-forward-syntactic-ws)
6150 (unless (c-forward-type) (throw 'break nil))
6151 (when (eq start-char ?\()
6152 (unless (eq (char-after) ?\)) (throw 'break nil))
6153 (forward-char)
6154 (c-forward-syntactic-ws)))
6155
6156 ;; Look for a protocol reference list.
6157 (if (eq (char-after) ?<)
6158 (let ((c-recognize-<>-arglists t)
6159 (c-parse-and-markup-<>-arglists t)
6160 c-restricted-<>-arglists)
6161 (c-forward-<>-arglist t))
6162 t))))
6163
6164 (progn
6165 (c-backward-syntactic-ws)
6166 (c-clear-c-type-property start (1- (point)) 'c-decl-end)
6167 (c-put-c-type-property (1- (point)) 'c-decl-end)
6168 t)
6169
6170 (c-clear-c-type-property start (point) 'c-decl-end)
6171 nil)))
6172
785eecbb
RS
6173(defun c-beginning-of-inheritance-list (&optional lim)
6174 ;; Go to the first non-whitespace after the colon that starts a
6175 ;; multiple inheritance introduction. Optional LIM is the farthest
6176 ;; back we should search.
0386b551
AM
6177 ;;
6178 ;; This function might do hidden buffer changes.
6179 (c-with-syntax-table c++-template-syntax-table
6180 (c-backward-token-2 0 t lim)
6181 (while (and (or (looking-at c-symbol-start)
6182 (looking-at "[<,]\\|::"))
6183 (zerop (c-backward-token-2 1 t lim))))))
785eecbb 6184
785eecbb
RS
6185(defun c-in-method-def-p ()
6186 ;; Return nil if we aren't in a method definition, otherwise the
6187 ;; position of the initial [+-].
0386b551
AM
6188 ;;
6189 ;; This function might do hidden buffer changes.
785eecbb
RS
6190 (save-excursion
6191 (beginning-of-line)
a66cd3ee
MS
6192 (and c-opt-method-key
6193 (looking-at c-opt-method-key)
785eecbb
RS
6194 (point))
6195 ))
6196
a66cd3ee
MS
6197;; Contributed by Kevin Ryde <user42@zip.com.au>.
6198(defun c-in-gcc-asm-p ()
6199 ;; Return non-nil if point is within a gcc \"asm\" block.
6200 ;;
6201 ;; This should be called with point inside an argument list.
6202 ;;
6203 ;; Only one level of enclosing parentheses is considered, so for
6204 ;; instance `nil' is returned when in a function call within an asm
6205 ;; operand.
0386b551
AM
6206 ;;
6207 ;; This function might do hidden buffer changes.
a66cd3ee
MS
6208
6209 (and c-opt-asm-stmt-key
6210 (save-excursion
6211 (beginning-of-line)
6212 (backward-up-list 1)
6213 (c-beginning-of-statement-1 (point-min) nil t)
6214 (looking-at c-opt-asm-stmt-key))))
6215
abb7e5cf
SM
6216(defun c-at-toplevel-p ()
6217 "Return a determination as to whether point is at the `top-level'.
6218Being at the top-level means that point is either outside any
d9e94c22
MS
6219enclosing block (such function definition), or only inside a class,
6220namespace or other block that contains another declaration level.
abb7e5cf
SM
6221
6222If point is not at the top-level (e.g. it is inside a method
6223definition), then nil is returned. Otherwise, if point is at a
6224top-level not enclosed within a class definition, t is returned.
6225Otherwise, a 2-vector is returned where the zeroth element is the
6226buffer position of the start of the class declaration, and the first
6227element is the buffer position of the enclosing class's opening
0386b551
AM
6228brace.
6229
6230Note that this function might do hidden buffer changes. See the
6231comment at the start of cc-engine.el for more info."
a66cd3ee
MS
6232 (let ((paren-state (c-parse-state)))
6233 (or (not (c-most-enclosing-brace paren-state))
6234 (c-search-uplist-for-classkey paren-state))))
6235
d9e94c22 6236(defun c-just-after-func-arglist-p (&optional lim)
0386b551
AM
6237 ;; Return non-nil if the point is in the region after the argument
6238 ;; list of a function and its opening brace (or semicolon in case it
6239 ;; got no body). If there are K&R style argument declarations in
6240 ;; that region, the point has to be inside the first one for this
6241 ;; function to recognize it.
a66cd3ee 6242 ;;
0386b551
AM
6243 ;; If successful, the point is moved to the first token after the
6244 ;; function header (see `c-forward-decl-or-cast-1' for details) and
6245 ;; the position of the opening paren of the function arglist is
6246 ;; returned.
6247 ;;
6248 ;; The point is clobbered if not successful.
6249 ;;
6250 ;; LIM is used as bound for backward buffer searches.
6251 ;;
6252 ;; This function might do hidden buffer changes.
6253
6254 (let ((beg (point)) end id-start)
6255 (and
6256 (eq (c-beginning-of-statement-1 lim) 'same)
6257
6258 (not (or (c-major-mode-is 'objc-mode)
6259 (c-forward-objc-directive)))
6260
6261 (setq id-start
6262 (car-safe (c-forward-decl-or-cast-1 (c-point 'bosws) nil nil)))
6263 (< id-start beg)
6264
6265 ;; There should not be a '=' or ',' between beg and the
6266 ;; start of the declaration since that means we were in the
6267 ;; "expression part" of the declaration.
6268 (or (> (point) beg)
6269 (not (looking-at "[=,]")))
6270
6271 (save-excursion
6272 ;; Check that there's an arglist paren in the
6273 ;; declaration.
6274 (goto-char id-start)
6275 (cond ((eq (char-after) ?\()
6276 ;; The declarator is a paren expression, so skip past it
6277 ;; so that we don't get stuck on that instead of the
6278 ;; function arglist.
6279 (c-forward-sexp))
51c9af45
AM
6280 ((and c-opt-op-identifier-prefix
6281 (looking-at c-opt-op-identifier-prefix))
0386b551
AM
6282 ;; Don't trip up on "operator ()".
6283 (c-forward-token-2 2 t)))
6284 (and (< (point) beg)
6285 (c-syntactic-re-search-forward "(" beg t t)
6286 (1- (point)))))))
785eecbb 6287
a66cd3ee
MS
6288(defun c-in-knr-argdecl (&optional lim)
6289 ;; Return the position of the first argument declaration if point is
6290 ;; inside a K&R style argument declaration list, nil otherwise.
6291 ;; `c-recognize-knr-p' is not checked. If LIM is non-nil, it's a
6292 ;; position that bounds the backward search for the argument list.
6293 ;;
9cf17ef1
AM
6294 ;; Point must be within a possible K&R region, e.g. just before a top-level
6295 ;; "{". It must be outside of parens and brackets. The test can return
6296 ;; false positives otherwise.
0386b551
AM
6297 ;;
6298 ;; This function might do hidden buffer changes.
d9e94c22 6299
a66cd3ee
MS
6300 (save-excursion
6301 (save-restriction
9cf17ef1
AM
6302 ;; If we're in a macro, our search range is restricted to it. Narrow to
6303 ;; the searchable range.
6304 (let* ((macro-start (c-query-macro-start))
6305 (lim (max (or lim (point-min)) (or macro-start (point-min))))
6306 before-lparen after-rparen)
6307 (narrow-to-region lim (c-point 'eol))
6308
6309 ;; Search backwards for the defun's argument list. We give up if we
6310 ;; encounter a "}" (end of a previous defun) or BOB.
6311 ;;
6312 ;; The criterion for a paren structure being the arg list is:
6313 ;; o - there is non-WS stuff after it but before any "{"; AND
6314 ;; o - the token after it isn't a ";" AND
6315 ;; o - it is preceded by either an identifier (the function name) or
6316 ;; a macro expansion like "DEFUN (...)"; AND
6317 ;; o - its content is a non-empty comma-separated list of identifiers
6318 ;; (an empty arg list won't have a knr region).
6319 ;;
6320 ;; The following snippet illustrates these rules:
6321 ;; int foo (bar, baz, yuk)
6322 ;; int bar [] ;
6323 ;; int (*baz) (my_type) ;
6324 ;; int (*) (void) (*yuk) (void) ;
6325 ;; {
6326
6327 (catch 'knr
6328 (while t ; go round one paren/bracket construct each time round.
10489fcb 6329 (c-syntactic-skip-backward "^)]}")
9cf17ef1
AM
6330 (cond ((eq (char-before) ?\))
6331 (setq after-rparen (point)))
10489fcb
AM
6332 ((eq (char-before) ?\])
6333 (setq after-rparen nil))
6334 (t ; either } (hit previous defun) or no more parens/brackets
6335 (throw 'knr nil)))
9cf17ef1
AM
6336
6337 (if after-rparen
6338 ;; We're inside a paren. Could it be our argument list....?
6339 (if
6340 (and
6341 (progn
6342 (goto-char after-rparen)
6343 (unless (c-go-list-backward) (throw 'knr nil)) ;
6344 ;; FIXME!!! What about macros between the parens? 2007/01/20
6345 (setq before-lparen (point)))
d9e94c22 6346
9cf17ef1
AM
6347 ;; It can't be the arg list if next token is ; or {
6348 (progn (goto-char after-rparen)
6349 (c-forward-syntactic-ws)
6350 (not (memq (char-after) '(?\; ?\{))))
d9e94c22 6351
9cf17ef1
AM
6352 ;; Is the thing preceding the list an identifier (the
6353 ;; function name), or a macro expansion?
6354 (progn
6355 (goto-char before-lparen)
6356 (eq (c-backward-token-2) 0)
6357 (or (c-on-identifier)
6358 (and (eq (char-after) ?\))
6359 (c-go-up-list-backward)
6360 (eq (c-backward-token-2) 0)
6361 (c-on-identifier))))
6362
6363 ;; Have we got a non-empty list of comma-separated
6364 ;; identifiers?
6365 (progn
6366 (goto-char before-lparen)
6367 (c-forward-token-2) ; to first token inside parens
6368 (and
6369 (c-on-identifier)
6370 (c-forward-token-2)
6371 (catch 'id-list
6372 (while (eq (char-after) ?\,)
6373 (c-forward-token-2)
6374 (unless (c-on-identifier) (throw 'id-list nil))
6375 (c-forward-token-2))
6376 (eq (char-after) ?\))))))
6377
6378 ;; ...Yes. We've identified the function's argument list.
6379 (throw 'knr
6380 (progn (goto-char after-rparen)
6381 (c-forward-syntactic-ws)
6382 (point)))
6383
6384 ;; ...No. The current parens aren't the function's arg list.
6385 (goto-char before-lparen))
6386
6387 (or (c-go-list-backward) ; backwards over [ .... ]
6388 (throw 'knr nil)))))))))
785eecbb
RS
6389
6390(defun c-skip-conditional ()
6391 ;; skip forward over conditional at point, including any predicate
6392 ;; statements in parentheses. No error checking is performed.
0386b551
AM
6393 ;;
6394 ;; This function might do hidden buffer changes.
0ec8351b
BW
6395 (c-forward-sexp (cond
6396 ;; else if()
a66cd3ee
MS
6397 ((looking-at (concat "\\<else"
6398 "\\([ \t\n]\\|\\\\\n\\)+"
6399 "if\\>\\([^_]\\|$\\)"))
6400 3)
0ec8351b 6401 ;; do, else, try, finally
a66cd3ee
MS
6402 ((looking-at (concat "\\<\\("
6403 "do\\|else\\|try\\|finally"
6404 "\\)\\>\\([^_]\\|$\\)"))
130c507e 6405 1)
ce8c7486 6406 ;; for, if, while, switch, catch, synchronized, foreach
0ec8351b 6407 (t 2))))
785eecbb 6408
a66cd3ee
MS
6409(defun c-after-conditional (&optional lim)
6410 ;; If looking at the token after a conditional then return the
6411 ;; position of its start, otherwise return nil.
0386b551
AM
6412 ;;
6413 ;; This function might do hidden buffer changes.
a66cd3ee 6414 (save-excursion
d9e94c22 6415 (and (zerop (c-backward-token-2 1 t lim))
a66cd3ee
MS
6416 (or (looking-at c-block-stmt-1-key)
6417 (and (eq (char-after) ?\()
d9e94c22 6418 (zerop (c-backward-token-2 1 t lim))
a66cd3ee
MS
6419 (looking-at c-block-stmt-2-key)))
6420 (point))))
6421
0386b551
AM
6422(defun c-after-special-operator-id (&optional lim)
6423 ;; If the point is after an operator identifier that isn't handled
6424 ;; like an ordinary symbol (i.e. like "operator =" in C++) then the
6425 ;; position of the start of that identifier is returned. nil is
6426 ;; returned otherwise. The point may be anywhere in the syntactic
6427 ;; whitespace after the last token of the operator identifier.
6428 ;;
6429 ;; This function might do hidden buffer changes.
6430 (save-excursion
6431 (and c-overloadable-operators-regexp
6432 (zerop (c-backward-token-2 1 nil lim))
6433 (looking-at c-overloadable-operators-regexp)
51c9af45 6434 (or (not c-opt-op-identifier-prefix)
0386b551
AM
6435 (and
6436 (zerop (c-backward-token-2 1 nil lim))
51c9af45 6437 (looking-at c-opt-op-identifier-prefix)))
0386b551
AM
6438 (point))))
6439
a66cd3ee
MS
6440(defsubst c-backward-to-block-anchor (&optional lim)
6441 ;; Assuming point is at a brace that opens a statement block of some
6442 ;; kind, move to the proper anchor point for that block. It might
6443 ;; need to be adjusted further by c-add-stmt-syntax, but the
6444 ;; position at return is suitable as start position for that
6445 ;; function.
0386b551
AM
6446 ;;
6447 ;; This function might do hidden buffer changes.
a66cd3ee
MS
6448 (unless (= (point) (c-point 'boi))
6449 (let ((start (c-after-conditional lim)))
6450 (if start
6451 (goto-char start)))))
6452
037558bf 6453(defsubst c-backward-to-decl-anchor (&optional lim)
a66cd3ee
MS
6454 ;; Assuming point is at a brace that opens the block of a top level
6455 ;; declaration of some kind, move to the proper anchor point for
6456 ;; that block.
0386b551
AM
6457 ;;
6458 ;; This function might do hidden buffer changes.
a66cd3ee 6459 (unless (= (point) (c-point 'boi))
037558bf 6460 (c-beginning-of-statement-1 lim)))
a66cd3ee 6461
ff959bab 6462(defun c-search-decl-header-end ()
a66cd3ee
MS
6463 ;; Search forward for the end of the "header" of the current
6464 ;; declaration. That's the position where the definition body
6465 ;; starts, or the first variable initializer, or the ending
6466 ;; semicolon. I.e. search forward for the closest following
6467 ;; (syntactically relevant) '{', '=' or ';' token. Point is left
6468 ;; _after_ the first found token, or at point-max if none is found.
0386b551
AM
6469 ;;
6470 ;; This function might do hidden buffer changes.
ff959bab
MS
6471
6472 (let ((base (point)))
6473 (if (c-major-mode-is 'c++-mode)
6474
6475 ;; In C++ we need to take special care to handle operator
6476 ;; tokens and those pesky template brackets.
6477 (while (and
6478 (c-syntactic-re-search-forward "[;{<=]" nil 'move t t)
6479 (or
6480 (c-end-of-current-token base)
6481 ;; Handle operator identifiers, i.e. ignore any
6482 ;; operator token preceded by "operator".
6483 (save-excursion
6484 (and (c-safe (c-backward-sexp) t)
51c9af45 6485 (looking-at c-opt-op-identifier-prefix)))
ff959bab
MS
6486 (and (eq (char-before) ?<)
6487 (c-with-syntax-table c++-template-syntax-table
6488 (if (c-safe (goto-char (c-up-list-forward (point))))
6489 t
6490 (goto-char (point-max))
6491 nil)))))
6492 (setq base (point)))
6493
6494 (while (and
6495 (c-syntactic-re-search-forward "[;{=]" nil 'move t t)
6496 (c-end-of-current-token base))
6497 (setq base (point))))))
a66cd3ee
MS
6498
6499(defun c-beginning-of-decl-1 (&optional lim)
6500 ;; Go to the beginning of the current declaration, or the beginning
6501 ;; of the previous one if already at the start of it. Point won't
0386b551 6502 ;; be moved out of any surrounding paren. Return a cons cell of the
a66cd3ee
MS
6503 ;; form (MOVE . KNR-POS). MOVE is like the return value from
6504 ;; `c-beginning-of-statement-1'. If point skipped over some K&R
6505 ;; style argument declarations (and they are to be recognized) then
6506 ;; KNR-POS is set to the start of the first such argument
6507 ;; declaration, otherwise KNR-POS is nil. If LIM is non-nil, it's a
6508 ;; position that bounds the backward search.
6509 ;;
6510 ;; NB: Cases where the declaration continues after the block, as in
6511 ;; "struct foo { ... } bar;", are currently recognized as two
6512 ;; declarations, e.g. "struct foo { ... }" and "bar;" in this case.
0386b551
AM
6513 ;;
6514 ;; This function might do hidden buffer changes.
a66cd3ee
MS
6515 (catch 'return
6516 (let* ((start (point))
d9e94c22 6517 (last-stmt-start (point))
0386b551 6518 (move (c-beginning-of-statement-1 lim nil t)))
a66cd3ee 6519
a66cd3ee
MS
6520 ;; `c-beginning-of-statement-1' stops at a block start, but we
6521 ;; want to continue if the block doesn't begin a top level
2a15eb73
MS
6522 ;; construct, i.e. if it isn't preceded by ';', '}', ':', bob,
6523 ;; or an open paren.
d9e94c22 6524 (let ((beg (point)) tentative-move)
51c9af45
AM
6525 ;; Go back one "statement" each time round the loop until we're just
6526 ;; after a ;, }, or :, or at BOB or the start of a macro or start of
6527 ;; an ObjC method. This will move over a multiple declaration whose
6528 ;; components are comma separated.
d9e94c22
MS
6529 (while (and
6530 ;; Must check with c-opt-method-key in ObjC mode.
6531 (not (and c-opt-method-key
6532 (looking-at c-opt-method-key)))
6533 (/= last-stmt-start (point))
6534 (progn
6535 (c-backward-syntactic-ws lim)
6536 (not (memq (char-before) '(?\; ?} ?: nil))))
2a15eb73
MS
6537 (save-excursion
6538 (backward-char)
6539 (not (looking-at "\\s(")))
d9e94c22
MS
6540 ;; Check that we don't move from the first thing in a
6541 ;; macro to its header.
6542 (not (eq (setq tentative-move
0386b551 6543 (c-beginning-of-statement-1 lim nil t))
d9e94c22
MS
6544 'macro)))
6545 (setq last-stmt-start beg
6546 beg (point)
6547 move tentative-move))
6548 (goto-char beg))
6549
6550 (when c-recognize-knr-p
6551 (let ((fallback-pos (point)) knr-argdecl-start)
6552 ;; Handle K&R argdecls. Back up after the "statement" jumped
6553 ;; over by `c-beginning-of-statement-1', unless it was the
6554 ;; function body, in which case we're sitting on the opening
6555 ;; brace now. Then test if we're in a K&R argdecl region and
6556 ;; that we started at the other side of the first argdecl in
6557 ;; it.
6558 (unless (eq (char-after) ?{)
6559 (goto-char last-stmt-start))
6560 (if (and (setq knr-argdecl-start (c-in-knr-argdecl lim))
6561 (< knr-argdecl-start start)
6562 (progn
6563 (goto-char knr-argdecl-start)
0386b551 6564 (not (eq (c-beginning-of-statement-1 lim nil t) 'macro))))
d9e94c22
MS
6565 (throw 'return
6566 (cons (if (eq (char-after fallback-pos) ?{)
6567 'previous
6568 'same)
6569 knr-argdecl-start))
6570 (goto-char fallback-pos))))
6571
51c9af45
AM
6572 ;; `c-beginning-of-statement-1' counts each brace block as a separate
6573 ;; statement, so the result will be 'previous if we've moved over any.
6574 ;; So change our result back to 'same if necessary.
6575 ;;
6576 ;; If they were brace list initializers we might not have moved over a
6577 ;; declaration boundary though, so change it to 'same if we've moved
6578 ;; past a '=' before '{', but not ';'. (This ought to be integrated
6579 ;; into `c-beginning-of-statement-1', so we avoid this extra pass which
6580 ;; potentially can search over a large amount of text.). Take special
6581 ;; pains not to get mislead by C++'s "operator=", and the like.
d9e94c22
MS
6582 (if (and (eq move 'previous)
6583 (c-with-syntax-table (if (c-major-mode-is 'c++-mode)
6584 c++-template-syntax-table
6585 (syntax-table))
6586 (save-excursion
51c9af45
AM
6587 (and
6588 (progn
6589 (while ; keep going back to "[;={"s until we either find
6590 ; no more, or get to one which isn't an "operator ="
6591 (and (c-syntactic-re-search-forward "[;={]" start t t t)
6592 (eq (char-before) ?=)
6593 c-overloadable-operators-regexp
6594 c-opt-op-identifier-prefix
6595 (save-excursion
6596 (eq (c-backward-token-2) 0)
6597 (looking-at c-overloadable-operators-regexp)
6598 (eq (c-backward-token-2) 0)
6599 (looking-at c-opt-op-identifier-prefix))))
6600 (eq (char-before) ?=))
6601 (c-syntactic-re-search-forward "[;{]" start t t)
6602 (eq (char-before) ?{)
6603 (c-safe (goto-char (c-up-list-forward (point))) t)
6604 (not (c-syntactic-re-search-forward ";" start t t))))))
d9e94c22
MS
6605 (cons 'same nil)
6606 (cons move nil)))))
a66cd3ee
MS
6607
6608(defun c-end-of-decl-1 ()
6609 ;; Assuming point is at the start of a declaration (as detected by
6610 ;; e.g. `c-beginning-of-decl-1'), go to the end of it. Unlike
6611 ;; `c-beginning-of-decl-1', this function handles the case when a
6612 ;; block is followed by identifiers in e.g. struct declarations in C
6613 ;; or C++. If a proper end was found then t is returned, otherwise
6614 ;; point is moved as far as possible within the current sexp and nil
6615 ;; is returned. This function doesn't handle macros; use
6616 ;; `c-end-of-macro' instead in those cases.
0386b551
AM
6617 ;;
6618 ;; This function might do hidden buffer changes.
ce8c7486 6619 (let ((start (point))
a66cd3ee
MS
6620 (decl-syntax-table (if (c-major-mode-is 'c++-mode)
6621 c++-template-syntax-table
6622 (syntax-table))))
6623 (catch 'return
6624 (c-search-decl-header-end)
6625
6626 (when (and c-recognize-knr-p
6627 (eq (char-before) ?\;)
6628 (c-in-knr-argdecl start))
6629 ;; Stopped at the ';' in a K&R argdecl section which is
6630 ;; detected using the same criteria as in
6631 ;; `c-beginning-of-decl-1'. Move to the following block
6632 ;; start.
d9e94c22 6633 (c-syntactic-re-search-forward "{" nil 'move t))
a66cd3ee
MS
6634
6635 (when (eq (char-before) ?{)
6636 ;; Encountered a block in the declaration. Jump over it.
6637 (condition-case nil
6638 (goto-char (c-up-list-forward (point)))
d9e94c22
MS
6639 (error (goto-char (point-max))
6640 (throw 'return nil)))
a66cd3ee
MS
6641 (if (or (not c-opt-block-decls-with-vars-key)
6642 (save-excursion
6643 (c-with-syntax-table decl-syntax-table
6644 (let ((lim (point)))
6645 (goto-char start)
b3cf7e18
MS
6646 (not (and
6647 ;; Check for `c-opt-block-decls-with-vars-key'
6648 ;; before the first paren.
6649 (c-syntactic-re-search-forward
d9e94c22 6650 (concat "[;=\(\[{]\\|\\("
b3cf7e18
MS
6651 c-opt-block-decls-with-vars-key
6652 "\\)")
d9e94c22 6653 lim t t t)
b3cf7e18
MS
6654 (match-beginning 1)
6655 (not (eq (char-before) ?_))
d9e94c22
MS
6656 ;; Check that the first following paren is
6657 ;; the block.
6658 (c-syntactic-re-search-forward "[;=\(\[{]"
6659 lim t t t)
b3cf7e18 6660 (eq (char-before) ?{)))))))
a66cd3ee
MS
6661 ;; The declaration doesn't have any of the
6662 ;; `c-opt-block-decls-with-vars' keywords in the
6663 ;; beginning, so it ends here at the end of the block.
6664 (throw 'return t)))
6665
6666 (c-with-syntax-table decl-syntax-table
6667 (while (progn
6668 (if (eq (char-before) ?\;)
6669 (throw 'return t))
d9e94c22 6670 (c-syntactic-re-search-forward ";" nil 'move t))))
a66cd3ee 6671 nil)))
ce8c7486 6672
0386b551
AM
6673(defun c-looking-at-decl-block (containing-sexp goto-start &optional limit)
6674 ;; Assuming the point is at an open brace, check if it starts a
6675 ;; block that contains another declaration level, i.e. that isn't a
6676 ;; statement block or a brace list, and if so return non-nil.
6677 ;;
6678 ;; If the check is successful, the return value is the start of the
6679 ;; keyword that tells what kind of construct it is, i.e. typically
6680 ;; what `c-decl-block-key' matched. Also, if GOTO-START is set then
6681 ;; the point will be at the start of the construct, before any
6682 ;; leading specifiers, otherwise it's at the returned position.
6683 ;;
6684 ;; The point is clobbered if the check is unsuccessful.
6685 ;;
6686 ;; CONTAINING-SEXP is the position of the open of the surrounding
6687 ;; paren, or nil if none.
6688 ;;
6689 ;; The optional LIMIT limits the backward search for the start of
6690 ;; the construct. It's assumed to be at a syntactically relevant
6691 ;; position.
6692 ;;
6693 ;; If any template arglists are found in the searched region before
6694 ;; the open brace, they get marked with paren syntax.
6695 ;;
6696 ;; This function might do hidden buffer changes.
6697
6698 (let ((open-brace (point)) kwd-start first-specifier-pos)
6699 (c-syntactic-skip-backward c-block-prefix-charset limit t)
6700
6701 (when (and c-recognize-<>-arglists
6702 (eq (char-before) ?>))
6703 ;; Could be at the end of a template arglist.
6704 (let ((c-parse-and-markup-<>-arglists t)
6705 (c-disallow-comma-in-<>-arglists
6706 (and containing-sexp
6707 (not (eq (char-after containing-sexp) ?{)))))
6708 (while (and
6709 (c-backward-<>-arglist nil limit)
6710 (progn
6711 (c-syntactic-skip-backward c-block-prefix-charset limit t)
6712 (eq (char-before) ?>))))))
6713
6714 ;; Note: Can't get bogus hits inside template arglists below since they
6715 ;; have gotten paren syntax above.
6716 (when (and
6717 ;; If `goto-start' is set we begin by searching for the
6718 ;; first possible position of a leading specifier list.
6719 ;; The `c-decl-block-key' search continues from there since
6720 ;; we know it can't match earlier.
6721 (if goto-start
6722 (when (c-syntactic-re-search-forward c-symbol-start
6723 open-brace t t)
6724 (goto-char (setq first-specifier-pos (match-beginning 0)))
6725 t)
6726 t)
6727
6728 (cond
6729 ((c-syntactic-re-search-forward c-decl-block-key open-brace t t t)
6730 (goto-char (setq kwd-start (match-beginning 0)))
6731 (or
6732
6733 ;; Found a keyword that can't be a type?
6734 (match-beginning 1)
6735
6736 ;; Can be a type too, in which case it's the return type of a
6737 ;; function (under the assumption that no declaration level
6738 ;; block construct starts with a type).
6739 (not (c-forward-type))
6740
6741 ;; Jumped over a type, but it could be a declaration keyword
6742 ;; followed by the declared identifier that we've jumped over
6743 ;; instead (e.g. in "class Foo {"). If it indeed is a type
6744 ;; then we should be at the declarator now, so check for a
6745 ;; valid declarator start.
6746 ;;
6747 ;; Note: This doesn't cope with the case when a declared
6748 ;; identifier is followed by e.g. '(' in a language where '('
6749 ;; also might be part of a declarator expression. Currently
6750 ;; there's no such language.
6751 (not (or (looking-at c-symbol-start)
6752 (looking-at c-type-decl-prefix-key)))))
6753
6754 ;; In Pike a list of modifiers may be followed by a brace
6755 ;; to make them apply to many identifiers. Note that the
6756 ;; match data will be empty on return in this case.
6757 ((and (c-major-mode-is 'pike-mode)
6758 (progn
6759 (goto-char open-brace)
6760 (= (c-backward-token-2) 0))
6761 (looking-at c-specifier-key)
6762 ;; Use this variant to avoid yet another special regexp.
6763 (c-keyword-member (c-keyword-sym (match-string 1))
6764 'c-modifier-kwds))
6765 (setq kwd-start (point))
6766 t)))
6767
6768 ;; Got a match.
6769
6770 (if goto-start
6771 ;; Back up over any preceding specifiers and their clauses
6772 ;; by going forward from `first-specifier-pos', which is the
6773 ;; earliest possible position where the specifier list can
6774 ;; start.
6775 (progn
6776 (goto-char first-specifier-pos)
6777
6778 (while (< (point) kwd-start)
6779 (if (looking-at c-symbol-key)
6780 ;; Accept any plain symbol token on the ground that
6781 ;; it's a specifier masked through a macro (just
6782 ;; like `c-forward-decl-or-cast-1' skip forward over
6783 ;; such tokens).
6784 ;;
6785 ;; Could be more restrictive wrt invalid keywords,
6786 ;; but that'd only occur in invalid code so there's
6787 ;; no use spending effort on it.
6788 (let ((end (match-end 0)))
6789 (unless (c-forward-keyword-clause 0)
6790 (goto-char end)
6791 (c-forward-syntactic-ws)))
6792
6793 ;; Can't parse a declaration preamble and is still
6794 ;; before `kwd-start'. That means `first-specifier-pos'
6795 ;; was in some earlier construct. Search again.
6796 (if (c-syntactic-re-search-forward c-symbol-start
6797 kwd-start 'move t)
6798 (goto-char (setq first-specifier-pos (match-beginning 0)))
6799 ;; Got no preamble before the block declaration keyword.
6800 (setq first-specifier-pos kwd-start))))
6801
6802 (goto-char first-specifier-pos))
6803 (goto-char kwd-start))
6804
6805 kwd-start)))
ce8c7486 6806
a66cd3ee 6807(defun c-search-uplist-for-classkey (paren-state)
0386b551
AM
6808 ;; Check if the closest containing paren sexp is a declaration
6809 ;; block, returning a 2 element vector in that case. Aref 0
6810 ;; contains the bufpos at boi of the class key line, and aref 1
6811 ;; contains the bufpos of the open brace. This function is an
6812 ;; obsolete wrapper for `c-looking-at-decl-block'.
6813 ;;
6814 ;; This function might do hidden buffer changes.
6815 (let ((open-paren-pos (c-most-enclosing-brace paren-state)))
6816 (when open-paren-pos
6817 (save-excursion
6818 (goto-char open-paren-pos)
6819 (when (and (eq (char-after) ?{)
6820 (c-looking-at-decl-block
6821 (c-safe-position open-paren-pos paren-state)
6822 nil))
6823 (back-to-indentation)
6824 (vector (point) open-paren-pos))))))
785eecbb 6825
a66cd3ee 6826(defun c-inside-bracelist-p (containing-sexp paren-state)
785eecbb
RS
6827 ;; return the buffer position of the beginning of the brace list
6828 ;; statement if we're inside a brace list, otherwise return nil.
6829 ;; CONTAINING-SEXP is the buffer pos of the innermost containing
0386b551 6830 ;; paren. PAREN-STATE is the remainder of the state of enclosing
130c507e 6831 ;; braces
785eecbb
RS
6832 ;;
6833 ;; N.B.: This algorithm can potentially get confused by cpp macros
0386b551 6834 ;; placed in inconvenient locations. It's a trade-off we make for
785eecbb 6835 ;; speed.
0386b551
AM
6836 ;;
6837 ;; This function might do hidden buffer changes.
785eecbb 6838 (or
d9e94c22 6839 ;; This will pick up brace list declarations.
b2acd789
RS
6840 (c-safe
6841 (save-excursion
6842 (goto-char containing-sexp)
0ec8351b 6843 (c-forward-sexp -1)
b2acd789 6844 (let (bracepos)
d9e94c22 6845 (if (and (or (looking-at c-brace-list-key)
0ec8351b 6846 (progn (c-forward-sexp -1)
d9e94c22 6847 (looking-at c-brace-list-key)))
a66cd3ee 6848 (setq bracepos (c-down-list-forward (point)))
b2acd789
RS
6849 (not (c-crosses-statement-barrier-p (point)
6850 (- bracepos 2))))
6851 (point)))))
785eecbb
RS
6852 ;; this will pick up array/aggregate init lists, even if they are nested.
6853 (save-excursion
0ec8351b
BW
6854 (let ((class-key
6855 ;; Pike can have class definitions anywhere, so we must
6856 ;; check for the class key here.
6857 (and (c-major-mode-is 'pike-mode)
a66cd3ee
MS
6858 c-decl-block-key))
6859 bufpos braceassignp lim next-containing)
785eecbb
RS
6860 (while (and (not bufpos)
6861 containing-sexp)
a66cd3ee
MS
6862 (when paren-state
6863 (if (consp (car paren-state))
6864 (setq lim (cdr (car paren-state))
6865 paren-state (cdr paren-state))
6866 (setq lim (car paren-state)))
6867 (when paren-state
6868 (setq next-containing (car paren-state)
6869 paren-state (cdr paren-state))))
785eecbb 6870 (goto-char containing-sexp)
a66cd3ee
MS
6871 (if (c-looking-at-inexpr-block next-containing next-containing)
6872 ;; We're in an in-expression block of some kind. Do not
6873 ;; check nesting. We deliberately set the limit to the
6874 ;; containing sexp, so that c-looking-at-inexpr-block
6875 ;; doesn't check for an identifier before it.
0ec8351b
BW
6876 (setq containing-sexp nil)
6877 ;; see if the open brace is preceded by = or [...] in
6878 ;; this statement, but watch out for operator=
a66cd3ee 6879 (setq braceassignp 'dontknow)
d9e94c22 6880 (c-backward-token-2 1 t lim)
6393fef2 6881 ;; Checks to do only on the first sexp before the brace.
d9e94c22 6882 (when (and c-opt-inexpr-brace-list-key
6393fef2
RS
6883 (eq (char-after) ?\[))
6884 ;; In Java, an initialization brace list may follow
6885 ;; directly after "new Foo[]", so check for a "new"
6886 ;; earlier.
6887 (while (eq braceassignp 'dontknow)
6888 (setq braceassignp
d9e94c22
MS
6889 (cond ((/= (c-backward-token-2 1 t lim) 0) nil)
6890 ((looking-at c-opt-inexpr-brace-list-key) t)
6393fef2
RS
6891 ((looking-at "\\sw\\|\\s_\\|[.[]")
6892 ;; Carry on looking if this is an
6893 ;; identifier (may contain "." in Java)
6894 ;; or another "[]" sexp.
6895 'dontknow)
6896 (t nil)))))
6897 ;; Checks to do on all sexps before the brace, up to the
6898 ;; beginning of the statement.
6899 (while (eq braceassignp 'dontknow)
0ec8351b
BW
6900 (cond ((eq (char-after) ?\;)
6901 (setq braceassignp nil))
6902 ((and class-key
6903 (looking-at class-key))
6904 (setq braceassignp nil))
6905 ((eq (char-after) ?=)
6906 ;; We've seen a =, but must check earlier tokens so
6907 ;; that it isn't something that should be ignored.
6908 (setq braceassignp 'maybe)
6909 (while (and (eq braceassignp 'maybe)
d9e94c22 6910 (zerop (c-backward-token-2 1 t lim)))
0ec8351b
BW
6911 (setq braceassignp
6912 (cond
6913 ;; Check for operator =
51c9af45
AM
6914 ((and c-opt-op-identifier-prefix
6915 (looking-at c-opt-op-identifier-prefix))
0386b551 6916 nil)
130c507e
GM
6917 ;; Check for `<opchar>= in Pike.
6918 ((and (c-major-mode-is 'pike-mode)
6919 (or (eq (char-after) ?`)
6920 ;; Special case for Pikes
6921 ;; `[]=, since '[' is not in
6922 ;; the punctuation class.
6923 (and (eq (char-after) ?\[)
6924 (eq (char-before) ?`))))
6925 nil)
0ec8351b
BW
6926 ((looking-at "\\s.") 'maybe)
6927 ;; make sure we're not in a C++ template
6928 ;; argument assignment
a66cd3ee
MS
6929 ((and
6930 (c-major-mode-is 'c++-mode)
6931 (save-excursion
6932 (let ((here (point))
6933 (pos< (progn
6934 (skip-chars-backward "^<>")
6935 (point))))
6936 (and (eq (char-before) ?<)
6937 (not (c-crosses-statement-barrier-p
6938 pos< here))
6939 (not (c-in-literal))
6940 ))))
0ec8351b 6941 nil)
6393fef2
RS
6942 (t t))))))
6943 (if (and (eq braceassignp 'dontknow)
d9e94c22 6944 (/= (c-backward-token-2 1 t lim) 0))
6393fef2
RS
6945 (setq braceassignp nil)))
6946 (if (not braceassignp)
0ec8351b
BW
6947 (if (eq (char-after) ?\;)
6948 ;; Brace lists can't contain a semicolon, so we're done.
6949 (setq containing-sexp nil)
a66cd3ee
MS
6950 ;; Go up one level.
6951 (setq containing-sexp next-containing
6952 lim nil
6953 next-containing nil))
0ec8351b
BW
6954 ;; we've hit the beginning of the aggregate list
6955 (c-beginning-of-statement-1
a66cd3ee 6956 (c-most-enclosing-brace paren-state))
0ec8351b 6957 (setq bufpos (point))))
a66cd3ee 6958 )
785eecbb
RS
6959 bufpos))
6960 ))
6961
0ec8351b
BW
6962(defun c-looking-at-special-brace-list (&optional lim)
6963