1 |
;;; cc-engine.el --- core syntax guessing engine for CC mode |
;;; cc-engine.el --- core syntax guessing engine for CC mode |
2 |
|
|
3 |
;; Copyright (C) 1985,1987,1992-2001 Free Software Foundation, Inc. |
;; Copyright (C) 1985,1987,1992-2003 Free Software Foundation, Inc. |
4 |
|
|
5 |
;; Authors: 2000- Martin Stjernholm |
;; Authors: 1998- Martin Stjernholm |
6 |
;; 1998-1999 Barry A. Warsaw and Martin Stjernholm |
;; 1992-1999 Barry A. Warsaw |
|
;; 1992-1997 Barry A. Warsaw |
|
7 |
;; 1987 Dave Detlefs and Stewart Clamen |
;; 1987 Dave Detlefs and Stewart Clamen |
8 |
;; 1985 Richard M. Stallman |
;; 1985 Richard M. Stallman |
9 |
;; Maintainer: bug-cc-mode@gnu.org |
;; Maintainer: bug-cc-mode@gnu.org |
40 |
;; probably also applies to many other Emacs packages, but here it's |
;; probably also applies to many other Emacs packages, but here it's |
41 |
;; clearly spelled out.) |
;; clearly spelled out.) |
42 |
|
|
43 |
|
;; Hidden buffer changes |
44 |
|
;; |
45 |
|
;; Various functions in CC Mode use text properties for caching and |
46 |
|
;; syntactic markup purposes, and those of them that might modify such |
47 |
|
;; properties are said to do "hidden buffer changes". They should be |
48 |
|
;; used within `c-save-buffer-state' or a similar function that saves |
49 |
|
;; and restores buffer modifiedness etc. |
50 |
|
;; |
51 |
|
;; Interactive functions are assumed to not do hidden buffer changes |
52 |
|
;; (this isn't applicable in the specific parts of them that do real |
53 |
|
;; changes, though). |
54 |
|
;; |
55 |
|
;; All other functions are assumed to do hidden buffer changes and |
56 |
|
;; must thus be wrapped inside `c-save-buffer-state' if they're used |
57 |
|
;; from any function that does not do hidden buffer changes. |
58 |
|
;; |
59 |
|
;; Every function, except the interactive ones, that doesn't do hidden |
60 |
|
;; buffer changes have that explicitly stated in their docstring or |
61 |
|
;; comment. |
62 |
|
|
63 |
|
;; Use of text properties |
64 |
|
;; |
65 |
|
;; CC Mode uses several text properties internally to mark up various |
66 |
|
;; positions, e.g. to improve speed and to eliminate glitches in |
67 |
|
;; interactive refontification. |
68 |
|
;; |
69 |
|
;; 'syntax-table |
70 |
|
;; Used to modify the syntax of some characters. Currently used to |
71 |
|
;; mark the "<" and ">" of angle bracket parens with paren syntax. |
72 |
|
;; |
73 |
|
;; This property is used on single characters and is therefore |
74 |
|
;; always treated as front and rear nonsticky (or start and end open |
75 |
|
;; in XEmacs vocabulary). It's therefore installed on |
76 |
|
;; `text-property-default-nonsticky' if that variable exists (Emacs |
77 |
|
;; >= 21). |
78 |
|
;; |
79 |
|
;; 'c-is-sws and 'c-in-sws |
80 |
|
;; Used by `c-forward-syntactic-ws' and `c-backward-syntactic-ws' to |
81 |
|
;; speed them up. See the comment blurb before `c-put-is-sws' |
82 |
|
;; below for further details. |
83 |
|
;; |
84 |
|
;; 'c-type |
85 |
|
;; This property is used on single characters to mark positions with |
86 |
|
;; special syntactic relevance of various sorts. It's primary use |
87 |
|
;; is to avoid glitches when multiline constructs are refontified |
88 |
|
;; interactively (on font lock decoration level 3). It's cleared in |
89 |
|
;; a region before it's fontified and is then put on relevant chars |
90 |
|
;; in that region as they are encountered during the fontification. |
91 |
|
;; The value specifies the kind of position: |
92 |
|
;; |
93 |
|
;; 'c-decl-arg-start |
94 |
|
;; Put on the last char of the token preceding each declaration |
95 |
|
;; inside a declaration style arglist (typically in a function |
96 |
|
;; prototype). |
97 |
|
;; |
98 |
|
;; 'c-decl-end |
99 |
|
;; Put on the last char of the token preceding a declaration. |
100 |
|
;; This is used in cases where declaration boundaries can't be |
101 |
|
;; recognized simply by looking for a token like ";" or "}". |
102 |
|
;; `c-type-decl-end-used' must be set if this is used (see also |
103 |
|
;; `c-find-decl-spots'). |
104 |
|
;; |
105 |
|
;; 'c-<>-arg-sep |
106 |
|
;; Put on the commas that separate arguments in angle bracket |
107 |
|
;; arglists like C++ template arglists. |
108 |
|
;; |
109 |
|
;; 'c-decl-id-start and 'c-decl-type-start |
110 |
|
;; Put on the last char of the token preceding each declarator |
111 |
|
;; in the declarator list of a declaration. They are also used |
112 |
|
;; between the identifiers cases like enum declarations. |
113 |
|
;; 'c-decl-type-start is used when the declarators are types, |
114 |
|
;; 'c-decl-id-start otherwise. |
115 |
|
;; |
116 |
|
;; 'c-awk-NL-prop |
117 |
|
;; Used in AWK mode to mark the various kinds of newlines. See |
118 |
|
;; cc-awk.el. |
119 |
|
|
120 |
;;; Code: |
;;; Code: |
121 |
|
|
122 |
(eval-when-compile |
(eval-when-compile |
125 |
(stringp byte-compile-dest-file)) |
(stringp byte-compile-dest-file)) |
126 |
(cons (file-name-directory byte-compile-dest-file) load-path) |
(cons (file-name-directory byte-compile-dest-file) load-path) |
127 |
load-path))) |
load-path))) |
128 |
(require 'cc-bytecomp))) |
(load "cc-bytecomp" nil t))) |
129 |
|
|
130 |
(cc-require 'cc-defs) |
(cc-require 'cc-defs) |
131 |
|
(cc-require-when-compile 'cc-langs) |
132 |
(cc-require 'cc-vars) |
(cc-require 'cc-vars) |
133 |
(cc-require 'cc-langs) |
|
134 |
|
;; Some functions/constants in cc-awk.el that are called/referenced here. |
135 |
|
;; (Can't use cc-require due to cyclicity.) |
136 |
|
(cc-bytecomp-defun c-awk-unstick-NL-prop) |
137 |
|
(cc-bytecomp-defun c-awk-clear-NL-props) |
138 |
|
(cc-bytecomp-defvar awk-mode-syntax-table) |
139 |
|
(cc-bytecomp-defun c-awk-backward-syntactic-ws) |
140 |
|
(cc-bytecomp-defun c-awk-after-logical-semicolon) |
141 |
|
(cc-bytecomp-defun c-awk-NL-prop-not-set) |
142 |
|
(cc-bytecomp-defun c-awk-completed-stmt-ws-ends-line-p) |
143 |
|
(cc-bytecomp-defun c-awk-completed-stmt-ws-ends-prev-line-p) |
144 |
|
(cc-bytecomp-defun c-awk-prev-line-incomplete-p) |
145 |
|
(cc-bytecomp-defun c-awk-after-change) |
146 |
|
|
147 |
;; Silence the compiler. |
;; Silence the compiler. |
148 |
(cc-bytecomp-defun buffer-syntactic-context) ; XEmacs |
(cc-bytecomp-defun buffer-syntactic-context) ; XEmacs |
149 |
|
|
150 |
|
|
151 |
|
;; Make declarations for all the `c-lang-defvar' variables in cc-langs. |
152 |
|
|
153 |
|
(defmacro c-declare-lang-variables () |
154 |
|
`(progn |
155 |
|
,@(mapcan (lambda (init) |
156 |
|
`(,(if (elt init 2) |
157 |
|
`(defvar ,(car init) nil ,(elt init 2)) |
158 |
|
`(defvar ,(car init) nil)) |
159 |
|
(make-variable-buffer-local ',(car init)))) |
160 |
|
(cdr c-lang-variable-inits)))) |
161 |
|
(c-declare-lang-variables) |
162 |
|
|
163 |
|
|
164 |
|
;;; Internal state variables. |
165 |
|
|
166 |
|
;; Internal state of hungry delete key feature |
167 |
|
(defvar c-hungry-delete-key nil) |
168 |
|
(make-variable-buffer-local 'c-hungry-delete-key) |
169 |
|
|
170 |
|
;; Internal state of auto newline feature. |
171 |
|
(defvar c-auto-newline nil) |
172 |
|
(make-variable-buffer-local 'c-auto-newline) |
173 |
|
|
174 |
|
;; Internal auto-newline/hungry-delete designation string for mode line. |
175 |
|
(defvar c-auto-hungry-string nil) |
176 |
|
(make-variable-buffer-local 'c-auto-hungry-string) |
177 |
|
|
178 |
(defun c-calculate-state (arg prevstate) |
(defun c-calculate-state (arg prevstate) |
179 |
;; Calculate the new state of PREVSTATE, t or nil, based on arg. If |
;; Calculate the new state of PREVSTATE, t or nil, based on arg. If |
180 |
;; arg is nil or zero, toggle the state. If arg is negative, turn |
;; arg is nil or zero, toggle the state. If arg is negative, turn |
184 |
(not prevstate) |
(not prevstate) |
185 |
(> arg 0))) |
(> arg 0))) |
186 |
|
|
187 |
|
;; Dynamically bound cache for `c-in-literal'. |
188 |
(defvar c-in-literal-cache t) |
(defvar c-in-literal-cache t) |
189 |
|
|
190 |
|
;; Must be set in buffers where the `c-type' text property might be used |
191 |
|
;; with the value `c-decl-end'. |
192 |
|
(defvar c-type-decl-end-used nil) |
193 |
|
(make-variable-buffer-local 'c-type-decl-end-used) |
194 |
|
|
195 |
|
|
196 |
|
;;; Basic utility functions. |
197 |
|
|
198 |
|
(defun c-syntactic-content (from to) |
199 |
|
;; Return the given region as a string where all syntactic |
200 |
|
;; whitespace is removed or, where necessary, replaced with a single |
201 |
|
;; space. |
202 |
|
(save-excursion |
203 |
|
(goto-char from) |
204 |
|
(let* ((parts (list nil)) (tail parts) pos) |
205 |
|
(while (re-search-forward c-syntactic-ws-start to t) |
206 |
|
(goto-char (setq pos (match-beginning 0))) |
207 |
|
(c-forward-syntactic-ws to) |
208 |
|
(if (= (point) pos) |
209 |
|
(forward-char) |
210 |
|
(if (and (> pos from) |
211 |
|
(< (point) to) |
212 |
|
(looking-at "\\w\\|\\s_") |
213 |
|
(save-excursion |
214 |
|
(goto-char (1- pos)) |
215 |
|
(looking-at "\\w\\|\\s_"))) |
216 |
|
(progn |
217 |
|
(setcdr tail (list (buffer-substring-no-properties from pos) |
218 |
|
" ")) |
219 |
|
(setq tail (cddr tail))) |
220 |
|
(setcdr tail (list (buffer-substring-no-properties from pos))) |
221 |
|
(setq tail (cdr tail))) |
222 |
|
(setq from (point)))) |
223 |
|
(setcdr tail (list (buffer-substring-no-properties from to))) |
224 |
|
(apply 'concat (cdr parts))))) |
225 |
|
|
226 |
|
(defsubst c-keyword-sym (keyword) |
227 |
|
;; Return non-nil if the string KEYWORD is a known keyword. More |
228 |
|
;; precisely, the value is the symbol for the keyword in |
229 |
|
;; `c-keywords-obarray'. |
230 |
|
(intern-soft keyword c-keywords-obarray)) |
231 |
|
|
232 |
|
(defsubst c-keyword-member (keyword-sym lang-constant) |
233 |
|
;; Return non-nil if the symbol KEYWORD-SYM, as returned by |
234 |
|
;; `c-keyword-sym', is a member of LANG-CONSTANT, which is the name |
235 |
|
;; of a language constant that ends with "-kwds". If KEYWORD-SYM is |
236 |
|
;; nil then the result is nil. |
237 |
|
(get keyword-sym lang-constant)) |
238 |
|
|
239 |
|
;; String syntax chars, suitable for skip-syntax-(forward|backward). |
240 |
|
(defconst c-string-syntax (if (memq 'gen-string-delim c-emacs-features) |
241 |
|
"\"|" |
242 |
|
"\"")) |
243 |
|
|
244 |
|
;; Regexp matching string start syntax. |
245 |
|
(defconst c-string-limit-regexp (if (memq 'gen-string-delim c-emacs-features) |
246 |
|
"\\s\"\\|\\s|" |
247 |
|
"\\s\"")) |
248 |
|
|
249 |
|
;; Holds formatted error strings for the few cases where parse errors |
250 |
|
;; are reported. |
251 |
(defvar c-parsing-error nil) |
(defvar c-parsing-error nil) |
252 |
|
(make-variable-buffer-local 'c-parsing-error) |
253 |
|
|
254 |
|
(defun c-echo-parsing-error (&optional quiet) |
255 |
|
;; This function does not do any hidden buffer changes. |
256 |
|
(when (and c-report-syntactic-errors c-parsing-error (not quiet)) |
257 |
|
(c-benign-error "%s" c-parsing-error)) |
258 |
|
c-parsing-error) |
259 |
|
|
260 |
|
;; Faces given to comments and string literals. This is used in some |
261 |
|
;; situations to speed up recognition; it isn't mandatory that font |
262 |
|
;; locking is in use. This variable is extended with the face in |
263 |
|
;; `c-doc-face-name' when fontification is activated in cc-fonts.el. |
264 |
|
(defconst c-literal-faces |
265 |
|
'(font-lock-comment-face font-lock-string-face)) |
266 |
|
|
267 |
|
|
268 |
|
;; Some debug tools to visualize various special positions. This |
269 |
|
;; debug code isn't as portable as the rest of CC Mode. |
270 |
|
|
271 |
|
(cc-bytecomp-defun overlays-in) |
272 |
|
(cc-bytecomp-defun overlay-get) |
273 |
|
(cc-bytecomp-defun overlay-start) |
274 |
|
(cc-bytecomp-defun overlay-end) |
275 |
|
(cc-bytecomp-defun delete-overlay) |
276 |
|
(cc-bytecomp-defun overlay-put) |
277 |
|
(cc-bytecomp-defun make-overlay) |
278 |
|
|
279 |
|
(defun c-debug-add-face (beg end face) |
280 |
|
(c-save-buffer-state ((overlays (overlays-in beg end)) overlay) |
281 |
|
(while overlays |
282 |
|
(setq overlay (car overlays) |
283 |
|
overlays (cdr overlays)) |
284 |
|
(when (eq (overlay-get overlay 'face) face) |
285 |
|
(setq beg (min beg (overlay-start overlay)) |
286 |
|
end (max end (overlay-end overlay))) |
287 |
|
(delete-overlay overlay))) |
288 |
|
(overlay-put (make-overlay beg end) 'face face))) |
289 |
|
|
290 |
|
(defun c-debug-remove-face (beg end face) |
291 |
|
(c-save-buffer-state ((overlays (overlays-in beg end)) overlay |
292 |
|
(ol-beg beg) (ol-end end)) |
293 |
|
(while overlays |
294 |
|
(setq overlay (car overlays) |
295 |
|
overlays (cdr overlays)) |
296 |
|
(when (eq (overlay-get overlay 'face) face) |
297 |
|
(setq ol-beg (min ol-beg (overlay-start overlay)) |
298 |
|
ol-end (max ol-end (overlay-end overlay))) |
299 |
|
(delete-overlay overlay))) |
300 |
|
(when (< ol-beg beg) |
301 |
|
(overlay-put (make-overlay ol-beg beg) 'face face)) |
302 |
|
(when (> ol-end end) |
303 |
|
(overlay-put (make-overlay end ol-end) 'face face)))) |
304 |
|
|
305 |
|
|
306 |
|
;; `c-beginning-of-statement-1' and accompanying stuff. |
307 |
|
|
308 |
;; KLUDGE ALERT: c-maybe-labelp is used to pass information between |
;; KLUDGE ALERT: c-maybe-labelp is used to pass information between |
309 |
;; c-crosses-statement-barrier-p and c-beginning-of-statement-1. A |
;; c-crosses-statement-barrier-p and c-beginning-of-statement-1. A |
311 |
;; the byte compiler. |
;; the byte compiler. |
312 |
(defvar c-maybe-labelp nil) |
(defvar c-maybe-labelp nil) |
313 |
|
|
314 |
|
;; New awk-compatible version of c-beginning-of-statement-1, ACM 2002/6/22 |
315 |
|
|
316 |
;; Macros used internally in c-beginning-of-statement-1 for the |
;; Macros used internally in c-beginning-of-statement-1 for the |
317 |
;; automaton actions. |
;; automaton actions. |
318 |
(defmacro c-bos-push-state () |
(defmacro c-bos-push-state () |
358 |
statements/declarations on the same level are considered, i.e. don't |
statements/declarations on the same level are considered, i.e. don't |
359 |
move into or out of sexps (not even normal expression parentheses). |
move into or out of sexps (not even normal expression parentheses). |
360 |
|
|
361 |
Stop at statement continuations like \"else\", \"catch\", \"finally\" |
Stop at statement continuation tokens like \"else\", \"catch\", |
362 |
and the \"while\" in \"do ... while\" if the start point is within |
\"finally\" and the \"while\" in \"do ... while\" if the start point |
363 |
them. If starting at such a continuation, move to the corresponding |
is within the continuation. If starting at such a token, move to the |
364 |
statement start. If at the beginning of a statement, move to the |
corresponding statement start. If at the beginning of a statement, |
365 |
closest containing statement if there is any. This might also stop at |
move to the closest containing statement if there is any. This might |
366 |
a continuation clause. |
also stop at a continuation clause. |
367 |
|
|
368 |
Labels are treated as separate statements if IGNORE-LABELS is non-nil. |
Labels are treated as separate statements if IGNORE-LABELS is non-nil. |
369 |
The function is not overly intelligent in telling labels from other |
The function is not overly intelligent in telling labels from other |
394 |
Normally only ';' is considered to delimit statements, but if |
Normally only ';' is considered to delimit statements, but if |
395 |
COMMA-DELIM is non-nil then ',' is treated likewise." |
COMMA-DELIM is non-nil then ',' is treated likewise." |
396 |
|
|
397 |
;; The bulk of this function is a pushdown automaton that looks at |
;; The bulk of this function is a pushdown automaton that looks at statement |
398 |
;; statement boundaries and the tokens in c-opt-block-stmt-key. |
;; boundaries and the tokens (such as "while") in c-opt-block-stmt-key. Its |
399 |
|
;; purpose is to keep track of nested statements, ensuring that such |
400 |
|
;; statments are skipped over in their entirety (somewhat akin to what C-M-p |
401 |
|
;; does with nested braces/brackets/parentheses). |
402 |
;; |
;; |
403 |
;; Note: The position of a boundary is the following token. |
;; Note: The position of a boundary is the following token. |
404 |
;; |
;; |
405 |
;; Begin with current token, stop when stack is empty and the |
;; Beginning with the current token (the one following point), move back one |
406 |
;; position has been moved. |
;; sexp at a time (where a sexp is, more or less, either a token or the |
407 |
|
;; entire contents of a brace/bracket/paren pair). Each time a statement |
408 |
|
;; boundary is crossed or a "while"-like token is found, update the state of |
409 |
|
;; the PDA. Stop at the beginning of a statement when the stack (holding |
410 |
|
;; nested statement info) is empty and the position has been moved. |
411 |
|
;; |
412 |
|
;; The following variables constitute the PDA: |
413 |
|
;; |
414 |
|
;; sym: This is either the "while"-like token (e.g. 'for) we've just |
415 |
|
;; scanned back over, 'boundary if we've just gone back over a |
416 |
|
;; statement boundary, or nil otherwise. |
417 |
|
;; state: takes one of the values (nil else else-boundary while |
418 |
|
;; while-boundary catch catch-boundary). |
419 |
|
;; nil means "no "while"-like token yet scanned". |
420 |
|
;; 'else, for example, means "just gone back over an else". |
421 |
|
;; 'else-boundary means "just gone back over a statement boundary |
422 |
|
;; immediately after having gone back over an else". |
423 |
|
;; saved-pos: A vector of either saved positions (tok ptok pptok, etc.) or |
424 |
|
;; of error reporting information. |
425 |
|
;; stack: The stack onto which the PDA pushes its state. Each entry |
426 |
|
;; consists of a saved value of state and saved-pos. An entry is |
427 |
|
;; pushed when we move back over a "continuation" token (e.g. else) |
428 |
|
;; and popped when we encounter the corresponding opening token |
429 |
|
;; (e.g. if). |
430 |
|
;; |
431 |
|
;; |
432 |
|
;; The following diagram briefly outlines the PDA. |
433 |
;; |
;; |
434 |
;; Common state: |
;; Common state: |
435 |
;; "else": Push state, goto state `else': |
;; "else": Push state, goto state `else'. |
436 |
;; boundary: Goto state `else-boundary': |
;; "while": Push state, goto state `while'. |
437 |
;; "if": Pop state. |
;; "catch" or "finally": Push state, goto state `catch'. |
438 |
;; boundary: Error, pop state. |
;; boundary: Pop state. |
|
;; other: See common state. |
|
|
;; other: Error, pop state, retry token. |
|
|
;; "while": Push state, goto state `while': |
|
|
;; boundary: Save position, goto state `while-boundary': |
|
|
;; "do": Pop state. |
|
|
;; boundary: Restore position if it's not at start, pop state. |
|
|
;; other: See common state. |
|
|
;; other: Pop state, retry token. |
|
|
;; "catch" or "finally": Push state, goto state `catch': |
|
|
;; boundary: Goto state `catch-boundary': |
|
|
;; "try": Pop state. |
|
|
;; "catch": Goto state `catch'. |
|
|
;; boundary: Error, pop state. |
|
|
;; other: See common state. |
|
|
;; other: Error, pop state, retry token. |
|
439 |
;; other: Do nothing special. |
;; other: Do nothing special. |
440 |
;; |
;; |
441 |
|
;; State `else': |
442 |
|
;; boundary: Goto state `else-boundary'. |
443 |
|
;; other: Error, pop state, retry token. |
444 |
|
;; |
445 |
|
;; State `else-boundary': |
446 |
|
;; "if": Pop state. |
447 |
|
;; boundary: Error, pop state. |
448 |
|
;; other: See common state. |
449 |
|
;; |
450 |
|
;; State `while': |
451 |
|
;; boundary: Save position, goto state `while-boundary'. |
452 |
|
;; other: Pop state, retry token. |
453 |
|
;; |
454 |
|
;; State `while-boundary': |
455 |
|
;; "do": Pop state. |
456 |
|
;; boundary: Restore position if it's not at start, pop state. [*see below] |
457 |
|
;; other: See common state. |
458 |
|
;; |
459 |
|
;; State `catch': |
460 |
|
;; boundary: Goto state `catch-boundary'. |
461 |
|
;; other: Error, pop state, retry token. |
462 |
|
;; |
463 |
|
;; State `catch-boundary': |
464 |
|
;; "try": Pop state. |
465 |
|
;; "catch": Goto state `catch'. |
466 |
|
;; boundary: Error, pop state. |
467 |
|
;; other: See common state. |
468 |
|
;; |
469 |
|
;; [*] In the `while-boundary' state, we had pushed a 'while state, and were |
470 |
|
;; searching for a "do" which would have opened a do-while. If we didn't |
471 |
|
;; find it, we discard the analysis done since the "while", go back to this |
472 |
|
;; token in the buffer and restart the scanning there, this time WITHOUT |
473 |
|
;; pushing the 'while state onto the stack. |
474 |
|
;; |
475 |
;; In addition to the above there is some special handling of labels |
;; In addition to the above there is some special handling of labels |
476 |
;; and macros. |
;; and macros. |
477 |
|
|
483 |
c-stmt-delim-chars-with-comma |
c-stmt-delim-chars-with-comma |
484 |
c-stmt-delim-chars)) |
c-stmt-delim-chars)) |
485 |
pos ; Current position. |
pos ; Current position. |
486 |
boundary-pos ; Position of last boundary. |
boundary-pos ; Position of last stmt boundary character (e.g. ;). |
487 |
after-labels-pos ; Value of tok after first found colon. |
after-labels-pos ; Value of tok after first found colon. |
488 |
last-label-pos ; Value of tok after last found colon. |
last-label-pos ; Value of tok after last found colon. |
489 |
sym ; Current symbol in the alphabet. |
sym ; Symbol just scanned back over (e.g. 'while or |
490 |
state ; Current state in the automaton. |
; 'boundary). See above |
491 |
saved-pos ; Current saved positions. |
state ; Current state in the automaton. See above. |
492 |
|
saved-pos ; Current saved positions. See above |
493 |
stack ; Stack of conses (state . saved-pos). |
stack ; Stack of conses (state . saved-pos). |
494 |
(cond-key (or c-opt-block-stmt-key |
(cond-key (or c-opt-block-stmt-key ; regexp which matches "for", "if", etc. |
495 |
"\\<\\>")) ; Matches nothing. |
"\\<\\>")) ; Matches nothing. |
496 |
(ret 'same) |
(ret 'same) ; Return value. |
497 |
tok ptok pptok ; Pos of last three sexps or bounds. |
tok ptok pptok ; Pos of last three sexps or bounds. |
498 |
c-in-literal-cache c-maybe-labelp saved) |
c-in-literal-cache c-maybe-labelp saved) |
499 |
|
|
505 |
(/= (point) start))) |
(/= (point) start))) |
506 |
(setq macro-start (point))) |
(setq macro-start (point))) |
507 |
|
|
508 |
;; Try to skip over unary operator characters, to register |
;; Try to skip back over unary operator characters, to register |
509 |
;; that we've moved. |
;; that we've moved. |
510 |
(while (progn |
(while (progn |
511 |
(setq pos (point)) |
(setq pos (point)) |
512 |
(c-backward-syntactic-ws) |
(c-backward-syntactic-ws) ; might go back an awk-mode virtual semicolon, here. |
513 |
(/= (skip-chars-backward "-+!*&~@`#") 0))) |
; How about using c-awk-NL-prop for AWK Mode, here. |
514 |
|
; Something like c-awk-backward-syntactic-ws. |
515 |
;; First check for bare semicolon. Later on we ignore the |
; 2002/6/22. Doesn't matter! Leave it as it is. |
516 |
;; boundaries for statements that doesn't contain any sexp. |
(/= (skip-chars-backward "-+!*&~@`#") 0))) ; ACM, 2002/5/31; |
517 |
;; The only thing that is affected is that the error checking |
; Make a variable in |
518 |
;; is a little less strict, and we really don't bother. |
; cc-langs.el, maybe |
519 |
|
|
520 |
|
;; Skip back over any semicolon here. If it was a bare semicolon, we're |
521 |
|
;; done. Later on we ignore the boundaries for statements that doesn't |
522 |
|
;; contain any sexp. The only thing that is affected is that the error |
523 |
|
;; checking is a little less strict, and we really don't bother. |
524 |
(if (and (memq (char-before) delims) |
(if (and (memq (char-before) delims) |
525 |
(progn (forward-char -1) |
(progn (forward-char -1) |
526 |
(setq saved (point)) |
(setq saved (point)) |
527 |
(c-backward-syntactic-ws) |
(if (c-mode-is-new-awk-p) |
528 |
|
(c-awk-backward-syntactic-ws) |
529 |
|
(c-backward-syntactic-ws)) |
530 |
(or (memq (char-before) delims) |
(or (memq (char-before) delims) |
531 |
(memq (char-before) '(?: nil)) |
(memq (char-before) '(?: nil)) |
532 |
(eq (char-syntax (char-before)) ?\()))) |
(eq (char-syntax (char-before)) ?\() |
533 |
|
(and (c-mode-is-new-awk-p) |
534 |
|
(c-awk-after-logical-semicolon))))) ; ACM 2002/6/22 |
535 |
|
;; ACM, 2002/7/20: What about giving a limit to the above function? |
536 |
|
;; ACM, 2003/6/16: The above two lines (checking for |
537 |
|
;; awk-logical-semicolon) are probably redundant after rewriting |
538 |
|
;; c-awk-backward-syntactic-ws. |
539 |
(setq ret 'previous |
(setq ret 'previous |
540 |
pos saved) |
pos saved) |
541 |
|
|
546 |
;; Record this as the first token if not starting inside it. |
;; Record this as the first token if not starting inside it. |
547 |
(setq tok start)) |
(setq tok start)) |
548 |
|
|
549 |
|
;; The following while loop goes back one sexp (balanced parens, |
550 |
|
;; etc. with contents, or symbol or suchlike) each iteration. This |
551 |
|
;; movement is accomplished with a call to scan-sexps approx 130 lines |
552 |
|
;; below. |
553 |
(while |
(while |
554 |
(catch 'loop ;; Throw nil to break, non-nil to continue. |
(catch 'loop ;; Throw nil to break, non-nil to continue. |
555 |
(cond |
(cond |
556 |
;; Check for macro start. |
;; Check for macro start. Take this out for AWK Mode (ACM, 2002/5/31) |
557 |
|
;; NO!! just make sure macro-start is nil in AWK Mode (ACM, 2002/6/22) |
558 |
|
;; It always is (ACM, 2002/6/23) |
559 |
((save-excursion |
((save-excursion |
560 |
(and macro-start |
(and macro-start |
|
(looking-at "[ \t]*[a-zA-Z0-9!]") |
|
561 |
(progn (skip-chars-backward " \t") |
(progn (skip-chars-backward " \t") |
562 |
(eq (char-before) ?#)) |
(eq (char-before) ?#)) |
563 |
(progn (setq saved (1- (point))) |
(progn (setq saved (1- (point))) |
564 |
(beginning-of-line) |
(beginning-of-line) |
565 |
(not (eq (char-before (1- (point))) ?\\))) |
(not (eq (char-before (1- (point))) ?\\))) |
566 |
|
(looking-at c-opt-cpp-start) |
567 |
(progn (skip-chars-forward " \t") |
(progn (skip-chars-forward " \t") |
568 |
(eq (point) saved)))) |
(eq (point) saved)))) |
569 |
(goto-char saved) |
(goto-char saved) |
578 |
ignore-labels t)) |
ignore-labels t)) |
579 |
(throw 'loop nil)) |
(throw 'loop nil)) |
580 |
|
|
581 |
;; Do a round through the automaton if we found a |
;; Do a round through the automaton if we've just passed a |
582 |
;; boundary or if looking at a statement keyword. |
;; statement boundary or passed a "while"-like token. |
583 |
((or sym |
((or sym |
584 |
(and (looking-at cond-key) |
(and (looking-at cond-key) |
585 |
(setq sym (intern (match-string 1))))) |
(setq sym (intern (match-string 1))))) |
587 |
(when (and (< pos start) (null stack)) |
(when (and (< pos start) (null stack)) |
588 |
(throw 'loop nil)) |
(throw 'loop nil)) |
589 |
|
|
590 |
;; The state handling. Continue in the common state for |
;; The PDA state handling. |
591 |
;; unhandled cases. |
;; |
592 |
|
;; Refer to the description of the PDA in the openining |
593 |
|
;; comments. In the following OR form, the first leaf |
594 |
|
;; attempts to handles one of the specific actions detailed |
595 |
|
;; (e.g., finding token "if" whilst in state `else-boundary'). |
596 |
|
;; We drop through to the second leaf (which handles common |
597 |
|
;; state) if no specific handler is found in the first cond. |
598 |
|
;; If a parsing error is detected (e.g. an "else" with no |
599 |
|
;; preceding "if"), we throw to the enclosing catch. |
600 |
|
;; |
601 |
|
;; Note that the (eq state 'else) means |
602 |
|
;; "we've just passed an else", NOT "we're looking for an |
603 |
|
;; else". |
604 |
(or (cond |
(or (cond |
605 |
((eq state 'else) |
((eq state 'else) |
606 |
(if (eq sym 'boundary) |
(if (eq sym 'boundary) |
624 |
(not after-labels-pos)) |
(not after-labels-pos)) |
625 |
(progn (c-bos-save-pos) |
(progn (c-bos-save-pos) |
626 |
(setq state 'while-boundary)) |
(setq state 'while-boundary)) |
627 |
(c-bos-pop-state-and-retry))) |
(c-bos-pop-state-and-retry))) ; Can't be a do-while |
628 |
|
|
629 |
((eq state 'while-boundary) |
((eq state 'while-boundary) |
630 |
(cond ((eq sym 'do) |
(cond ((eq sym 'do) |
631 |
(c-bos-pop-state (setq ret 'beginning))) |
(c-bos-pop-state (setq ret 'beginning))) |
632 |
((eq sym 'boundary) |
((eq sym 'boundary) ; isn't a do-while |
633 |
(c-bos-restore-pos) |
(c-bos-restore-pos) ; the position of the while |
634 |
(c-bos-pop-state)))) |
(c-bos-pop-state)))) ; no longer searching for do. |
635 |
|
|
636 |
((eq state 'catch) |
((eq state 'catch) |
637 |
(if (eq sym 'boundary) |
(if (eq sym 'boundary) |
649 |
(c-bos-report-error) |
(c-bos-report-error) |
650 |
(c-bos-pop-state))))) |
(c-bos-pop-state))))) |
651 |
|
|
652 |
;; This is state common. |
;; This is state common. We get here when the previous |
653 |
|
;; cond statement found no particular state handler. |
654 |
(cond ((eq sym 'boundary) |
(cond ((eq sym 'boundary) |
655 |
(if (< pos start) |
;; If we have a boundary at the start |
656 |
(c-bos-pop-state) |
;; position we push a frame to go to the |
657 |
(c-bos-push-state))) |
;; previous statement. |
658 |
|
(if (>= pos start) |
659 |
|
(c-bos-push-state) |
660 |
|
(c-bos-pop-state))) |
661 |
((eq sym 'else) |
((eq sym 'else) |
662 |
(c-bos-push-state) |
(c-bos-push-state) |
663 |
(c-bos-save-error-info 'if 'else) |
(c-bos-save-error-info 'if 'else) |
664 |
(setq state 'else)) |
(setq state 'else)) |
665 |
((eq sym 'while) |
((eq sym 'while) |
666 |
(when (or (not pptok) |
(when (or (not pptok) |
667 |
(memq (char-after pptok) delims)) |
(memq (char-after pptok) delims) |
668 |
|
(and (c-mode-is-new-awk-p) |
669 |
|
(or |
670 |
|
;; might we be calling this from |
671 |
|
;; c-awk-after-if-do-for-while-condition-p? |
672 |
|
;; If so, avoid infinite recursion. |
673 |
|
(and (eq (point) start) |
674 |
|
(c-awk-NL-prop-not-set)) |
675 |
|
;; The following may recursively |
676 |
|
;; call this function. |
677 |
|
(c-awk-completed-stmt-ws-ends-line-p pptok)))) |
678 |
;; Since this can cause backtracking we do a |
;; Since this can cause backtracking we do a |
679 |
;; little more careful analysis to avoid it: If |
;; little more careful analysis to avoid it: If |
680 |
;; the while isn't followed by a semicolon it |
;; the while isn't followed by a semicolon it |
681 |
;; can't be a do-while. |
;; can't be a do-while. |
682 |
|
;; ACM, 2002/5/31; IT CAN IN AWK Mode. ;-( |
683 |
(c-bos-push-state) |
(c-bos-push-state) |
684 |
(setq state 'while))) |
(setq state 'while))) |
685 |
((memq sym '(catch finally)) |
((memq sym '(catch finally)) |
695 |
last-label-pos nil |
last-label-pos nil |
696 |
c-maybe-labelp nil)))) |
c-maybe-labelp nil)))) |
697 |
|
|
698 |
;; Step to next sexp, but not if we crossed a boundary, since |
;; Step to the previous sexp, but not if we crossed a |
699 |
;; that doesn't consume a sexp. |
;; boundary, since that doesn't consume an sexp. |
700 |
(if (eq sym 'boundary) |
(if (eq sym 'boundary) |
701 |
(setq ret 'previous) |
(setq ret 'previous) |
702 |
|
|
703 |
|
;; HERE IS THE SINGLE PLACE INSIDE THE PDA LOOP WHERE WE MOVE |
704 |
|
;; BACKWARDS THROUGH THE SOURCE. The following loop goes back |
705 |
|
;; one sexp and then only loops in special circumstances (line |
706 |
|
;; continuations and skipping past entire macros). |
707 |
(while |
(while |
708 |
(progn |
(progn |
709 |
(or (c-safe (goto-char (scan-sexps (point) -1)) t) |
(or (c-safe (goto-char (scan-sexps (point) -1)) t) |
710 |
|
;; Give up if we hit an unbalanced block. |
711 |
|
;; Since the stack won't be empty the code |
712 |
|
;; below will report a suitable error. |
713 |
(throw 'loop nil)) |
(throw 'loop nil)) |
714 |
(cond ((looking-at "\\\\$") |
(cond ((looking-at "\\\\$") |
715 |
;; Step again if we hit a line continuation. |
;; Step again if we hit a line continuation. |
718 |
;; If we started inside a macro then this |
;; If we started inside a macro then this |
719 |
;; sexp is always interesting. |
;; sexp is always interesting. |
720 |
nil) |
nil) |
721 |
(t |
((not (c-mode-is-new-awk-p)) ; Changed from t, ACM 2002/6/25 |
722 |
;; Otherwise check that we didn't step |
;; Otherwise check that we didn't step |
723 |
;; into a macro from the end. |
;; into a macro from the end. |
724 |
(let ((macro-start |
(let ((macro-start |
729 |
(goto-char macro-start) |
(goto-char macro-start) |
730 |
t)))))) |
t)))))) |
731 |
|
|
732 |
;; Check for statement boundary. |
;; Did the last movement by a sexp cross a statement boundary? |
733 |
(when (save-excursion |
(when (save-excursion |
734 |
(if (if (eq (char-after) ?{) |
(if (if (eq (char-after) ?{) |
735 |
(c-looking-at-inexpr-block lim nil) |
(c-looking-at-inexpr-block lim nil) |
736 |
(eq (char-syntax (char-after)) ?\()) |
(looking-at "\\s\(")) |
737 |
;; Need to move over parens and |
|
738 |
;; in-expression blocks to get a good start |
;; Should not include the paren sexp we've |
739 |
;; position for the boundary check. |
;; passed over in the boundary check. |
740 |
(c-forward-sexp 1)) |
(if (> (point) (- pos 100)) |
741 |
|
(c-forward-sexp 1) |
742 |
|
|
743 |
|
;; Find its end position this way instead of |
744 |
|
;; moving forward if the sexp is large. |
745 |
|
(goto-char pos) |
746 |
|
(while |
747 |
|
(progn |
748 |
|
(goto-char (1+ (c-down-list-backward))) |
749 |
|
(unless macro-start |
750 |
|
;; Check that we didn't step into |
751 |
|
;; a macro from the end. |
752 |
|
(let ((macro-start |
753 |
|
(save-excursion |
754 |
|
(and (c-beginning-of-macro) |
755 |
|
(point))))) |
756 |
|
(when macro-start |
757 |
|
(goto-char macro-start) |
758 |
|
t))))))) |
759 |
|
|
760 |
(setq boundary-pos (c-crosses-statement-barrier-p |
(setq boundary-pos (c-crosses-statement-barrier-p |
761 |
(point) pos))) |
(point) pos))) |
762 |
|
|
763 |
(setq pptok ptok |
(setq pptok ptok |
764 |
ptok tok |
ptok tok |
765 |
tok boundary-pos |
tok boundary-pos |
766 |
sym 'boundary) |
sym 'boundary) |
767 |
(throw 'loop t))) |
(throw 'loop t))) ; like a C "continue". Analyze the next sexp. |
768 |
|
|
769 |
(when (and (numberp c-maybe-labelp) (not ignore-labels)) |
(when (and (numberp c-maybe-labelp) (not ignore-labels)) |
770 |
;; c-crosses-statement-barrier-p has found a colon, so |
;; c-crosses-statement-barrier-p has found a colon, so |
781 |
ignore-labels t) ; Avoid the label check on exit. |
ignore-labels t) ; Avoid the label check on exit. |
782 |
(throw 'loop nil)) |
(throw 'loop nil)) |
783 |
|
|
784 |
|
;; We've moved back by a sexp, so update the token positions. |
785 |
(setq sym nil |
(setq sym nil |
786 |
pptok ptok |
pptok ptok |
787 |
ptok tok |
ptok tok |
788 |
tok (point) |
tok (point) |
789 |
pos tok))) ; Not nil. |
pos tok))) ; Not nil (for the while loop). |
790 |
|
|
791 |
;; If the stack isn't empty there might be errors to report. |
;; If the stack isn't empty there might be errors to report. |
792 |
(while stack |
(while stack |
805 |
(cond ((> start saved) (setq pos saved)) |
(cond ((> start saved) (setq pos saved)) |
806 |
((= start saved) (setq ret 'up))))) |
((= start saved) (setq ret 'up))))) |
807 |
|
|
808 |
(when (and c-maybe-labelp (not ignore-labels) after-labels-pos) |
(when (and c-maybe-labelp |
809 |
|
(not ignore-labels) |
810 |
|
(not (eq ret 'beginning)) |
811 |
|
after-labels-pos) |
812 |
;; We're in a label. Maybe we should step to the statement |
;; We're in a label. Maybe we should step to the statement |
813 |
;; after it. |
;; after it. |
814 |
(if (< after-labels-pos start) |
(if (< after-labels-pos start) |
821 |
(goto-char pos) |
(goto-char pos) |
822 |
(while (progn |
(while (progn |
823 |
(c-backward-syntactic-ws) |
(c-backward-syntactic-ws) |
824 |
(/= (skip-chars-backward "-+!*&~@`#") 0)) |
(/= (skip-chars-backward "-+!*&~@`#") 0)) ; Hopefully the # won't hurt awk. |
825 |
(setq pos (point))) |
(setq pos (point))) |
826 |
(goto-char pos) |
(goto-char pos) |
827 |
ret))) |
ret))) |
829 |
(defun c-crosses-statement-barrier-p (from to) |
(defun c-crosses-statement-barrier-p (from to) |
830 |
"Return non-nil if buffer positions FROM to TO cross one or more |
"Return non-nil if buffer positions FROM to TO cross one or more |
831 |
statement or declaration boundaries. The returned value is actually |
statement or declaration boundaries. The returned value is actually |
832 |
the position of the earliest boundary char. |
the position of the earliest boundary char. FROM must not be within |
833 |
|
a string or comment. |
834 |
|
|
835 |
The variable `c-maybe-labelp' is set to the position of the first `:' that |
The variable `c-maybe-labelp' is set to the position of the first `:' that |
836 |
might start a label (i.e. not part of `::' and not preceded by `?'). If a |
might start a label (i.e. not part of `::' and not preceded by `?'). If a |
842 |
(goto-char from) |
(goto-char from) |
843 |
(while (progn (skip-chars-forward skip-chars to) |
(while (progn (skip-chars-forward skip-chars to) |
844 |
(< (point) to)) |
(< (point) to)) |
845 |
(if (setq lit-range (c-literal-limits from)) |
(if (setq lit-range (c-literal-limits from)) ; Have we landed in a string/comment? |
846 |
(goto-char (setq from (cdr lit-range))) |
(progn (goto-char (setq from (cdr lit-range))) |
847 |
|
(if (and (c-mode-is-new-awk-p) (bolp)) ; ACM 2002/7/17. Make sure we |
848 |
|
(backward-char))) ; don't skip over a virtual semi-colon after an awk comment. :-( |
849 |
(cond ((eq (char-after) ?:) |
(cond ((eq (char-after) ?:) |
850 |
(forward-char) |
(forward-char) |
851 |
(if (and (eq (char-after) ?:) |
(if (and (eq (char-after) ?:) |
858 |
;; looking for more : and ?. |
;; looking for more : and ?. |
859 |
(setq c-maybe-labelp nil |
(setq c-maybe-labelp nil |
860 |
skip-chars (substring c-stmt-delim-chars 0 -2))) |
skip-chars (substring c-stmt-delim-chars 0 -2))) |
861 |
|
((and (eolp) ; Can only happen in AWK Mode |
862 |
|
(not (c-awk-completed-stmt-ws-ends-line-p))) |
863 |
|
(forward-char)) |
864 |
|
((and (c-mode-is-new-awk-p) |
865 |
|
(bolp) lit-range ; awk: comment/string ended prev line. |
866 |
|
(not (c-awk-completed-stmt-ws-ends-prev-line-p)))) |
867 |
(t (throw 'done (point)))))) |
(t (throw 'done (point)))))) |
868 |
nil)))) |
nil)))) |
869 |
|
|
870 |
|
|
871 |
|
;; A set of functions that covers various idiosyncrasies in |
872 |
|
;; implementations of `forward-comment'. |
873 |
|
|
874 |
|
;; Note: Some emacsen considers incorrectly that any line comment |
875 |
|
;; ending with a backslash continues to the next line. I can't think |
876 |
|
;; of any way to work around that in a reliable way without changing |
877 |
|
;; the buffer, though. Suggestions welcome. ;) (No, temporarily |
878 |
|
;; changing the syntax for backslash doesn't work since we must treat |
879 |
|
;; escapes in string literals correctly.) |
880 |
|
|
881 |
|
(defun c-forward-single-comment () |
882 |
|
"Move forward past whitespace and the closest following comment, if any. |
883 |
|
Return t if a comment was found, nil otherwise. In either case, the |
884 |
|
point is moved past the following whitespace. Line continuations, |
885 |
|
i.e. a backslashes followed by line breaks, are treated as whitespace. |
886 |
|
The line breaks that end line comments are considered to be the |
887 |
|
comment enders, so the point will be put on the beginning of the next |
888 |
|
line if it moved past a line comment. |
889 |
|
|
890 |
|
This function does not do any hidden buffer changes." |
891 |
|
|
892 |
|
(let ((start (point))) |
893 |
|
(when (looking-at "\\([ \t\n\r\f\v]\\|\\\\[\n\r]\\)+") |
894 |
|
(goto-char (match-end 0))) |
895 |
|
|
896 |
|
(when (forward-comment 1) |
897 |
|
(if (eobp) |
898 |
|
;; Some emacsen (e.g. XEmacs 21) return t when moving |
899 |
|
;; forwards at eob. |
900 |
|
nil |
901 |
|
|
902 |
|
;; Emacs includes the ending newline in a b-style (c++) |
903 |
|
;; comment, but XEmacs doesn't. We depend on the Emacs |
904 |
|
;; behavior (which also is symmetric). |
905 |
|
(if (and (eolp) (elt (parse-partial-sexp start (point)) 7)) |
906 |
|
(condition-case nil (forward-char 1))) |
907 |
|
|
908 |
|
t)))) |
909 |
|
|
910 |
|
(defsubst c-forward-comments () |
911 |
|
"Move forward past all following whitespace and comments. |
912 |
|
Line continuations, i.e. a backslashes followed by line breaks, are |
913 |
|
treated as whitespace. |
914 |
|
|
915 |
|
This function does not do any hidden buffer changes." |
916 |
|
|
917 |
|
(while (or |
918 |
|
;; If forward-comment in at least XEmacs 21 is given a large |
919 |
|
;; positive value, it'll loop all the way through if it hits |
920 |
|
;; eob. |
921 |
|
(and (forward-comment 5) |
922 |
|
;; Some emacsen (e.g. XEmacs 21) return t when moving |
923 |
|
;; forwards at eob. |
924 |
|
(not (eobp))) |
925 |
|
|
926 |
|
(when (looking-at "\\\\[\n\r]") |
927 |
|
(forward-char 2) |
928 |
|
t)))) |
929 |
|
|
930 |
|
(defun c-backward-single-comment () |
931 |
|
"Move backward past whitespace and the closest preceding comment, if any. |
932 |
|
Return t if a comment was found, nil otherwise. In either case, the |
933 |
|
point is moved past the preceding whitespace. Line continuations, |
934 |
|
i.e. a backslashes followed by line breaks, are treated as whitespace. |
935 |
|
The line breaks that end line comments are considered to be the |
936 |
|
comment enders, so the point cannot be at the end of the same line to |
937 |
|
move over a line comment. |
938 |
|
|
939 |
|
This function does not do any hidden buffer changes." |
940 |
|
|
941 |
|
(let ((start (point))) |
942 |
|
;; When we got newline terminated comments, forward-comment in all |
943 |
|
;; supported emacsen so far will stop at eol of each line not |
944 |
|
;; ending with a comment when moving backwards. This corrects for |
945 |
|
;; that, and at the same time handles line continuations. |
946 |
|
(while (progn |
947 |
|
(skip-chars-backward " \t\n\r\f\v") |
948 |
|
(and (looking-at "[\n\r]") |
949 |
|
(eq (char-before) ?\\) |
950 |
|
(< (point) start))) |
951 |
|
(backward-char)) |
952 |
|
|
953 |
|
(if (bobp) |
954 |
|
;; Some emacsen (e.g. Emacs 19.34) return t when moving |
955 |
|
;; backwards at bob. |
956 |
|
nil |
957 |
|
|
958 |
|
;; Leave point after the closest following newline if we've |
959 |
|
;; backed up over any above, since forward-comment won't move |
960 |
|
;; backward over a line comment if point is at the end of the |
961 |
|
;; same line. |
962 |
|
(re-search-forward "\\=\\s *[\n\r]" start t) |
963 |
|
|
964 |
|
(if (if (forward-comment -1) |
965 |
|
(if (eolp) |
966 |
|
;; If forward-comment above succeeded and we're at eol |
967 |
|
;; then the newline we moved over above didn't end a |
968 |
|
;; line comment, so we give it another go. |
969 |
|
(forward-comment -1) |
970 |
|
t)) |
971 |
|
|
972 |
|
;; Emacs <= 20 and XEmacs move back over the closer of a |
973 |
|
;; block comment that lacks an opener. |
974 |
|
(if (looking-at "\\*/") |
975 |
|
(progn (forward-char 2) nil) |
976 |
|
t))))) |
977 |
|
|
978 |
|
(defsubst c-backward-comments () |
979 |
|
"Move backward past all preceding whitespace and comments. |
980 |
|
Line continuations, i.e. a backslashes followed by line breaks, are |
981 |
|
treated as whitespace. The line breaks that end line comments are |
982 |
|
considered to be the comment enders, so the point cannot be at the end |
983 |
|
of the same line to move over a line comment. |
984 |
|
|
985 |
|
This function does not do any hidden buffer changes." |
986 |
|
|
987 |
|
(let ((start (point))) |
988 |
|
(while (and |
989 |
|
;; `forward-comment' in some emacsen (e.g. Emacs 19.34) |
990 |
|
;; return t when moving backwards at bob. |
991 |
|
(not (bobp)) |
992 |
|
|
993 |
|
(if (forward-comment -1) |
994 |
|
(if (looking-at "\\*/") |
995 |
|
;; Emacs <= 20 and XEmacs move back over the |
996 |
|
;; closer of a block comment that lacks an opener. |
997 |
|
(progn (forward-char 2) nil) |
998 |
|
t) |
999 |
|
|
1000 |
|
;; XEmacs treats line continuations as whitespace but |
1001 |
|
;; only in the backward direction, which seems a bit |
1002 |
|
;; odd. Anyway, this is necessary for Emacs. |
1003 |
|
(when (and (looking-at "[\n\r]") |
1004 |
|
(eq (char-before) ?\\) |
1005 |
|
(< (point) start)) |
1006 |
|
(backward-char) |
1007 |
|
t)))))) |
1008 |
|
|
1009 |
|
|
1010 |
|
;; Basic handling of preprocessor directives. |
1011 |
|
|
1012 |
;; This is a dynamically bound cache used together with |
;; This is a dynamically bound cache used together with |
1013 |
;; c-query-macro-start and c-query-and-set-macro-start. It only works |
;; `c-query-macro-start' and `c-query-and-set-macro-start'. It only |
1014 |
;; as long as point doesn't cross a macro boundary. |
;; works as long as point doesn't cross a macro boundary. |
1015 |
(defvar c-macro-start 'unknown) |
(defvar c-macro-start 'unknown) |
1016 |
|
|
1017 |
(defsubst c-query-and-set-macro-start () |
(defsubst c-query-and-set-macro-start () |
1018 |
|
;; This function does not do any hidden buffer changes. |
1019 |
(if (symbolp c-macro-start) |
(if (symbolp c-macro-start) |
1020 |
(setq c-macro-start (save-excursion |
(setq c-macro-start (save-excursion |
1021 |
(and (c-beginning-of-macro) |
(and (c-beginning-of-macro) |
1023 |
c-macro-start)) |
c-macro-start)) |
1024 |
|
|
1025 |
(defsubst c-query-macro-start () |
(defsubst c-query-macro-start () |
1026 |
|
;; This function does not do any hidden buffer changes. |
1027 |
(if (symbolp c-macro-start) |
(if (symbolp c-macro-start) |
1028 |
(save-excursion |
(save-excursion |
1029 |
(and (c-beginning-of-macro) |
(and (c-beginning-of-macro) |
1031 |
c-macro-start)) |
c-macro-start)) |
1032 |
|
|
1033 |
(defun c-beginning-of-macro (&optional lim) |
(defun c-beginning-of-macro (&optional lim) |
1034 |
"Go to the beginning of a cpp macro definition. |
"Go to the beginning of a preprocessor directive. |
1035 |
Leave point at the beginning of the macro and return t if in a cpp |
Leave point at the beginning of the directive and return t if in one, |
1036 |
macro definition, otherwise return nil and leave point unchanged." |
otherwise return nil and leave point unchanged. |
1037 |
(let ((here (point))) |
|
1038 |
(save-restriction |
This function does not do any hidden buffer changes." |
1039 |
(if lim (narrow-to-region lim (point-max))) |
(when c-opt-cpp-prefix |
1040 |
(beginning-of-line) |
(let ((here (point))) |
1041 |
(while (eq (char-before (1- (point))) ?\\) |
(save-restriction |
1042 |
(forward-line -1)) |
(if lim (narrow-to-region lim (point-max))) |
1043 |
(back-to-indentation) |
(beginning-of-line) |
1044 |
(if (and (<= (point) here) |
(while (eq (char-before (1- (point))) ?\\) |
1045 |
(looking-at "#[ \t]*[a-zA-Z0-9!]")) |
(forward-line -1)) |
1046 |
t |
(back-to-indentation) |
1047 |
(goto-char here) |
(if (and (<= (point) here) |
1048 |
nil)))) |
(looking-at c-opt-cpp-start)) |
1049 |
|
t |
1050 |
|
(goto-char here) |
1051 |
|
nil))))) |
1052 |
|
|
1053 |
(defun c-end-of-macro () |
(defun c-end-of-macro () |
1054 |
"Go to the end of a cpp macro definition. |
"Go to the end of a preprocessor directive. |
1055 |
More accurately, move point to the end of the closest following line |
More accurately, move point to the end of the closest following line |
1056 |
that doesn't end with a line continuation backslash." |
that doesn't end with a line continuation backslash. |
1057 |
|
|
1058 |
|
This function does not do any hidden buffer changes." |
1059 |
(while (progn |
(while (progn |
1060 |
(end-of-line) |
(end-of-line) |
1061 |
(when (and (eq (char-before) ?\\) |
(when (and (eq (char-before) ?\\) |
1063 |
(forward-char) |
(forward-char) |
1064 |
t)))) |
t)))) |
1065 |
|
|
1066 |
(defun c-forward-comment (count) |
(defun c-forward-to-cpp-define-body () |
1067 |
;; Insulation from various idiosyncrasies in implementations of |
;; Assuming point is at the "#" that introduces a preprocessor |
1068 |
;; `forward-comment'. |
;; directive, it's moved forward to the start of the definition body |
1069 |
;; |
;; if it's a "#define". Non-nil is returned in this case, in all |
1070 |
;; Note: Some emacsen considers incorrectly that any line comment |
;; other cases nil is returned and point isn't moved. |
1071 |
;; ending with a backslash continues to the next line. I can't |
(when (and (looking-at |
1072 |
;; think of any way to work around that in a reliable way without |
(concat "#[ \t]*" |
1073 |
;; changing the buffer, though. Suggestions welcome. ;) (No, |
"define[ \t]+\\(\\sw\\|_\\)+\\(\([^\)]*\)\\)?" |
1074 |
;; temporarily changing the syntax for backslash doesn't work since |
"\\([ \t]\\|\\\\\n\\)*")) |
1075 |
;; we must treat escapes in string literals correctly.) |
(not (= (match-end 0) (c-point 'eol)))) |
1076 |
;; |
(goto-char (match-end 0)))) |
|
;; Another note: When moving backwards over a block comment, there's |
|
|
;; a bug in forward-comment that can make it stop at "/*" inside a |
|
|
;; line comment. Haven't yet found a reasonably cheap way to kludge |
|
|
;; around that one either. :\ |
|
|
(let ((here (point))) |
|
|
(if (>= count 0) |
|
|
(when (forward-comment count) |
|
|
(if (eobp) |
|
|
;; Some emacsen (e.g. XEmacs 21) return t when moving |
|
|
;; forwards at eob. |
|
|
nil |
|
|
;; Emacs includes the ending newline in a b-style (c++) |
|
|
;; comment, but XEmacs doesn't. We depend on the Emacs |
|
|
;; behavior (which also is symmetric). |
|
|
(if (and (eolp) (nth 7 (parse-partial-sexp here (point)))) |
|
|
(condition-case nil (forward-char 1))) |
|
|
t)) |
|
|
;; When we got newline terminated comments, |
|
|
;; forward-comment in all supported emacsen so far will |
|
|
;; stop at eol of each line not ending with a comment when |
|
|
;; moving backwards. The following corrects for it when |
|
|
;; count is -1. The other common case, when count is |
|
|
;; large and negative, works regardless. It's too much |
|
|
;; work to correct for the rest of the cases. |
|
|
(skip-chars-backward " \t\n\r\f") |
|
|
(if (bobp) |
|
|
;; Some emacsen return t when moving backwards at bob. |
|
|
nil |
|
|
(re-search-forward "[\n\r]" here t) |
|
|
(let* ((res (if (forward-comment count) |
|
|
(if (eolp) (forward-comment -1) t))) |
|
|
(savepos (point))) |
|
|
;; XEmacs treats line continuations as whitespace (but only |
|
|
;; in the backward direction). |
|
|
(while (and (progn (end-of-line) (< (point) here)) |
|
|
(eq (char-before) ?\\)) |
|
|
(setq res nil |
|
|
savepos (point)) |
|
|
(forward-line)) |
|
|
(goto-char savepos) |
|
|
res))))) |
|
|
|
|
|
(defun c-forward-comment-lc (count) |
|
|
;; Like `c-forward-comment', but treat line continuations as |
|
|
;; whitespace. |
|
|
(catch 'done |
|
|
(if (> count 0) |
|
|
(while (if (c-forward-comment 1) |
|
|
(progn |
|
|
(setq count (1- count)) |
|
|
(> count 0)) |
|
|
(if (looking-at "\\\\$") |
|
|
(progn |
|
|
(forward-char) |
|
|
t) |
|
|
(throw 'done nil)))) |
|
|
(while (if (c-forward-comment -1) |
|
|
(progn |
|
|
(setq count (1+ count)) |
|
|
(< count 0)) |
|
|
(if (and (eolp) (eq (char-before) ?\\)) |
|
|
(progn |
|
|
(backward-char) |
|
|
t) |
|
|
(throw 'done nil))))) |
|
|
t)) |
|
1077 |
|
|
1078 |
(defun c-forward-syntactic-ws (&optional lim) |
|
1079 |
"Forward skip of syntactic whitespace. |
;; Tools for skipping over syntactic whitespace. |
|
Syntactic whitespace is defined as whitespace characters, comments, |
|
|
and preprocessor directives. However if point starts inside a comment |
|
|
or preprocessor directive, the content of it is not treated as |
|
|
whitespace. LIM sets an upper limit of the forward movement, if |
|
|
specified." |
|
|
(let ((here (point-max))) |
|
|
(or lim (setq lim here)) |
|
|
(while (/= here (point)) |
|
|
;; If forward-comment in at least XEmacs 21 is given a large |
|
|
;; positive value, it'll loop all the way through if it hits eob. |
|
|
(while (c-forward-comment 5)) |
|
|
(setq here (point)) |
|
|
(cond |
|
|
;; Skip line continuations. |
|
|
((looking-at "\\\\$") |
|
|
(forward-char)) |
|
|
;; Skip preprocessor directives. |
|
|
((and (looking-at "#[ \t]*[a-zA-Z0-9!]") |
|
|
(save-excursion |
|
|
(skip-chars-backward " \t") |
|
|
(bolp))) |
|
|
(end-of-line) |
|
|
(while (and (<= (point) lim) |
|
|
(eq (char-before) ?\\) |
|
|
(= (forward-line 1) 0)) |
|
|
(end-of-line)) |
|
|
(when (> (point) lim) |
|
|
;; Don't move past the macro if that'd take us past the limit. |
|
|
(goto-char here))) |
|
|
;; Skip in-comment line continuations (used for Pike refdoc). |
|
|
((and c-opt-in-comment-lc (looking-at c-opt-in-comment-lc)) |
|
|
(goto-char (match-end 0))))) |
|
|
(goto-char (min (point) lim)))) |
|
|
|
|
|
(defun c-backward-syntactic-ws (&optional lim) |
|
|
"Backward skip of syntactic whitespace. |
|
|
Syntactic whitespace is defined as whitespace characters, comments, |
|
|
and preprocessor directives. However if point starts inside a comment |
|
|
or preprocessor directive, the content of it is not treated as |
|
|
whitespace. LIM sets a lower limit of the backward movement, if |
|
|
specified." |
|
|
(let ((start-line (c-point 'bol)) |
|
|
(here (point-min)) |
|
|
(line-cont 'maybe) |
|
|
prev-pos) |
|
|
(or lim (setq lim here)) |
|
|
(while (/= here (point)) |
|
|
(setq prev-pos (point)) |
|
|
;; If forward-comment in Emacs 19.34 is given a large negative |
|
|
;; value, it'll loop all the way through if it hits bob. |
|
|
(while (c-forward-comment -5)) |
|
|
(setq here (point)) |
|
|
(cond |
|
|
((and (eolp) |
|
|
(eq (char-before) ?\\) |
|
|
(if (<= prev-pos (c-point 'eonl)) |
|
|
t |
|
|
;; Passed a line continuation, but not from the line we |
|
|
;; started on. |
|
|
(forward-char) |
|
|
(setq line-cont nil))) |
|
|
(backward-char) |
|
|
(setq line-cont t)) |
|
|
((progn |
|
|
(when (eq line-cont 'maybe) |
|
|
(save-excursion |
|
|
(end-of-line) |
|
|
(setq line-cont (eq (char-before) ?\\)))) |
|
|
(or line-cont |
|
|
(and (< (point) start-line) |
|
|
(c-beginning-of-macro)))) |
|
|
(if (< (point) lim) |
|
|
;; Don't move past the macro if we began inside it or at |
|
|
;; the end of the same line, or if the move would take us |
|
|
;; past the limit. |
|
|
(goto-char here)) |
|
|
(setq line-cont nil)) |
|
|
;; Skip in-comment line continuations (used for Pike refdoc). |
|
|
((and c-opt-in-comment-lc |
|
|
(save-excursion |
|
|
(and (c-safe (beginning-of-line) |
|
|
(backward-char 2) |
|
|
t) |
|
|
(looking-at c-opt-in-comment-lc) |
|
|
(eq (match-end 0) here)))) |
|
|
(goto-char (match-beginning 0))))) |
|
|
(goto-char (max (point) lim)))) |
|
1080 |
|
|
1081 |
(defun c-forward-token-1 (&optional count balanced lim) |
;; The following functions use text properties to cache searches over |
1082 |
"Move forward by tokens. |
;; large regions of syntactic whitespace. It works as follows: |
1083 |
A token is defined as all symbols and identifiers which aren't |
;; |
1084 |
syntactic whitespace \(note that e.g. \"->\" is considered to be two |
;; o If a syntactic whitespace region contains anything but simple |
1085 |
tokens). Point is always either left at the beginning of a token or |
;; whitespace (i.e. space, tab and line breaks), the text property |
1086 |
not moved at all. COUNT specifies the number of tokens to move; a |
;; `c-in-sws' is put over it. At places where we have stopped |
1087 |
negative COUNT moves in the opposite direction. A COUNT of 0 moves to |
;; within that region there's also a `c-is-sws' text property. |
1088 |
the next token beginning only if not already at one. If BALANCED is |
;; That since there typically are nested whitespace inside that |
1089 |
true, move over balanced parens, otherwise move into them. Also, if |
;; must be handled separately, e.g. whitespace inside a comment or |
1090 |
BALANCED is true, never move out of an enclosing paren. LIM sets the |
;; cpp directive. Thus, from one point with `c-is-sws' it's safe |
1091 |
limit for the movement and defaults to the point limit. |
;; to jump to another point with that property within the same |
1092 |
|
;; `c-in-sws' region. It can be likened to a ladder where |
1093 |
|
;; `c-in-sws' marks the bars and `c-is-sws' the rungs. |
1094 |
|
;; |
1095 |
|
;; o The `c-is-sws' property is put on the simple whitespace chars at |
1096 |
|
;; a "rung position" and also maybe on the first following char. |
1097 |
|
;; As many characters as can be conveniently found in this range |
1098 |
|
;; are marked, but no assumption can be made that the whole range |
1099 |
|
;; is marked (it could be clobbered by later changes, for |
1100 |
|
;; instance). |
1101 |
|
;; |
1102 |
|
;; Note that some part of the beginning of a sequence of simple |
1103 |
|
;; whitespace might be part of the end of a preceding line comment |
1104 |
|
;; or cpp directive and must not be considered part of the "rung". |
1105 |
|
;; Such whitespace is some amount of horizontal whitespace followed |
1106 |
|
;; by a newline. In the case of cpp directives it could also be |
1107 |
|
;; two newlines with horizontal whitespace between them. |
1108 |
|
;; |
1109 |
|
;; The reason to include the first following char is to cope with |
1110 |
|
;; "rung positions" that doesn't have any ordinary whitespace. If |
1111 |
|
;; `c-is-sws' is put on a token character it does not have |
1112 |
|
;; `c-in-sws' set simultaneously. That's the only case when that |
1113 |
|
;; can occur, and the reason for not extending the `c-in-sws' |
1114 |
|
;; region to cover it is that the `c-in-sws' region could then be |
1115 |
|
;; accidentally merged with a following one if the token is only |
1116 |
|
;; one character long. |
1117 |
|
;; |
1118 |
|
;; o On buffer changes the `c-in-sws' and `c-is-sws' properties are |
1119 |
|
;; removed in the changed region. If the change was inside |
1120 |
|
;; syntactic whitespace that means that the "ladder" is broken, but |
1121 |
|
;; a later call to `c-forward-sws' or `c-backward-sws' will use the |
1122 |
|
;; parts on either side and use an ordinary search only to "repair" |
1123 |
|
;; the gap. |
1124 |
|
;; |
1125 |
|
;; Special care needs to be taken if a region is removed: If there |
1126 |
|
;; are `c-in-sws' on both sides of it which do not connect inside |
1127 |
|
;; the region then they can't be joined. If e.g. a marked macro is |
1128 |
|
;; broken, syntactic whitespace inside the new text might be |
1129 |
|
;; marked. If those marks would become connected with the old |
1130 |
|
;; `c-in-sws' range around the macro then we could get a ladder |
1131 |
|
;; with one end outside the macro and the other at some whitespace |
1132 |
|
;; within it. |
1133 |
|
;; |
1134 |
|
;; The main motivation for this system is to increase the speed in |
1135 |
|
;; skipping over the large whitespace regions that can occur at the |
1136 |
|
;; top level in e.g. header files that contain a lot of comments and |
1137 |
|
;; cpp directives. For small comments inside code it's probably |
1138 |
|
;; slower than using `forward-comment' straightforwardly, but speed is |
1139 |
|
;; not a significant factor there anyway. |
1140 |
|
|
1141 |
|
; (defface c-debug-is-sws-face |
1142 |
|
; '((t (:background "GreenYellow"))) |
1143 |
|
; "Debug face to mark the `c-is-sws' property.") |
1144 |
|
; (defface c-debug-in-sws-face |
1145 |
|
; '((t (:underline t))) |
1146 |
|
; "Debug face to mark the `c-in-sws' property.") |
1147 |
|
|
1148 |
|
; (defun c-debug-put-sws-faces () |
1149 |
|
; ;; Put the sws debug faces on all the `c-is-sws' and `c-in-sws' |
1150 |
|
; ;; properties in the buffer. |
1151 |
|
; (interactive) |
1152 |
|
; (save-excursion |
1153 |
|
; (let (in-face) |
1154 |
|
; (goto-char (point-min)) |
1155 |
|
; (setq in-face (if (get-text-property (point) 'c-is-sws) |
1156 |
|
; (point))) |
1157 |
|
; (while (progn |
1158 |
|
; (goto-char (next-single-property-change |
1159 |
|
; (point) 'c-is-sws nil (point-max))) |
1160 |
|
; (if in-face |
1161 |
|
; (progn |
1162 |
|
; (c-debug-add-face in-face (point) 'c-debug-is-sws-face) |
1163 |
|
; (setq in-face nil)) |
1164 |
|
; (setq in-face (point))) |
1165 |
|
; (not (eobp)))) |
1166 |
|
; (goto-char (point-min)) |
1167 |
|
; (setq in-face (if (get-text-property (point) 'c-in-sws) |
1168 |
|
; (point))) |
1169 |
|
; (while (progn |
1170 |
|
; (goto-char (next-single-property-change |
1171 |
|
; (point) 'c-in-sws nil (point-max))) |
1172 |
|
; (if in-face |
1173 |
|
; (progn |
1174 |
|
; (c-debug-add-face in-face (point) 'c-debug-in-sws-face) |
1175 |
|
; (setq in-face nil)) |
1176 |
|
; (setq in-face (point))) |
1177 |
|
; (not (eobp))))))) |
1178 |
|
|
1179 |
|
(defmacro c-debug-sws-msg (&rest args) |
1180 |
|
;;`(message ,@args) |
1181 |
|
) |
1182 |
|
|
1183 |
|
(defmacro c-put-is-sws (beg end) |
1184 |
|
`(let ((beg ,beg) (end ,end)) |
1185 |
|
(put-text-property beg end 'c-is-sws t) |
1186 |
|
,@(when (facep 'c-debug-is-sws-face) |
1187 |
|
`((c-debug-add-face beg end 'c-debug-is-sws-face))))) |
1188 |
|
|
1189 |
|
(defmacro c-put-in-sws (beg end) |
1190 |
|
`(let ((beg ,beg) (end ,end)) |
1191 |
|
(put-text-property beg end 'c-in-sws t) |
1192 |
|
,@(when (facep 'c-debug-is-sws-face) |
1193 |
|
`((c-debug-add-face beg end 'c-debug-in-sws-face))))) |
1194 |
|
|
1195 |
|
(defmacro c-remove-is-sws (beg end) |
1196 |
|
`(let ((beg ,beg) (end ,end)) |
1197 |
|
(remove-text-properties beg end '(c-is-sws nil)) |
1198 |
|
,@(when (facep 'c-debug-is-sws-face) |
1199 |
|
`((c-debug-remove-face beg end 'c-debug-is-sws-face))))) |
1200 |
|
|
1201 |
|
(defmacro c-remove-in-sws (beg end) |
1202 |
|
`(let ((beg ,beg) (end ,end)) |
1203 |
|
(remove-text-properties beg end '(c-in-sws nil)) |
1204 |
|
,@(when (facep 'c-debug-is-sws-face) |
1205 |
|
`((c-debug-remove-face beg end 'c-debug-in-sws-face))))) |
1206 |
|
|
1207 |
|
(defmacro c-remove-is-and-in-sws (beg end) |
1208 |
|
`(let ((beg ,beg) (end ,end)) |
1209 |
|
(remove-text-properties beg end '(c-is-sws nil c-in-sws nil)) |
1210 |
|
,@(when (facep 'c-debug-is-sws-face) |
1211 |
|
`((c-debug-remove-face beg end 'c-debug-is-sws-face) |
1212 |
|
(c-debug-remove-face beg end 'c-debug-in-sws-face))))) |
1213 |
|
|
1214 |
|
(defsubst c-invalidate-sws-region-after (beg end) |
1215 |
|
;; Called from `after-change-functions'. Note that if |
1216 |
|
;; `c-forward-sws' or `c-backward-sws' are used outside |
1217 |
|
;; `c-save-buffer-state' or similar then this will remove the cache |
1218 |
|
;; properties right after they're added. |
1219 |
|
|
1220 |
Return the number of tokens left to move \(positive or negative). If |
(save-excursion |
1221 |
BALANCED is true, a move over a balanced paren counts as one. Note |
;; Adjust the end to remove the properties in any following simple |
1222 |
that if COUNT is 0 and no appropriate token beginning is found, 1 will |
;; ws up to and including the next line break, if there is any |
1223 |
be returned. Thus, a return value of 0 guarantees that point is at |
;; after the changed region. This is necessary e.g. when a rung |
1224 |
the requested position and a return value less \(without signs) than |
;; marked empty line is converted to a line comment by inserting |
1225 |
COUNT guarantees that point is at the beginning of some token." |
;; "//" before the line break. In that case the line break would |
1226 |
(or count (setq count 1)) |
;; keep the rung mark which could make a later `c-backward-sws' |
1227 |
(if (< count 0) |
;; move into the line comment instead of over it. |
1228 |
(- (c-backward-token-1 (- count) balanced lim)) |
(goto-char end) |
1229 |
(let ((jump-syntax (if balanced |
(skip-chars-forward " \t\f\v") |
1230 |
'(?w ?_ ?\( ?\) ?\" ?\\ ?/ ?$ ?') |
(when (and (eolp) (not (eobp))) |
1231 |
'(?w ?_ ?\" ?\\ ?/ ?'))) |
(setq end (1+ (point))))) |
1232 |
(last (point)) |
|
1233 |
(prev (point))) |
(when (and (= beg end) |
1234 |
(save-restriction |
(get-text-property beg 'c-in-sws) |
1235 |
(if lim (narrow-to-region (point-min) lim)) |
(not (bobp)) |
1236 |
(if (/= (point) |
(get-text-property (1- beg) 'c-in-sws)) |
1237 |
(progn (c-forward-syntactic-ws) (point))) |
;; Ensure that an `c-in-sws' range gets broken. Note that it isn't |
1238 |
;; Skip whitespace. Count this as a move if we did in fact |
;; safe to keep a range that was continuous before the change. E.g: |
1239 |
;; move and aren't out of bounds. |
;; |
1240 |
(or (eobp) |
;; #define foo |
1241 |
(setq count (max (1- count) 0)))) |
;; \ |
1242 |
(if (and (= count 0) |
;; bar |
1243 |
(or (and (memq (char-syntax (or (char-after) ? )) '(?w ?_)) |
;; |
1244 |
(memq (char-syntax (or (char-before) ? )) '(?w ?_))) |
;; There can be a "ladder" between "#" and "b". Now, if the newline |
1245 |
(eobp))) |
;; after "foo" is removed then "bar" will become part of the cpp |
1246 |
;; If count is zero we should jump if in the middle of a |
;; directive instead of a syntactically relevant token. In that |
1247 |
;; token or if there is whitespace between point and the |
;; case there's no longer syntactic ws from "#" to "b". |
1248 |
;; following token beginning. |
(setq beg (1- beg))) |
1249 |
(setq count 1)) |
|
1250 |
(if (eobp) |
(c-debug-sws-msg "c-invalidate-sws-region-after [%s..%s]" beg end) |
1251 |
(goto-char last) |
(c-remove-is-and-in-sws beg end)) |
1252 |
;; Avoid having the limit tests inside the loop. |
|
1253 |
(condition-case nil |
(defun c-forward-sws () |
1254 |
(while (> count 0) |
;; Used by `c-forward-syntactic-ws' to implement the unbounded search. |
1255 |
(setq prev last |
|
1256 |
last (point)) |
(let (;; `rung-pos' is set to a position as early as possible in the |
1257 |
(if (memq (char-syntax (char-after)) jump-syntax) |
;; unmarked part of the simple ws region. |
1258 |
(goto-char (scan-sexps (point) 1)) |
(rung-pos (point)) next-rung-pos rung-end-pos last-put-in-sws-pos |
1259 |
(forward-char)) |
rung-is-marked next-rung-is-marked simple-ws-end |
1260 |
(c-forward-syntactic-ws) |
;; `safe-start' is set when it's safe to cache the start position. |
1261 |
(setq count (1- count))) |
;; It's not set if we've initially skipped over comments and line |
1262 |
(error (goto-char last))) |
;; continuations since we might have gone out through the end of a |
1263 |
(when (eobp) |
;; macro then. This provision makes `c-forward-sws' not populate the |
1264 |
(goto-char prev) |
;; cache in the majority of cases, but otoh is `c-backward-sws' by far |
1265 |
(setq count (1+ count))))) |
;; more common. |
1266 |
count))) |
safe-start) |
1267 |
|
|
1268 |
|
;; Skip simple ws and do a quick check on the following character to see |
1269 |
|
;; if it's anything that can't start syntactic ws, so we can bail out |
1270 |
|
;; early in the majority of cases when there just are a few ws chars. |
1271 |
|
(skip-chars-forward " \t\n\r\f\v") |
1272 |
|
(when (looking-at c-syntactic-ws-start) |
1273 |
|
|
1274 |
|
(setq rung-end-pos (min (1+ (point)) (point-max))) |
1275 |
|
(if (setq rung-is-marked (text-property-any rung-pos rung-end-pos |
1276 |
|
'c-is-sws t)) |
1277 |
|
;; Find the last rung position to avoid setting properties in all |
1278 |
|
;; the cases when the marked rung is complete. |
1279 |
|
;; (`next-single-property-change' is certain to move at least one |
1280 |
|
;; step forward.) |
1281 |
|
(setq rung-pos (1- (next-single-property-change |
1282 |
|
rung-is-marked 'c-is-sws nil rung-end-pos))) |
1283 |
|
;; Got no marked rung here. Since the simple ws might have started |
1284 |
|
;; inside a line comment or cpp directive we must set `rung-pos' as |
1285 |
|
;; high as possible. |
1286 |
|
(setq rung-pos (point))) |
1287 |
|
|
1288 |
(defun c-backward-token-1 (&optional count balanced lim) |
(while |
1289 |
"Move backward by tokens. |
(progn |
1290 |
See `c-forward-token-1' for details." |
(while |
1291 |
(or count (setq count 1)) |
(when (and rung-is-marked |
1292 |
(if (< count 0) |
(get-text-property (point) 'c-in-sws)) |
1293 |
(- (c-forward-token-1 (- count) balanced lim)) |
|
1294 |
(let ((jump-syntax (if balanced |
;; The following search is the main reason that `c-in-sws' |
1295 |
'(?w ?_ ?\( ?\) ?\" ?\\ ?/ ?$ ?') |
;; and `c-is-sws' aren't combined to one property. |
1296 |
'(?w ?_ ?\" ?\\ ?/ ?'))) |
(goto-char (next-single-property-change |
1297 |
last) |
(point) 'c-in-sws nil (point-max))) |
1298 |
(if (and (= count 0) |
(unless (get-text-property (point) 'c-is-sws) |
1299 |
(or (and (memq (char-syntax (or (char-after) ? )) '(?w ?_)) |
;; If the `c-in-sws' region extended past the last |
1300 |
(memq (char-syntax (or (char-before) ? )) '(?w ?_))) |
;; `c-is-sws' char we have to go back a bit. |
1301 |
(/= (point) |
(or (get-text-property (1- (point)) 'c-is-sws) |
1302 |
(save-excursion |
(goto-char (previous-single-property-change |
1303 |
(c-forward-syntactic-ws (1+ lim)) |
(point) 'c-is-sws))) |
1304 |
(point))) |
(backward-char)) |
1305 |
(eobp))) |
|
1306 |
;; If count is zero we should jump if in the middle of a |
(c-debug-sws-msg |
1307 |
;; token or if there is whitespace between point and the |
"c-forward-sws cached move %s -> %s (max %s)" |
1308 |
;; following token beginning. |
rung-pos (point) (point-max)) |
1309 |
(setq count 1)) |
|
1310 |
(save-restriction |
(setq rung-pos (point)) |
1311 |
(if lim (narrow-to-region lim (point-max))) |
(and (> (skip-chars-forward " \t\n\r\f\v") 0) |
1312 |
(or (bobp) |
(not (eobp)))) |
1313 |
(progn |
|
1314 |
;; Avoid having the limit tests inside the loop. |
;; We'll loop here if there is simple ws after the last rung. |
1315 |
(condition-case nil |
;; That means that there's been some change in it and it's |
1316 |
(while (progn |
;; possible that we've stepped into another ladder, so extend |
1317 |
(setq last (point)) |
;; the previous one to join with it if there is one, and try to |
1318 |
(> count 0)) |
;; use the cache again. |
1319 |
(c-backward-syntactic-ws) |
(c-debug-sws-msg |
1320 |
(if (memq (char-syntax (char-before)) jump-syntax) |
"c-forward-sws extending rung with [%s..%s] (max %s)" |
1321 |
(goto-char (scan-sexps (point) -1)) |
(1+ rung-pos) (1+ (point)) (point-max)) |
1322 |
(backward-char)) |
(unless (get-text-property (point) 'c-is-sws) |
1323 |
(setq count (1- count))) |
;; Remove any `c-in-sws' property from the last char of |
1324 |
(error (goto-char last))) |
;; the rung before we mark it with `c-is-sws', so that we |
1325 |
(if (bobp) (goto-char last))))) |
;; won't connect with the remains of a broken "ladder". |
1326 |
count))) |
(c-remove-in-sws (point) (1+ (point)))) |
1327 |
|
(c-put-is-sws (1+ rung-pos) |
1328 |
|
(1+ (point))) |
1329 |
|
(c-put-in-sws rung-pos |
1330 |
|
(setq rung-pos (point) |
1331 |
|
last-put-in-sws-pos rung-pos))) |
1332 |
|
|
1333 |
(defun c-syntactic-re-search-forward (regexp &optional bound noerror count |
(setq simple-ws-end (point)) |
1334 |
paren-level) |
(c-forward-comments) |
|
;; Like `re-search-forward', but only report matches that are found |
|
|
;; in syntactically significant text. I.e. matches that begins in |
|
|
;; comments, macros or string literals are ignored. The start point |
|
|
;; is assumed to be outside any comment, macro or string literal, or |
|
|
;; else the content of that region is taken as syntactically |
|
|
;; significant text. If PAREN-LEVEL is non-nil, an additional |
|
|
;; restriction is added to ignore matches in nested paren sexps, and |
|
|
;; the search will also not go outside the current paren sexp. |
|
|
(or bound (setq bound (point-max))) |
|
|
(or count (setq count 1)) |
|
|
(if paren-level (setq paren-level -1)) |
|
|
(let ((start (point)) |
|
|
(pos (point)) |
|
|
match-pos state) |
|
|
(condition-case err |
|
|
(while (and (> count 0) |
|
|
(re-search-forward regexp bound noerror)) |
|
|
(setq match-pos (point) |
|
|
state (parse-partial-sexp pos (match-beginning 0) |
|
|
paren-level nil state) |
|
|
pos (point)) |
|
|
(cond ((nth 3 state) |
|
|
;; Match inside a string. Skip to the end of it |
|
|
;; before continuing. |
|
|
(let ((ender (make-string 1 (nth 3 state)))) |
|
|
(while (progn |
|
|
(search-forward ender bound noerror) |
|
|
(setq state (parse-partial-sexp pos (point) |
|
|
nil nil state) |
|
|
pos (point)) |
|
|
(nth 3 state))))) |
|
|
((nth 7 state) |
|
|
;; Match inside a line comment. Skip to eol. Use |
|
|
;; re-search-forward for it to get the right bound |
|
|
;; behavior. |
|
|
(re-search-forward "[\n\r]" bound noerror)) |
|
|
((nth 4 state) |
|
|
;; Match inside a block comment. Skip to the '*/'. |
|
|
(re-search-forward "\\*/" bound noerror)) |
|
|
((save-excursion (c-beginning-of-macro start)) |
|
|
;; Match inside a macro. Skip to the end of it. |
|
|
(c-end-of-macro)) |
|
|
((and paren-level (/= (car state) 0)) |
|
|
(if (> (car state) 0) |
|
|
;; Match inside a nested paren sexp. Skip out of it. |
|
|
(setq state (parse-partial-sexp pos bound 0 nil state) |
|
|
pos (point)) |
|
|
;; Have exited the current paren sexp. The |
|
|
;; parse-partial-sexp above has left us just after |
|
|
;; the closing paren in this case. Just make |
|
|
;; re-search-forward above fail in the appropriate |
|
|
;; way; we'll adjust the leave off point below if |
|
|
;; necessary. |
|
|
(setq bound (point)))) |
|
|
(t |
|
|
;; A real match. |
|
|
(setq count (1- count))))) |
|
|
(error |
|
|
(goto-char start) |
|
|
(signal (car err) (cdr err)))) |
|
|
(if (= count 0) |
|
|
(progn |
|
|
(goto-char match-pos) |
|
|
match-pos) |
|
|
;; Search failed. Set point as appropriate. |
|
|
(cond ((eq noerror t) |
|
|
(goto-char start)) |
|
|
(paren-level |
|
|
(if (eq (car (parse-partial-sexp pos bound -1 nil state)) -1) |
|
|
(backward-char))) |
|
|
(t |
|
|
(goto-char bound))) |
|
|
nil))) |
|
1335 |
|
|
1336 |
|
(cond |
1337 |
(defun c-in-literal (&optional lim detect-cpp) |
((/= (point) simple-ws-end) |
1338 |
"Return the type of literal point is in, if any. |
;; Skipped over comments. Don't cache at eob in case the buffer |
1339 |
The return value is `c' if in a C-style comment, `c++' if in a C++ |
;; is narrowed. |
1340 |
style comment, `string' if in a string literal, `pound' if DETECT-CPP |
(not (eobp))) |
|
is non-nil and on a preprocessor line, or nil if somewhere else. |
|
|
Optional LIM is used as the backward limit of the search. If omitted, |
|
|
or nil, `c-beginning-of-defun' is used. |
|
1341 |
|
|
1342 |
The last point calculated is cached if the cache is enabled, i.e. if |
((save-excursion |
1343 |
`c-in-literal-cache' is bound to a two element vector." |
(and c-opt-cpp-prefix |
1344 |
(if (and (vectorp c-in-literal-cache) |
(looking-at c-opt-cpp-start) |
1345 |
(= (point) (aref c-in-literal-cache 0))) |
(progn (skip-chars-backward " \t") |
1346 |
(aref c-in-literal-cache 1) |
(bolp)) |
1347 |
(let ((rtn (save-excursion |
(or (bobp) |
1348 |
(let* ((lim (or lim (c-point 'bod))) |
(progn (backward-char) |
1349 |
(state (parse-partial-sexp lim (point)))) |
(not (eq (char-before) ?\\)))))) |
1350 |
(cond |
;; Skip a preprocessor directive. |
1351 |
((nth 3 state) 'string) |
(end-of-line) |
1352 |
((nth 4 state) (if (nth 7 state) 'c++ 'c)) |
(while (and (eq (char-before) ?\\) |
1353 |
((and detect-cpp (c-beginning-of-macro lim)) 'pound) |
(= (forward-line 1) 0)) |
1354 |
(t nil)))))) |
(end-of-line)) |
1355 |
;; cache this result if the cache is enabled |
(forward-line 1) |
1356 |
(if (not c-in-literal-cache) |
(setq safe-start t) |
1357 |
(setq c-in-literal-cache (vector (point) rtn))) |
;; Don't cache at eob in case the buffer is narrowed. |
1358 |
rtn))) |
(not (eobp))))) |
1359 |
|
|
1360 |
|
;; We've searched over a piece of non-white syntactic ws. See if this |
1361 |
|
;; can be cached. |
1362 |
|
(setq next-rung-pos (point)) |
1363 |
|
(skip-chars-forward " \t\n\r\f\v") |
1364 |
|
(setq rung-end-pos (min (1+ (point)) (point-max))) |
1365 |
|
|
1366 |
|
(if (or |
1367 |
|
;; Cache if we haven't skipped comments only, and if we started |
1368 |
|
;; either from a marked rung or from a completely uncached |
1369 |
|
;; position. |
1370 |
|
(and safe-start |
1371 |
|
(or rung-is-marked |
1372 |
|
(not (get-text-property simple-ws-end 'c-in-sws)))) |
1373 |
|
|
1374 |
|
;; See if there's a marked rung in the encountered simple ws. If |
1375 |
|
;; so then we can cache, unless `safe-start' is nil. Even then |
1376 |
|
;; we need to do this to check if the cache can be used for the |
1377 |
|
;; next step. |
1378 |
|
(and (setq next-rung-is-marked |
1379 |
|
(text-property-any next-rung-pos rung-end-pos |
1380 |
|
'c-is-sws t)) |
1381 |
|
safe-start)) |
1382 |
|
|
1383 |
;; XEmacs has a built-in function that should make this much quicker. |
(progn |
1384 |
;; I don't think we even need the cache, which makes our lives more |
(c-debug-sws-msg |
1385 |
;; complicated anyway. In this case, lim is only used to detect |
"c-forward-sws caching [%s..%s] - [%s..%s] (max %s)" |
1386 |
;; cpp directives. |
rung-pos (1+ simple-ws-end) next-rung-pos rung-end-pos |
1387 |
(defun c-fast-in-literal (&optional lim detect-cpp) |
(point-max)) |
1388 |
(let ((context (buffer-syntactic-context))) |
|
1389 |
(cond |
;; Remove the properties for any nested ws that might be cached. |
1390 |
((eq context 'string) 'string) |
;; Only necessary for `c-is-sws' since `c-in-sws' will be set |
1391 |
((eq context 'comment) 'c++) |
;; anyway. |
1392 |
((eq context 'block-comment) 'c) |
(c-remove-is-sws (1+ simple-ws-end) next-rung-pos) |
1393 |
((and detect-cpp (save-excursion (c-beginning-of-macro lim))) 'pound)))) |
(unless (and rung-is-marked (= rung-pos simple-ws-end)) |
1394 |
|
(c-put-is-sws rung-pos |
1395 |
|
(1+ simple-ws-end)) |
1396 |
|
(setq rung-is-marked t)) |
1397 |
|
(c-put-in-sws rung-pos |
1398 |
|
(setq rung-pos (point) |
1399 |
|
last-put-in-sws-pos rung-pos)) |
1400 |
|
(unless (get-text-property (1- rung-end-pos) 'c-is-sws) |
1401 |
|
;; Remove any `c-in-sws' property from the last char of |
1402 |
|
;; the rung before we mark it with `c-is-sws', so that we |
1403 |
|
;; won't connect with the remains of a broken "ladder". |
1404 |
|
(c-remove-in-sws (1- rung-end-pos) rung-end-pos)) |
1405 |
|
(c-put-is-sws next-rung-pos |
1406 |
|
rung-end-pos)) |
1407 |
|
|
1408 |
|
(c-debug-sws-msg |
1409 |
|
"c-forward-sws not caching [%s..%s] - [%s..%s] (max %s)" |
1410 |
|
rung-pos (1+ simple-ws-end) next-rung-pos rung-end-pos |
1411 |
|
(point-max)) |
1412 |
|
|
1413 |
|
;; Set `rung-pos' for the next rung. It's the same thing here as |
1414 |
|
;; initially, except that the rung position is set as early as |
1415 |
|
;; possible since we can't be in the ending ws of a line comment or |
1416 |
|
;; cpp directive now. |
1417 |
|
(if (setq rung-is-marked next-rung-is-marked) |
1418 |
|
(setq rung-pos (1- (next-single-property-change |
1419 |
|
rung-is-marked 'c-is-sws nil rung-end-pos))) |
1420 |
|
(setq rung-pos next-rung-pos)) |
1421 |
|
(setq safe-start t))) |
1422 |
|
|
1423 |
|
;; Make sure that the newly marked `c-in-sws' region doesn't connect to |
1424 |
|
;; another one after the point (which might occur when editing inside a |
1425 |
|
;; comment or macro). |
1426 |
|
(when (eq last-put-in-sws-pos (point)) |
1427 |
|
(cond ((< last-put-in-sws-pos (point-max)) |
1428 |
|
(c-debug-sws-msg |
1429 |
|
"c-forward-sws clearing at %s for cache separation" |
1430 |
|
last-put-in-sws-pos) |
1431 |
|
(c-remove-in-sws last-put-in-sws-pos |
1432 |
|
(1+ last-put-in-sws-pos))) |
1433 |
|
(t |
1434 |
|
;; If at eob we have to clear the last character before the end |
1435 |
|
;; instead since the buffer might be narrowed and there might |
1436 |
|
;; be a `c-in-sws' after (point-max). In this case it's |
1437 |
|
;; necessary to clear both properties. |
1438 |
|
(c-debug-sws-msg |
1439 |
|
"c-forward-sws clearing thoroughly at %s for cache separation" |
1440 |
|
(1- last-put-in-sws-pos)) |
1441 |
|
(c-remove-is-and-in-sws (1- last-put-in-sws-pos) |
1442 |
|
last-put-in-sws-pos)))) |
1443 |
|
))) |
1444 |
|
|
1445 |
(if (fboundp 'buffer-syntactic-context) |
(defun c-backward-sws () |
1446 |
(defalias 'c-in-literal 'c-fast-in-literal)) |
;; Used by `c-backward-syntactic-ws' to implement the unbounded search. |
1447 |
|
|
1448 |
(defun c-literal-limits (&optional lim near not-in-delimiter) |
(let (;; `rung-pos' is set to a position as late as possible in the unmarked |
1449 |
"Return a cons of the beginning and end positions of the comment or |
;; part of the simple ws region. |
1450 |
string surrounding point (including both delimiters), or nil if point |
(rung-pos (point)) next-rung-pos last-put-in-sws-pos |
1451 |
isn't in one. If LIM is non-nil, it's used as the \"safe\" position |
rung-is-marked simple-ws-beg cmt-skip-pos) |
1452 |
to start parsing from. If NEAR is non-nil, then the limits of any |
|
1453 |
literal next to point is returned. \"Next to\" means there's only [ |
;; Skip simple horizontal ws and do a quick check on the preceding |
1454 |
\t] between point and the literal. The search for such a literal is |
;; character to see if it's anying that can't end syntactic ws, so we can |
1455 |
done first in forward direction. If NOT-IN-DELIMITER is non-nil, the |
;; bail out early in the majority of cases when there just are a few ws |
1456 |
case when point is inside a starting delimiter won't be recognized. |
;; chars. Newlines are complicated in the backward direction, so we can't |
1457 |
This only has effect for comments, which have starting delimiters with |
;; skip over them. |
1458 |
more than one character." |
(skip-chars-backward " \t\f") |
1459 |
(save-excursion |
(when (and (not (bobp)) |
1460 |
(let* ((pos (point)) |
(save-excursion |
1461 |
(lim (or lim (c-point 'bod))) |
(backward-char) |
1462 |
(state (parse-partial-sexp lim (point)))) |
(looking-at c-syntactic-ws-end))) |
|
(cond ((nth 3 state) |
|
|
;; String. Search backward for the start. |
|
|
(while (nth 3 state) |
|
|
(search-backward (make-string 1 (nth 3 state))) |
|
|
(setq state (parse-partial-sexp lim (point)))) |
|
|
(cons (point) (or (c-safe (c-forward-sexp 1) (point)) |
|
|
(point-max)))) |
|
|
((nth 7 state) |
|
|
;; Line comment. Search from bol for the comment starter. |
|
|
(beginning-of-line) |
|
|
(setq state (parse-partial-sexp lim (point)) |
|
|
lim (point)) |
|
|
(while (not (nth 7 state)) |
|
|
(search-forward "//") ; Should never fail. |
|
|
(setq state (parse-partial-sexp |
|
|
lim (point) nil nil state) |
|
|
lim (point))) |
|
|
(backward-char 2) |
|
|
(cons (point) (progn (c-forward-comment 1) (point)))) |
|
|
((nth 4 state) |
|
|
;; Block comment. Search backward for the comment starter. |
|
|
(while (nth 4 state) |
|
|
(search-backward "/*") ; Should never fail. |
|
|
(setq state (parse-partial-sexp lim (point)))) |
|
|
(cons (point) (progn (c-forward-comment 1) (point)))) |
|
|
((and (not not-in-delimiter) |
|
|
(not (nth 5 state)) |
|
|
(eq (char-before) ?/) |
|
|
(looking-at "[/*]")) |
|
|
;; We're standing in a comment starter. |
|
|
(backward-char 1) |
|
|
(cons (point) (progn (c-forward-comment 1) (point)))) |
|
|
(near |
|
|
(goto-char pos) |
|
|
;; Search forward for a literal. |
|
|
(skip-chars-forward " \t") |
|
|
(cond |
|
|
((eq (char-syntax (or (char-after) ?\ )) ?\") ; String. |
|
|
(cons (point) (or (c-safe (c-forward-sexp 1) (point)) |
|
|
(point-max)))) |
|
|
((looking-at "/[/*]") ; Line or block comment. |
|
|
(cons (point) (progn (c-forward-comment 1) (point)))) |
|
|
(t |
|
|
;; Search backward. |
|
|
(skip-chars-backward " \t") |
|
|
(let ((end (point)) beg) |
|
|
(cond |
|
|
((eq (char-syntax (or (char-before) ?\ )) ?\") ; String. |
|
|
(setq beg (c-safe (c-backward-sexp 1) (point)))) |
|
|
((and (c-safe (forward-char -2) t) |
|
|
(looking-at "*/")) |
|
|
;; Block comment. Due to the nature of line |
|
|
;; comments, they will always be covered by the |
|
|
;; normal case above. |
|
|
(goto-char end) |
|
|
(c-forward-comment -1) |
|
|
;; If LIM is bogus, beg will be bogus. |
|
|
(setq beg (point)))) |
|
|
(if beg (cons beg end)))))) |
|
|
)))) |
|
1463 |
|
|
1464 |
(defun c-literal-limits-fast (&optional lim near not-in-delimiter) |
;; Try to find a rung position in the simple ws preceding point, so that |
1465 |
;; Like c-literal-limits, but for emacsen whose `parse-partial-sexp' |
;; we can get a cache hit even if the last bit of the simple ws has |
1466 |
;; returns the pos of the comment start. |
;; changed recently. |
1467 |
(save-excursion |
(setq simple-ws-beg (point)) |
1468 |
(let* ((pos (point)) |
(skip-chars-backward " \t\n\r\f\v") |
1469 |
(lim (or lim (c-point 'bod))) |
(if (setq rung-is-marked (text-property-any |
1470 |
(state (parse-partial-sexp lim (point)))) |
(point) (min (1+ rung-pos) (point-max)) |
1471 |
(cond ((nth 3 state) ; String. |
'c-is-sws t)) |
1472 |
(goto-char (nth 8 state)) |
;; `rung-pos' will be the earliest marked position, which means that |
1473 |
(cons (point) (or (c-safe (c-forward-sexp 1) (point)) |
;; there might be later unmarked parts in the simple ws region. |
1474 |
(point-max)))) |
;; It's not worth the effort to fix that; the last part of the |
1475 |
((nth 4 state) ; Comment. |
;; simple ws is also typically edited often, so it could be wasted. |
1476 |
(goto-char (nth 8 state)) |
(goto-char (setq rung-pos rung-is-marked)) |
1477 |
(cons (point) (progn (c-forward-comment 1) (point)))) |
(goto-char simple-ws-beg)) |
|
((and (not not-in-delimiter) |
|
|
(not (nth 5 state)) |
|
|
(eq (char-before) ?/) |
|
|
(looking-at "[/*]")) |
|
|
;; We're standing in a comment starter. |
|
|
(backward-char 1) |
|
|
(cons (point) (progn (c-forward-comment 1) (point)))) |
|
|
(near |
|
|
(goto-char pos) |
|
|
;; Search forward for a literal. |
|
|
(skip-chars-forward " \t") |
|
|
(cond |
|
|
((eq (char-syntax (or (char-after) ?\ )) ?\") ; String. |
|
|
(cons (point) (or (c-safe (c-forward-sexp 1) (point)) |
|
|
(point-max)))) |
|
|
((looking-at "/[/*]") ; Line or block comment. |
|
|
(cons (point) (progn (c-forward-comment 1) (point)))) |
|
|
(t |
|
|
;; Search backward. |
|
|
(skip-chars-backward " \t") |
|
|
(let ((end (point)) beg) |
|
|
(cond |
|
|
((eq (char-syntax (or (char-before) ?\ )) ?\") ; String. |
|
|
(setq beg (c-safe (c-backward-sexp 1) (point)))) |
|
|
((and (c-safe (forward-char -2) t) |
|
|
(looking-at "*/")) |
|
|
;; Block comment. Due to the nature of line |
|
|
;; comments, they will always be covered by the |
|
|
;; normal case above. |
|
|
(goto-char end) |
|
|
(c-forward-comment -1) |
|
|
;; If LIM is bogus, beg will be bogus. |
|
|
(setq beg (point)))) |
|
|
(if beg (cons beg end)))))) |
|
|
)))) |
|
1478 |
|
|
1479 |
(if (c-safe (> (length (save-excursion (parse-partial-sexp 1 1))) 8)) |
(while |
1480 |
(defalias 'c-literal-limits 'c-literal-limits-fast)) |
(progn |
1481 |
|
(while |
1482 |
|
(when (and rung-is-marked |
1483 |
|
(not (bobp)) |
1484 |
|
(get-text-property (1- (point)) 'c-in-sws)) |
1485 |
|
|
1486 |
|
;; The following search is the main reason that `c-in-sws' |
1487 |
|
;; and `c-is-sws' aren't combined to one property. |
1488 |
|
(goto-char (previous-single-property-change |
1489 |
|
(point) 'c-in-sws nil (point-min))) |
1490 |
|
(unless (get-text-property (point) 'c-is-sws) |
1491 |
|
;; If the `c-in-sws' region extended past the first |
1492 |
|
;; `c-is-sws' char we have to go forward a bit. |
1493 |
|
(goto-char (next-single-property-change |
1494 |
|
(point) 'c-is-sws))) |
1495 |
|
|
1496 |
|
(c-debug-sws-msg |
1497 |
|
"c-backward-sws cached move %s <- %s (min %s)" |
1498 |
|
(point) rung-pos (point-min)) |
1499 |
|
|
1500 |
|
(setq rung-pos (point)) |
1501 |
|
(if (and (< (min (skip-chars-backward " \t\f\v") |
1502 |
|
(progn |
1503 |
|
(setq simple-ws-beg (point)) |
1504 |
|
(skip-chars-backward " \t\n\r\f\v"))) |
1505 |
|
0) |
1506 |
|
(setq rung-is-marked |
1507 |
|
(text-property-any (point) rung-pos |
1508 |
|
'c-is-sws t))) |
1509 |
|
t |
1510 |
|
(goto-char simple-ws-beg) |
1511 |
|
nil)) |
1512 |
|
|
1513 |
(defun c-collect-line-comments (range) |
;; We'll loop here if there is simple ws before the first rung. |
1514 |
"If the argument is a cons of two buffer positions (such as returned by |
;; That means that there's been some change in it and it's |
1515 |
`c-literal-limits'), and that range contains a C++ style line comment, |
;; possible that we've stepped into another ladder, so extend |
1516 |
then an extended range is returned that contains all adjacent line |
;; the previous one to join with it if there is one, and try to |
1517 |
comments (i.e. all comments that starts in the same column with no |
;; use the cache again. |
1518 |
empty lines or non-whitespace characters between them). Otherwise the |
(c-debug-sws-msg |
1519 |
argument is returned." |
"c-backward-sws extending rung with [%s..%s] (min %s)" |
1520 |
(save-excursion |
rung-is-marked rung-pos (point-min)) |
1521 |
(condition-case nil |
(unless (get-text-property (1- rung-pos) 'c-is-sws) |
1522 |
(if (and (consp range) (progn |
;; Remove any `c-in-sws' property from the last char of |
1523 |
(goto-char (car range)) |
;; the rung before we mark it with `c-is-sws', so that we |
1524 |
(looking-at "//"))) |
;; won't connect with the remains of a broken "ladder". |
1525 |
(let ((col (current-column)) |
(c-remove-in-sws (1- rung-pos) rung-pos)) |
1526 |
(beg (point)) |
(c-put-is-sws rung-is-marked |
1527 |
(bopl (c-point 'bopl)) |
rung-pos) |
1528 |
(end (cdr range))) |
(c-put-in-sws rung-is-marked |
1529 |
;; Got to take care in the backward direction to handle |
(1- rung-pos)) |
1530 |
;; comments which are preceded by code. |
(setq rung-pos rung-is-marked |
1531 |
(while (and (c-forward-comment -1) |
last-put-in-sws-pos rung-pos)) |
|
(>= (point) bopl) |
|
|
(looking-at "//") |
|
|
(= col (current-column))) |
|
|
(setq beg (point) |
|
|
bopl (c-point 'bopl))) |
|
|
(goto-char end) |
|
|
(while (and (progn (skip-chars-forward " \t") |
|
|
(looking-at "//")) |
|
|
(= col (current-column)) |
|
|
(prog1 (zerop (forward-line 1)) |
|
|
(setq end (point))))) |
|
|
(cons beg end)) |
|
|
range) |
|
|
(error range)))) |
|
1532 |
|
|
1533 |
(defun c-literal-type (range) |
(c-backward-comments) |
1534 |
"Convenience function that given the result of `c-literal-limits', |
(setq cmt-skip-pos (point)) |
1535 |
returns nil or the type of literal that the range surrounds. It's |
|
1536 |
much faster than using `c-in-literal' and is intended to be used when |
(cond |
1537 |
you need both the type of a literal and its limits." |
((and c-opt-cpp-prefix |
1538 |
(if (consp range) |
(/= cmt-skip-pos simple-ws-beg) |
1539 |
(save-excursion |
(c-beginning-of-macro)) |
1540 |
(goto-char (car range)) |
;; Inside a cpp directive. See if it should be skipped over. |
1541 |
(cond ((eq (char-syntax (or (char-after) ?\ )) ?\") 'string) |
(let ((cpp-beg (point))) |
1542 |
((looking-at "//") 'c++) |
|
1543 |
(t 'c))) ; Assuming the range is valid. |
;; Move back over all line continuations in the region skipped |
1544 |
range)) |
;; over by `c-backward-comments'. If we go past it then we |
1545 |
|
;; started inside the cpp directive. |
1546 |
|
(goto-char simple-ws-beg) |
1547 |
|
(beginning-of-line) |
1548 |
|
(while (and (> (point) cmt-skip-pos) |
1549 |
|
(progn (backward-char) |
1550 |
|
(eq (char-before) ?\\))) |
1551 |
|
(beginning-of-line)) |
1552 |
|
|
1553 |
|
(if (< (point) cmt-skip-pos) |
1554 |
|
;; Don't move past the cpp directive if we began inside |
1555 |
|
;; it. Note that the position at the end of the last line |
1556 |
|
;; of the macro is also considered to be within it. |
1557 |
|
(progn (goto-char cmt-skip-pos) |
1558 |
|
nil) |
1559 |
|
|
1560 |
|
;; It's worthwhile to spend a little bit of effort on finding |
1561 |
|
;; the end of the macro, to get a good `simple-ws-beg' |
1562 |
|
;; position for the cache. Note that `c-backward-comments' |
1563 |
|
;; could have stepped over some comments before going into |
1564 |
|
;; the macro, and then `simple-ws-beg' must be kept on the |
1565 |
|
;; same side of those comments. |
1566 |
|
(goto-char simple-ws-beg) |
1567 |
|
(skip-chars-backward " \t\n\r\f\v") |
1568 |
|
(if (eq (char-before) ?\\) |
1569 |
|
(forward-char)) |
1570 |
|
(forward-line 1) |
1571 |
|
(if (< (point) simple-ws-beg) |
1572 |
|
;; Might happen if comments after the macro were skipped |
1573 |
|
;; over. |
1574 |
|
(setq simple-ws-beg (point))) |
1575 |
|
|
1576 |
|
(goto-char cpp-beg) |
1577 |
|
t))) |
1578 |
|
|
1579 |
|
((/= (save-excursion |
1580 |
|
(skip-chars-forward " \t\n\r\f\v" simple-ws-beg) |
1581 |
|
(setq next-rung-pos (point))) |
1582 |
|
simple-ws-beg) |
1583 |
|
;; Skipped over comments. Must put point at the end of |
1584 |
|
;; the simple ws at point since we might be after a line |
1585 |
|
;; comment or cpp directive that's been partially |
1586 |
|
;; narrowed out, and we can't risk marking the simple ws |
1587 |
|
;; at the end of it. |
1588 |
|
(goto-char next-rung-pos) |
1589 |
|
t))) |
1590 |
|
|
1591 |
|
;; We've searched over a piece of non-white syntactic ws. See if this |
1592 |
|
;; can be cached. |
1593 |
|
(setq next-rung-pos (point)) |
1594 |
|
(skip-chars-backward " \t\f\v") |
1595 |
|
|
1596 |
|
(if (or |
1597 |
|
;; Cache if we started either from a marked rung or from a |
1598 |
|
;; completely uncached position. |
1599 |
|
rung-is-marked |
1600 |
|
(not (get-text-property (1- simple-ws-beg) 'c-in-sws)) |
1601 |
|
|
1602 |
|
;; Cache if there's a marked rung in the encountered simple ws. |
1603 |
|
(save-excursion |
1604 |
|
(skip-chars-backward " \t\n\r\f\v") |
1605 |
|
(text-property-any (point) (min (1+ next-rung-pos) (point-max)) |
1606 |
|
'c-is-sws t))) |
1607 |
|
|
1608 |
|
(progn |
1609 |
|
(c-debug-sws-msg |
1610 |
|
"c-backward-sws caching [%s..%s] - [%s..%s] (min %s)" |
1611 |
|
(point) (1+ next-rung-pos) |
1612 |
|
simple-ws-beg (min (1+ rung-pos) (point-max)) |
1613 |
|
(point-min)) |
1614 |
|
|
1615 |
|
;; Remove the properties for any nested ws that might be cached. |
1616 |
|
;; Only necessary for `c-is-sws' since `c-in-sws' will be set |
1617 |
|
;; anyway. |
1618 |
|
(c-remove-is-sws (1+ next-rung-pos) simple-ws-beg) |
1619 |
|
(unless (and rung-is-marked (= simple-ws-beg rung-pos)) |
1620 |
|
(let ((rung-end-pos (min (1+ rung-pos) (point-max)))) |
1621 |
|
(unless (get-text-property (1- rung-end-pos) 'c-is-sws) |
1622 |
|
;; Remove any `c-in-sws' property from the last char of |
1623 |
|
;; the rung before we mark it with `c-is-sws', so that we |
1624 |
|
;; won't connect with the remains of a broken "ladder". |
1625 |
|
(c-remove-in-sws (1- rung-end-pos) rung-end-pos)) |
1626 |
|
(c-put-is-sws simple-ws-beg |
1627 |
|
rung-end-pos) |
1628 |
|
(setq rung-is-marked t))) |
1629 |
|
(c-put-in-sws (setq simple-ws-beg (point) |
1630 |
|
last-put-in-sws-pos simple-ws-beg) |
1631 |
|
rung-pos) |
1632 |
|
(c-put-is-sws (setq rung-pos simple-ws-beg) |
1633 |
|
(1+ next-rung-pos))) |
1634 |
|
|
1635 |
|
(c-debug-sws-msg |
1636 |
|
"c-backward-sws not caching [%s..%s] - [%s..%s] (min %s)" |
1637 |
|
(point) (1+ next-rung-pos) |
1638 |
|
simple-ws-beg (min (1+ rung-pos) (point-max)) |
1639 |
|
(point-min)) |
1640 |
|
(setq rung-pos next-rung-pos |
1641 |
|
simple-ws-beg (point)) |
1642 |
|
)) |
1643 |
|
|
1644 |
|
;; Make sure that the newly marked `c-in-sws' region doesn't connect to |
1645 |
|
;; another one before the point (which might occur when editing inside a |
1646 |
|
;; comment or macro). |
1647 |
|
(when (eq last-put-in-sws-pos (point)) |
1648 |
|
(cond ((< (point-min) last-put-in-sws-pos) |
1649 |
|
(c-debug-sws-msg |
1650 |
|
"c-backward-sws clearing at %s for cache separation" |
1651 |
|
(1- last-put-in-sws-pos)) |
1652 |
|
(c-remove-in-sws (1- last-put-in-sws-pos) |
1653 |
|
last-put-in-sws-pos)) |
1654 |
|
((> (point-min) 1) |
1655 |
|
;; If at bob and the buffer is narrowed, we have to clear the |
1656 |
|
;; character we're standing on instead since there might be a |
1657 |
|
;; `c-in-sws' before (point-min). In this case it's necessary |
1658 |
|
;; to clear both properties. |
1659 |
|
(c-debug-sws-msg |
1660 |
|
"c-backward-sws clearing thoroughly at %s for cache separation" |
1661 |
|
last-put-in-sws-pos) |
1662 |
|
(c-remove-is-and-in-sws last-put-in-sws-pos |
1663 |
|
(1+ last-put-in-sws-pos))))) |
1664 |
|
))) |
1665 |
|
|
1666 |
|
|
1667 |
;; utilities for moving and querying around syntactic elements |
;; A system for handling noteworthy parens before the point. |
1668 |
|
|
1669 |
(defvar c-state-cache nil) |
(defvar c-state-cache nil) |
1670 |
(make-variable-buffer-local 'c-state-cache) |
(make-variable-buffer-local 'c-state-cache) |
1677 |
;; most effective if `c-parse-state' is used on each line while moving |
;; most effective if `c-parse-state' is used on each line while moving |
1678 |
;; forward. |
;; forward. |
1679 |
|
|
1680 |
(defvar c-state-cache-start nil) |
(defvar c-state-cache-start 1) |
1681 |
;; This (point-min) when `c-state-cache' was calculated, to detect |
(make-variable-buffer-local 'c-state-cache-start) |
1682 |
;; that the start point hasn't changed due to narrowing. |
;; This is (point-min) when `c-state-cache' was calculated, since a |
1683 |
|
;; change of narrowing is likely to affect the parens that are visible |
1684 |
|
;; before the point. |
1685 |
|
|
1686 |
|
(defsubst c-invalidate-state-cache (pos) |
1687 |
|
;; Invalidate all info on `c-state-cache' that applies to the buffer |
1688 |
|
;; at POS or higher. This is much like `c-whack-state-after', but |
1689 |
|
;; it never changes a paren pair element into an open paren element. |
1690 |
|
;; Doing that would mean that the new open paren wouldn't have the |
1691 |
|
;; required preceding paren pair element. |
1692 |
|
;; |
1693 |
|
;; This function does not do any hidden buffer changes. |
1694 |
|
(while (and c-state-cache |
1695 |
|
(let ((elem (car c-state-cache))) |
1696 |
|
(if (consp elem) |
1697 |
|
(or (<= pos (car elem)) |
1698 |
|
(< pos (cdr elem))) |
1699 |
|
(<= pos elem)))) |
1700 |
|
(setq c-state-cache (cdr c-state-cache)))) |
1701 |
|
|
1702 |
(defun c-parse-state () |
(defun c-parse-state () |
1703 |
;; Finds and records all noteworthy parens between some good point |
;; Finds and records all noteworthy parens between some good point |
1708 |
;; The returned value is a list of the noteworthy parens with the |
;; The returned value is a list of the noteworthy parens with the |
1709 |
;; last one first. If an element in the list is an integer, it's |
;; last one first. If an element in the list is an integer, it's |
1710 |
;; the position of an open paren which has not been closed before |
;; the position of an open paren which has not been closed before |
1711 |
;; point. If an element is a cons, it gives the position of a |
;; the point. If an element is a cons, it gives the position of a |
1712 |
;; closed brace paren pair; the car is the start paren position and |
;; closed brace paren pair; the car is the start paren position and |
1713 |
;; the cdr is the position following the closing paren. Only the |
;; the cdr is the position following the closing paren. Only the |
1714 |
;; last closed brace paren pair before each open paren is recorded, |
;; last closed brace paren pair before each open paren is recorded, |
1715 |
;; and thus the state never contains two cons elements in |
;; and thus the state never contains two cons elements in |
1716 |
;; succession. |
;; succession. |
1717 |
|
;; |
1718 |
|
;; Currently no characters which are given paren syntax with the |
1719 |
|
;; syntax-table property are recorded, i.e. angle bracket arglist |
1720 |
|
;; parens are never present here. Note that this might change. |
1721 |
|
;; |
1722 |
|
;; This function does not do any hidden buffer changes. |
1723 |
|
|
1724 |
(save-restriction |
(save-restriction |
1725 |
(let* ((here (point)) |
(let* ((here (point)) |
1726 |
(c-macro-start (c-query-macro-start)) |
(c-macro-start (c-query-macro-start)) |
1727 |
(in-macro-start (or c-macro-start (point))) |
(in-macro-start (or c-macro-start (point))) |
1728 |
old-state last-pos pairs pos save-pos) |
old-state last-pos pairs pos save-pos) |
1729 |
;; Somewhat ugly use of c-check-state-cache to get rid of the |
(c-invalidate-state-cache (point)) |
1730 |
;; part of the state cache that is after point. Can't use |
|
1731 |
;; c-whack-state-after for the same reasons as in that function. |
;; If the minimum position has changed due to narrowing then we |
1732 |
(c-check-state-cache (point) nil nil) |
;; have to fix the tail of `c-state-cache' accordingly. |
1733 |
|
(unless (= c-state-cache-start (point-min)) |
1734 |
|
(if (> (point-min) c-state-cache-start) |
1735 |
|
;; If point-min has moved forward then we just need to cut |
1736 |
|
;; off a bit of the tail. |
1737 |
|
(let ((ptr (cons nil c-state-cache)) elem) |
1738 |
|
(while (and (setq elem (cdr ptr)) |
1739 |
|
(>= (if (consp elem) (car elem) elem) |
1740 |
|
(point-min))) |
1741 |
|
(setq ptr elem)) |
1742 |
|
(when (consp ptr) |
1743 |
|
(if (eq (cdr ptr) c-state-cache) |
1744 |
|
(setq c-state-cache nil) |
1745 |
|
(setcdr ptr nil)))) |
1746 |
|
;; If point-min has moved backward then we drop the state |
1747 |
|
;; completely. It's possible to do a better job here and |
1748 |
|
;; recalculate the top only. |
1749 |
|
(setq c-state-cache nil)) |
1750 |
|
(setq c-state-cache-start (point-min))) |
1751 |
|
|
1752 |
;; Get the latest position we know are directly inside the |
;; Get the latest position we know are directly inside the |
1753 |
;; closest containing paren of the cached state. |
;; closest containing paren of the cached state. |
1754 |
(setq last-pos (and c-state-cache |
(setq last-pos (and c-state-cache |
1755 |
(if (consp (car c-state-cache)) |
(if (consp (car c-state-cache)) |
1756 |
(cdr (car c-state-cache)) |
(cdr (car c-state-cache)) |
1757 |
(1+ (car c-state-cache))))) |
(1+ (car c-state-cache))))) |
1758 |
|
|
1759 |
;; Check if the found last-pos is in a macro. If it is, and |
;; Check if the found last-pos is in a macro. If it is, and |
1760 |
;; we're not in the same macro, we must discard everything on |
;; we're not in the same macro, we must discard everything on |
1761 |
;; c-state-cache that is inside the macro before using it. |
;; c-state-cache that is inside the macro before using it. |
1764 |
(goto-char last-pos) |
(goto-char last-pos) |
1765 |
(when (and (c-beginning-of-macro) |
(when (and (c-beginning-of-macro) |
1766 |
(/= (point) in-macro-start)) |
(/= (point) in-macro-start)) |
1767 |
(c-check-state-cache (point) nil nil) |
(c-invalidate-state-cache (point)) |
1768 |
;; Set last-pos again, just like above. |
;; Set last-pos again, just like above. |
1769 |
(setq last-pos (and c-state-cache |
(setq last-pos (and c-state-cache |
1770 |
(if (consp (car c-state-cache)) |
(if (consp (car c-state-cache)) |
1771 |
(cdr (car c-state-cache)) |
(cdr (car c-state-cache)) |
1772 |
(1+ (car c-state-cache)))))))) |
(1+ (car c-state-cache)))))))) |
1773 |
|
|
1774 |
(setq pos |
(setq pos |
1775 |
;; Find the start position for the forward search. (Can't |
;; Find the start position for the forward search. (Can't |
1776 |
;; search in the backward direction since point might be |
;; search in the backward direction since point might be |
1777 |
;; in some kind of literal.) |
;; in some kind of literal.) |
1778 |
(or (when last-pos |
(or (when last-pos |
1779 |
|
|
1780 |
;; There's a cached state with a containing paren. Pop |
;; There's a cached state with a containing paren. Pop |
1781 |
;; off the stale containing sexps from it by going |
;; off the stale containing sexps from it by going |
1782 |
;; forward out of parens as far as possible. |
;; forward out of parens as far as possible. |
1791 |
c-state-cache (cdr-safe (cdr c-state-cache))) |
c-state-cache (cdr-safe (cdr c-state-cache))) |
1792 |
(setq pair-beg (car c-state-cache) |
(setq pair-beg (car c-state-cache) |
1793 |
c-state-cache (cdr c-state-cache)))) |
c-state-cache (cdr c-state-cache)))) |
1794 |
|
|
1795 |
(when (and pair-beg (eq (char-after pair-beg) ?{)) |
(when (and pair-beg (eq (char-after pair-beg) ?{)) |
1796 |
;; The last paren pair we moved out from was a brace |
;; The last paren pair we moved out from was a brace |
1797 |
;; pair. Modify the state to record this as a closed |
;; pair. Modify the state to record this as a closed |
1800 |
(setq c-state-cache (cdr c-state-cache))) |
(setq c-state-cache (cdr c-state-cache))) |
1801 |
(setq c-state-cache (cons (cons pair-beg last-pos) |
(setq c-state-cache (cons (cons pair-beg last-pos) |
1802 |
c-state-cache)))) |
c-state-cache)))) |
1803 |
|
|
1804 |
;; Check if the preceding balanced paren is within a |
;; Check if the preceding balanced paren is within a |
1805 |
;; macro; it should be ignored if we're outside the |
;; macro; it should be ignored if we're outside the |
1806 |
;; macro. There's no need to check any further upwards; |
;; macro. There's no need to check any further upwards; |
1813 |
(when (c-beginning-of-macro) |
(when (c-beginning-of-macro) |
1814 |
(setq here (point) |
(setq here (point) |
1815 |
c-state-cache (cdr c-state-cache))))) |
c-state-cache (cdr c-state-cache))))) |
1816 |
|
|
1817 |
(when c-state-cache |
(when c-state-cache |
1818 |
(setq old-state c-state-cache) |
(setq old-state c-state-cache) |
1819 |
last-pos)) |
last-pos)) |
1820 |
|
|
1821 |
(save-excursion |
(save-excursion |
1822 |
;; go back 2 bods, but ignore any bogus positions |
;; go back 2 bods, but ignore any bogus positions |
1823 |
;; returned by beginning-of-defun (i.e. open paren in |
;; returned by beginning-of-defun (i.e. open paren in |
1829 |
(if (eq (char-after) ?\{) |
(if (eq (char-after) ?\{) |
1830 |
(setq cnt (1- cnt))))) |
(setq cnt (1- cnt))))) |
1831 |
(point)))) |
(point)))) |
1832 |
|
|
1833 |
(narrow-to-region (point-min) here) |
(narrow-to-region (point-min) here) |
1834 |
|
|
1835 |
(while pos |
(while pos |
1836 |
;; Find the balanced brace pairs. |
;; Find the balanced brace pairs. |
1837 |
(setq save-pos pos |
(setq save-pos pos |
1840 |
(setq pos (c-up-list-forward last-pos))) |
(setq pos (c-up-list-forward last-pos))) |
1841 |
(if (eq (char-before last-pos) ?{) |
(if (eq (char-before last-pos) ?{) |
1842 |
(setq pairs (cons (cons last-pos pos) pairs)))) |
(setq pairs (cons (cons last-pos pos) pairs)))) |
1843 |
|
|
1844 |
;; Should ignore any pairs that are in a macro, providing |
;; Should ignore any pairs that are in a macro, providing |
1845 |
;; we're not in the same one. |
;; we're not in the same one. |
1846 |
(when (and pairs (< (car (car pairs)) in-macro-start)) |
(when (and pairs (< (car (car pairs)) in-macro-start)) |
1848 |
(goto-char (car (car pairs))) |
(goto-char (car (car pairs))) |
1849 |
(c-beginning-of-macro)) |
(c-beginning-of-macro)) |
1850 |
(setq pairs (cdr pairs))))) |
(setq pairs (cdr pairs))))) |
1851 |
|
|
1852 |
;; Record the last brace pair. |
;; Record the last brace pair. |
1853 |
(when pairs |
(when pairs |
1854 |
(if (and (eq c-state-cache old-state) |
(if (and (eq c-state-cache old-state) |
1860 |
(setcar pairs (1- (car pairs))) |
(setcar pairs (1- (car pairs))) |
1861 |
(when (consp (car-safe c-state-cache)) |
(when (consp (car-safe c-state-cache)) |
1862 |
;; There could already be a cons first in `c-state-cache' |
;; There could already be a cons first in `c-state-cache' |
1863 |
;; if we've jumped over an unbalanced open paren in a |
;; if we've e.g. jumped over an unbalanced open paren in a |
1864 |
;; macro below. |
;; macro below. |
1865 |
(setq c-state-cache (cdr c-state-cache))) |
(setq c-state-cache (cdr c-state-cache))) |
1866 |
(setq c-state-cache (cons pairs c-state-cache))) |
(setq c-state-cache (cons pairs c-state-cache))) |
1867 |
|
|
1868 |
(if last-pos |
(if last-pos |
1869 |
;; Prepare to loop, but record the open paren only if it's |
;; Prepare to loop, but record the open paren only if it's |
1870 |
;; outside a macro or within the same macro as point. |
;; outside a macro or within the same macro as point, and |
1871 |
|
;; if it is a "real" open paren and not some character |
1872 |
|
;; that got an open paren syntax-table property. |
1873 |
(progn |
(progn |
1874 |
(setq pos last-pos) |
(setq pos last-pos) |
1875 |
(if (or (>= last-pos in-macro-start) |
(if (and (or (>= last-pos in-macro-start) |
1876 |
(save-excursion |
(save-excursion |
1877 |
(goto-char last-pos) |
(goto-char last-pos) |
1878 |
(not (c-beginning-of-macro)))) |
(not (c-beginning-of-macro)))) |
1879 |
(setq c-state-cache (cons (1- pos) c-state-cache)))) |
(= (char-syntax (char-before last-pos)) ?\()) |
1880 |
|
(setq c-state-cache (cons (1- last-pos) c-state-cache)))) |
1881 |
|
|
1882 |
(if (setq last-pos (c-up-list-forward pos)) |
(if (setq last-pos (c-up-list-forward pos)) |
1883 |
;; Found a close paren without a corresponding opening |
;; Found a close paren without a corresponding opening |
1884 |
;; one. Maybe we didn't go back far enough, so try to |
;; one. Maybe we didn't go back far enough, so try to |
1899 |
(1+ (count-lines (point-min) |
(1+ (count-lines (point-min) |
1900 |
(c-point 'bol last-pos))))))) |
(c-point 'bol last-pos))))))) |
1901 |
(setq pos nil)))) |
(setq pos nil)))) |
1902 |
|
|
1903 |
c-state-cache))) |
c-state-cache))) |
1904 |
|
|
1905 |
;; Debug tool to catch cache inconsistencies. |
;; Debug tool to catch cache inconsistencies. |
1923 |
'c-real-parse-state))) |
'c-real-parse-state))) |
1924 |
(c-keep-region-active)) |
(c-keep-region-active)) |
1925 |
|
|
|
(defun c-check-state-cache (beg end old-length) |
|
|
;; Used on `after-change-functions' to adjust `c-state-cache'. |
|
|
;; Prefer speed to finesse here, since there will be many more calls |
|
|
;; to this function than times `c-state-cache' is used. |
|
|
;; |
|
|
;; This is much like `c-whack-state-after', but it never changes a |
|
|
;; paren pair element into an open paren element. Doing that would |
|
|
;; mean that the new open paren wouldn't have the required preceding |
|
|
;; paren pair element. |
|
|
(if (not (eq c-state-cache-start (point-min))) |
|
|
(setq c-state-cache-start (point-min) |
|
|
c-state-cache nil) |
|
|
(while (and c-state-cache |
|
|
(let ((elem (car c-state-cache))) |
|
|
(if (consp elem) |
|
|
(or (<= beg (car elem)) |
|
|
(< beg (cdr elem))) |
|
|
(<= beg elem)))) |
|
|
(setq c-state-cache (cdr c-state-cache))))) |
|
|
|
|
1926 |
(defun c-whack-state-before (bufpos paren-state) |
(defun c-whack-state-before (bufpos paren-state) |
1927 |
;; Whack off any state information from PAREN-STATE which lies |
;; Whack off any state information from PAREN-STATE which lies |
1928 |
;; before BUFPOS. Not destructive on PAREN-STATE. |
;; before BUFPOS. Not destructive on PAREN-STATE. |
1929 |
|
;; |
1930 |
|
;; This function does not do any hidden buffer changes. |
1931 |
(let* ((newstate (list nil)) |
(let* ((newstate (list nil)) |
1932 |
(ptr newstate) |
(ptr newstate) |
1933 |
car) |
car) |
1943 |
(defun c-whack-state-after (bufpos paren-state) |
(defun c-whack-state-after (bufpos paren-state) |
1944 |
;; Whack off any state information from PAREN-STATE which lies at or |
;; Whack off any state information from PAREN-STATE which lies at or |
1945 |
;; after BUFPOS. Not destructive on PAREN-STATE. |
;; after BUFPOS. Not destructive on PAREN-STATE. |
1946 |
|
;; |
1947 |
|
;; This function does not do any hidden buffer changes. |
1948 |
(catch 'done |
(catch 'done |
1949 |
(while paren-state |
(while paren-state |
1950 |
(let ((car (car paren-state))) |
(let ((car (car paren-state))) |
1973 |
(setq paren-state (cdr paren-state))) |
(setq paren-state (cdr paren-state))) |
1974 |
nil))) |
nil))) |
1975 |
|
|
1976 |
|
(defun c-most-enclosing-brace (paren-state &optional bufpos) |
1977 |
|
;; Return the bufpos of the innermost enclosing open paren before |
1978 |
|
;; bufpos that hasn't been narrowed out, or nil if none was found. |
1979 |
|
;; |
1980 |
|
;; This function does not do any hidden buffer changes. |
1981 |
|
(let (enclosingp) |
1982 |
|
(or bufpos (setq bufpos 134217727)) |
1983 |
|
(while paren-state |
1984 |
|
(setq enclosingp (car paren-state) |
1985 |
|
paren-state (cdr paren-state)) |
1986 |
|
(if (or (consp enclosingp) |
1987 |
|
(>= enclosingp bufpos)) |
1988 |
|
(setq enclosingp nil) |
1989 |
|
(if (< enclosingp (point-min)) |
1990 |
|
(setq enclosingp nil)) |
1991 |
|
(setq paren-state nil))) |
1992 |
|
enclosingp)) |
1993 |
|
|
1994 |
|
(defun c-least-enclosing-brace (paren-state &optional bufpos) |
1995 |
|
;; Return the bufpos of the outermost enclosing open paren before |
1996 |
|
;; bufpos that hasn't been narrowed out, or nil if none was found. |
1997 |
|
;; |
1998 |
|
;; This function does not do any hidden buffer changes. |
1999 |
|
(let (pos elem) |
2000 |
|
(or bufpos (setq bufpos 134217727)) |
2001 |
|
(while paren-state |
2002 |
|
(setq elem (car paren-state) |
2003 |
|
paren-state (cdr paren-state)) |
2004 |
|
(unless (or (consp elem) |
2005 |
|
(>= elem bufpos)) |
2006 |
|
(if (>= elem (point-min)) |
2007 |
|
(setq pos elem)))) |
2008 |
|
pos)) |
2009 |
|
|
2010 |
|
(defun c-safe-position (bufpos paren-state) |
2011 |
|
;; Return the closest known safe position higher up than BUFPOS, or |
2012 |
|
;; nil if PAREN-STATE doesn't contain one. Return nil if BUFPOS is |
2013 |
|
;; nil, which is useful to find the closest limit before a given |
2014 |
|
;; limit that might be nil. |
2015 |
|
;; |
2016 |
|
;; This function does not do any hidden buffer changes. |
2017 |
|
(when bufpos |
2018 |
|
(let (elem) |
2019 |
|
(catch 'done |
2020 |
|
(while paren-state |
2021 |
|
(setq elem (car paren-state)) |
2022 |
|
(if (consp elem) |
2023 |
|
(cond ((< (cdr elem) bufpos) |
2024 |
|
(throw 'done (cdr elem))) |
2025 |
|
((< (car elem) bufpos) |
2026 |
|
;; See below. |
2027 |
|
(throw 'done (min (1+ (car elem)) bufpos)))) |
2028 |
|
(if (< elem bufpos) |
2029 |
|
;; elem is the position at and not after the opening paren, so |
2030 |
|
;; we can go forward one more step unless it's equal to |
2031 |
|
;; bufpos. This is useful in some cases avoid an extra paren |
2032 |
|
;; level between the safe position and bufpos. |
2033 |
|
(throw 'done (min (1+ elem) bufpos)))) |
2034 |
|
(setq paren-state (cdr paren-state))))))) |
2035 |
|
|
2036 |
|
(defun c-beginning-of-syntax () |
2037 |
|
;; This is used for `font-lock-beginning-of-syntax-function'. It |
2038 |
|
;; goes to the closest previous point that is known to be outside |
2039 |
|
;; any string literal or comment. `c-state-cache' is used if it has |
2040 |
|
;; a position in the vicinity. |
2041 |
|
(let* ((paren-state c-state-cache) |
2042 |
|
elem |
2043 |
|
|
2044 |
|
(pos (catch 'done |
2045 |
|
;; Note: Similar code in `c-safe-position'. The |
2046 |
|
;; difference is that we accept a safe position at |
2047 |
|
;; the point and don't bother to go forward past open |
2048 |
|
;; parens. |
2049 |
|
(while paren-state |
2050 |
|
(setq elem (car paren-state)) |
2051 |
|
(if (consp elem) |
2052 |
|
(cond ((<= (cdr elem) (point)) |
2053 |
|
(throw 'done (cdr elem))) |
2054 |
|
((<= (car elem) (point)) |
2055 |
|
(throw 'done (car elem)))) |
2056 |
|
(if (<= elem (point)) |
2057 |
|
(throw 'done elem))) |
2058 |
|
(setq paren-state (cdr paren-state))) |
2059 |
|
(point-min)))) |
2060 |
|
|
2061 |
|
(if (> pos (- (point) 4000)) |
2062 |
|
(goto-char pos) |
2063 |
|
;; The position is far back. Try `c-beginning-of-defun-1' |
2064 |
|
;; (although we can't be entirely sure it will go to a position |
2065 |
|
;; outside a comment or string in current emacsen). FIXME: |
2066 |
|
;; Consult `syntax-ppss' here. |
2067 |
|
(c-beginning-of-defun-1) |
2068 |
|
(if (< (point) pos) |
2069 |
|
(goto-char pos))))) |
2070 |
|
|
2071 |
|
|
2072 |
|
;; Tools for scanning identifiers and other tokens. |
2073 |
|
|
2074 |
|
(defun c-on-identifier () |
2075 |
|
"Return non-nil if the point is on or directly after an identifier. |
2076 |
|
Keywords are recognized and not considered identifiers. If an |
2077 |
|
identifier is detected, the returned value is its starting position. |
2078 |
|
If an identifier both starts and stops at the point \(can only happen |
2079 |
|
in Pike) then the point for the preceding one is returned. |
2080 |
|
|
2081 |
|
This function does not do any hidden buffer changes." |
2082 |
|
|
2083 |
|
(save-excursion |
2084 |
|
(if (zerop (skip-syntax-backward "w_")) |
2085 |
|
|
2086 |
|
(when (c-major-mode-is 'pike-mode) |
2087 |
|
;; Handle the `<operator> syntax in Pike. |
2088 |
|
(let ((pos (point))) |
2089 |
|
(skip-chars-backward "!%&*+\\-/<=>^|~[]()") |
2090 |
|
(and (if (< (skip-chars-backward "`") 0) |
2091 |
|
t |
2092 |
|
(goto-char pos) |
2093 |
|
(eq (char-after) ?\`)) |
2094 |
|
(looking-at c-symbol-key) |
2095 |
|
(>= (match-end 0) pos) |
2096 |
|
(point)))) |
2097 |
|
|
2098 |
|
(and (not (looking-at c-keywords-regexp)) |
2099 |
|
(point))))) |
2100 |
|
|
2101 |
|
(defsubst c-simple-skip-symbol-backward () |
2102 |
|
;; If the point is at the end of a symbol then skip backward to the |
2103 |
|
;; beginning of it. Don't move otherwise. Return non-nil if point |
2104 |
|
;; moved. |
2105 |
|
(or (< (skip-syntax-backward "w_") 0) |
2106 |
|
(and (c-major-mode-is 'pike-mode) |
2107 |
|
;; Handle the `<operator> syntax in Pike. |
2108 |
|
(let ((pos (point))) |
2109 |
|
(if (and (< (skip-chars-backward "!%&*+\\-/<=>^|~[]()") 0) |
2110 |
|
(< (skip-chars-backward "`") 0) |
2111 |
|
(looking-at c-symbol-key) |
2112 |
|
(>= (match-end 0) pos)) |
2113 |
|
t |
2114 |
|
(goto-char pos) |
2115 |
|
nil))))) |
2116 |
|
|
2117 |
|
(defsubst c-beginning-of-current-token (&optional back-limit) |
2118 |
|
;; Move to the beginning of the current token. Do not move if not |
2119 |
|
;; in the middle of one. BACK-LIMIT may be used to bound the |
2120 |
|
;; backward search; if given it's assumed to be at the boundary |
2121 |
|
;; between two tokens. |
2122 |
|
(if (looking-at "\\w\\|\\s_") |
2123 |
|
(skip-syntax-backward "w_" back-limit) |
2124 |
|
(let ((start (point))) |
2125 |
|
(when (< (skip-syntax-backward ".()" back-limit) 0) |
2126 |
|
(while (let ((pos (or (and (looking-at c-nonsymbol-token-regexp) |
2127 |
|
(match-end 0)) |
2128 |
|
;; `c-nonsymbol-token-regexp' should always match |
2129 |
|
;; since we've skipped backward over punctuator |
2130 |
|
;; or paren syntax, but consume one char in case |
2131 |
|
;; it doesn't so that we don't leave point before |
2132 |
|
;; some earlier incorrect token. |
2133 |
|
(1+ (point))))) |
2134 |
|
(if (<= pos start) |
2135 |
|
(goto-char pos)) |
2136 |
|
(< pos start))))))) |
2137 |
|
|
2138 |
|
(defsubst c-end-of-current-token (&optional back-limit) |
2139 |
|
;; Move to the end of the current token. Do not move if not in the |
2140 |
|
;; middle of one. BACK-LIMIT may be used to bound the backward |
2141 |
|
;; search; if given it's assumed to be at the boundary between two |
2142 |
|
;; tokens. |
2143 |
|
(let ((start (point))) |
2144 |
|
(cond ((< (skip-syntax-backward "w_" (1- start)) 0) |
2145 |
|
(skip-syntax-forward "w_")) |
2146 |
|
((< (skip-syntax-backward ".()" back-limit) 0) |
2147 |
|
(while (progn |
2148 |
|
(if (looking-at c-nonsymbol-token-regexp) |
2149 |
|
(goto-char (match-end 0)) |
2150 |
|
;; `c-nonsymbol-token-regexp' should always match since |
2151 |
|
;; we've skipped backward over punctuator or paren |
2152 |
|
;; syntax, but move forward in case it doesn't so that |
2153 |
|
;; we don't leave point earlier than we started with. |
2154 |
|
(forward-char)) |
2155 |
|
(< (point) start))))))) |
2156 |
|
|
2157 |
|
(defconst c-jump-syntax-balanced |
2158 |
|
(if (memq 'gen-string-delim c-emacs-features) |
2159 |
|
"\\w\\|\\s_\\|\\s\(\\|\\s\)\\|\\s\"\\|\\s|" |
2160 |
|
"\\w\\|\\s_\\|\\s\(\\|\\s\)\\|\\s\"")) |
2161 |
|
|
2162 |
|
(defconst c-jump-syntax-unbalanced |
2163 |
|
(if (memq 'gen-string-delim c-emacs-features) |
2164 |
|
"\\w\\|\\s_\\|\\s\"\\|\\s|" |
2165 |
|
"\\w\\|\\s_\\|\\s\"")) |
2166 |
|
|
2167 |
|
(defun c-forward-token-2 (&optional count balanced limit) |
2168 |
|
"Move forward by tokens. |
2169 |
|
A token is defined as all symbols and identifiers which aren't |
2170 |
|
syntactic whitespace \(note that multicharacter tokens like \"==\" are |
2171 |
|
treated properly). Point is always either left at the beginning of a |
2172 |
|
token or not moved at all. COUNT specifies the number of tokens to |
2173 |
|
move; a negative COUNT moves in the opposite direction. A COUNT of 0 |
2174 |
|
moves to the next token beginning only if not already at one. If |
2175 |
|
BALANCED is true, move over balanced parens, otherwise move into them. |
2176 |
|
Also, if BALANCED is true, never move out of an enclosing paren. |
2177 |
|
|
2178 |
|
LIMIT sets the limit for the movement and defaults to the point limit. |
2179 |
|
The case when LIMIT is set in the middle of a token, comment or macro |
2180 |
|
is handled correctly, i.e. the point won't be left there. |
2181 |
|
|
2182 |
|
Return the number of tokens left to move \(positive or negative). If |
2183 |
|
BALANCED is true, a move over a balanced paren counts as one. Note |
2184 |
|
that if COUNT is 0 and no appropriate token beginning is found, 1 will |
2185 |
|
be returned. Thus, a return value of 0 guarantees that point is at |
2186 |
|
the requested position and a return value less \(without signs) than |
2187 |
|
COUNT guarantees that point is at the beginning of some token." |
2188 |
|
|
2189 |
|
(or count (setq count 1)) |
2190 |
|
(if (< count 0) |
2191 |
|
(- (c-backward-token-2 (- count) balanced limit)) |
2192 |
|
|
2193 |
|
(let ((jump-syntax (if balanced |
2194 |
|
c-jump-syntax-balanced |
2195 |
|
c-jump-syntax-unbalanced)) |
2196 |
|
(last (point)) |
2197 |
|
(prev (point))) |
2198 |
|
|
2199 |
|
(if (zerop count) |
2200 |
|
;; If count is zero we should jump if in the middle of a token. |
2201 |
|
(c-end-of-current-token)) |
2202 |
|
|
2203 |
|
(save-restriction |
2204 |
|
(if limit (narrow-to-region (point-min) limit)) |
2205 |
|
(if (/= (point) |
2206 |
|
(progn (c-forward-syntactic-ws) (point))) |
2207 |
|
;; Skip whitespace. Count this as a move if we did in |
2208 |
|
;; fact move. |
2209 |
|
(setq count (max (1- count) 0))) |
2210 |
|
|
2211 |
|
(if (eobp) |
2212 |
|
;; Moved out of bounds. Make sure the returned count isn't zero. |
2213 |
|
(progn |
2214 |
|
(if (zerop count) (setq count 1)) |
2215 |
|
(goto-char last)) |
2216 |
|
|
2217 |
|
;; Use `condition-case' to avoid having the limit tests |
2218 |
|
;; inside the loop. |
2219 |
|
(condition-case nil |
2220 |
|
(while (and |
2221 |
|
(> count 0) |
2222 |
|
(progn |
2223 |
|
(setq last (point)) |
2224 |
|
(cond ((looking-at jump-syntax) |
2225 |
|
(goto-char (scan-sexps (point) 1)) |
2226 |
|
t) |
2227 |
|
((looking-at c-nonsymbol-token-regexp) |
2228 |
|
(goto-char (match-end 0)) |
2229 |
|
t) |
2230 |
|
;; `c-nonsymbol-token-regexp' above should always |
2231 |
|
;; match if there are correct tokens. Try to |
2232 |
|
;; widen to see if the limit was set in the |
2233 |
|
;; middle of one, else fall back to treating |
2234 |
|
;; the offending thing as a one character token. |
2235 |
|
((and limit |
2236 |
|
(save-restriction |
2237 |
|
(widen) |
2238 |
|
(looking-at c-nonsymbol-token-regexp))) |
2239 |
|
nil) |
2240 |
|
(t |
2241 |
|
(forward-char) |
2242 |
|
t)))) |
2243 |
|
(c-forward-syntactic-ws) |
2244 |
|
(setq prev last |
2245 |
|
count (1- count))) |
2246 |
|
(error (goto-char last))) |
2247 |
|
|
2248 |
|
(when (eobp) |
2249 |
|
(goto-char prev) |
2250 |
|
(setq count (1+ count))))) |
2251 |
|
|
2252 |
|
count))) |
2253 |
|
|
2254 |
|
(defun c-backward-token-2 (&optional count balanced limit) |
2255 |
|
"Move backward by tokens. |
2256 |
|
See `c-forward-token-2' for details." |
2257 |
|
|
2258 |
|
(or count (setq count 1)) |
2259 |
|
(if (< count 0) |
2260 |
|
(- (c-forward-token-2 (- count) balanced limit)) |
2261 |
|
|
2262 |
|
(or limit (setq limit (point-min))) |
2263 |
|
(let ((jump-syntax (if balanced |
2264 |
|
c-jump-syntax-balanced |
2265 |
|
c-jump-syntax-unbalanced)) |
2266 |
|
(last (point))) |
2267 |
|
|
2268 |
|
(if (zerop count) |
2269 |
|
;; The count is zero so try to skip to the beginning of the |
2270 |
|
;; current token. |
2271 |
|
(if (> (point) |
2272 |
|
(progn (c-beginning-of-current-token) (point))) |
2273 |
|
(if (< (point) limit) |
2274 |
|
;; The limit is inside the same token, so return 1. |
2275 |
|
(setq count 1)) |
2276 |
|
|
2277 |
|
;; We're not in the middle of a token. If there's |
2278 |
|
;; whitespace after the point then we must move backward, |
2279 |
|
;; so set count to 1 in that case. |
2280 |
|
(and (looking-at c-syntactic-ws-start) |
2281 |
|
;; If we're looking at a '#' that might start a cpp |
2282 |
|
;; directive then we have to do a more elaborate check. |
2283 |
|
(or (/= (char-after) ?#) |
2284 |
|
(not c-opt-cpp-prefix) |
2285 |
|
(save-excursion |
2286 |
|
(and (= (point) |
2287 |
|
(progn (beginning-of-line) |
2288 |
|
(looking-at "[ \t]*") |
2289 |
|
(match-end 0))) |
2290 |
|
(or (bobp) |
2291 |
|
(progn (backward-char) |
2292 |
|
(not (eq (char-before) ?\\))))))) |
2293 |
|
(setq count 1)))) |
2294 |
|
|
2295 |
|
;; Use `condition-case' to avoid having to check for buffer |
2296 |
|
;; limits in `backward-char', `scan-sexps' and `goto-char' below. |
2297 |
|
(condition-case nil |
2298 |
|
(while (and |
2299 |
|
(> count 0) |
2300 |
|
(progn |
2301 |
|
(c-backward-syntactic-ws) |
2302 |
|
(backward-char) |
2303 |
|
(if (looking-at jump-syntax) |
2304 |
|
(goto-char (scan-sexps (1+ (point)) -1)) |
2305 |
|
;; This can be very inefficient if there's a long |
2306 |
|
;; sequence of operator tokens without any separation. |
2307 |
|
;; That doesn't happen in practice, anyway. |
2308 |
|
(c-beginning-of-current-token)) |
2309 |
|
(>= (point) limit))) |
2310 |
|
(setq last (point) |
2311 |
|
count (1- count))) |
2312 |
|
(error (goto-char last))) |
2313 |
|
|
2314 |
|
(if (< (point) limit) |
2315 |
|
(goto-char last)) |
2316 |
|
|
2317 |
|
count))) |
2318 |
|
|
2319 |
|
(defun c-forward-token-1 (&optional count balanced limit) |
2320 |
|
"Like `c-forward-token-2' but doesn't treat multicharacter operator |
2321 |
|
tokens like \"==\" as single tokens, i.e. all sequences of symbol |
2322 |
|
characters are jumped over character by character. This function is |
2323 |
|
for compatibility only; it's only a wrapper over `c-forward-token-2'." |
2324 |
|
(let ((c-nonsymbol-token-regexp "\\s.\\|\\s\(\\|\\s\)")) |
2325 |
|
(c-forward-token-2 count balanced limit))) |
2326 |
|
|
2327 |
|
(defun c-backward-token-1 (&optional count balanced limit) |
2328 |
|
"Like `c-backward-token-2' but doesn't treat multicharacter operator |
2329 |
|
tokens like \"==\" as single tokens, i.e. all sequences of symbol |
2330 |
|
characters are jumped over character by character. This function is |
2331 |
|
for compatibility only; it's only a wrapper over `c-backward-token-2'." |
2332 |
|
(let ((c-nonsymbol-token-regexp "\\s.\\|\\s\(\\|\\s\)")) |
2333 |
|
(c-backward-token-2 count balanced limit))) |
2334 |
|
|
2335 |
|
|
2336 |
|
;; Tools for doing searches restricted to syntactically relevant text. |
2337 |
|
|
2338 |
|
(defun c-syntactic-re-search-forward (regexp &optional bound noerror |
2339 |
|
paren-level not-inside-token |
2340 |
|
lookbehind-submatch) |
2341 |
|
"Like `re-search-forward', but only report matches that are found |
2342 |
|
in syntactically significant text. I.e. matches in comments, macros |
2343 |
|
or string literals are ignored. The start point is assumed to be |
2344 |
|
outside any comment, macro or string literal, or else the content of |
2345 |
|
that region is taken as syntactically significant text. |
2346 |
|
|
2347 |
|
If PAREN-LEVEL is non-nil, an additional restriction is added to |
2348 |
|
ignore matches in nested paren sexps, and the search will also not go |
2349 |
|
outside the current paren sexp. |
2350 |
|
|
2351 |
|
If NOT-INSIDE-TOKEN is non-nil, matches in the middle of tokens are |
2352 |
|
ignored. Things like multicharacter operators and special symbols |
2353 |
|
\(e.g. \"`()\" in Pike) are handled but currently not floating point |
2354 |
|
constants. |
2355 |
|
|
2356 |
|
If LOOKBEHIND-SUBMATCH is non-nil, it's taken as a number of a |
2357 |
|
subexpression in REGEXP. The end of that submatch is used as the |
2358 |
|
position to check for syntactic significance. If LOOKBEHIND-SUBMATCH |
2359 |
|
isn't used or if that subexpression didn't match then the start |
2360 |
|
position of the whole match is used instead. The \"look behind\" |
2361 |
|
subexpression is never tested before the starting position, so it |
2362 |
|
might be a good idea to include \\=\\= as a match alternative in it. |
2363 |
|
|
2364 |
|
Optimization note: Matches might be missed if the \"look behind\" |
2365 |
|
subexpression should match the end of nonwhite syntactic whitespace, |
2366 |
|
i.e. the end of comments or cpp directives. This since the function |
2367 |
|
skips over such things before resuming the search. It's also not safe |
2368 |
|
to assume that the \"look behind\" subexpression never can match |
2369 |
|
syntactic whitespace." |
2370 |
|
|
2371 |
|
(or bound (setq bound (point-max))) |
2372 |
|
(if paren-level (setq paren-level -1)) |
2373 |
|
|
2374 |
|
;;(message "c-syntactic-re-search-forward %s %s %S" (point) bound regexp) |
2375 |
|
|
2376 |
|
(let ((start (point)) |
2377 |
|
(pos (point)) |
2378 |
|
(last-token-end-pos (point-min)) |
2379 |
|
match-pos found state check-pos check-state tmp) |
2380 |
|
|
2381 |
|
(condition-case err |
2382 |
|
(while |
2383 |
|
(and |
2384 |
|
(re-search-forward regexp bound noerror) |
2385 |
|
|
2386 |
|
(progn |
2387 |
|
(setq match-pos (point) |
2388 |
|
state (parse-partial-sexp |
2389 |
|
pos (match-beginning 0) paren-level nil state) |
2390 |
|
pos (point)) |
2391 |
|
(if (setq check-pos (and lookbehind-submatch |
2392 |
|
(match-end lookbehind-submatch))) |
2393 |
|
(setq check-state (parse-partial-sexp |
2394 |
|
pos check-pos paren-level nil state)) |
2395 |
|
(setq check-pos pos |
2396 |
|
check-state state)) |
2397 |
|
|
2398 |
|
;; If we got a look behind subexpression and get an |
2399 |
|
;; insignificant match in something that isn't |
2400 |
|
;; syntactic whitespace (i.e. strings or in nested |
2401 |
|
;; parentheses), then we can never skip more than a |
2402 |
|
;; single character from the match position before |
2403 |
|
;; continuing the search. That since the look behind |
2404 |
|
;; subexpression might match the end of the |
2405 |
|
;; insignificant region. |
2406 |
|
|
2407 |
|
(cond |
2408 |
|
((setq tmp (elt check-state 3)) |
2409 |
|
;; Match inside a string. |
2410 |
|
(if (or lookbehind-submatch |
2411 |
|
(not (integerp tmp))) |
2412 |
|
(goto-char (min (1+ pos) bound)) |
2413 |
|
;; Skip to the end of the string before continuing. |
2414 |
|
(let ((ender (make-string 1 tmp)) (continue t)) |
2415 |
|
(while (if (search-forward ender bound noerror) |
2416 |
|
(progn |
2417 |
|
(setq state (parse-partial-sexp |
2418 |
|
pos (point) nil nil state) |
2419 |
|
pos (point)) |
2420 |
|
(elt state 3)) |
2421 |
|
(setq continue nil))) |
2422 |
|
continue))) |
2423 |
|
|
2424 |
|
((elt check-state 7) |
2425 |
|
;; Match inside a line comment. Skip to eol. Use |
2426 |
|
;; `re-search-forward' instead of `skip-chars-forward' to get |
2427 |
|
;; the right bound behavior. |
2428 |
|
(re-search-forward "[\n\r]" bound noerror)) |
2429 |
|
|
2430 |
|
((elt check-state 4) |
2431 |
|
;; Match inside a block comment. Skip to the '*/'. |
2432 |
|
(search-forward "*/" bound noerror)) |
2433 |
|
|
2434 |
|
((and (not (elt check-state 5)) |
2435 |
|
(eq (char-before check-pos) ?/) |
2436 |
|
(memq (char-after check-pos) '(?/ ?*))) |
2437 |
|
;; Match in the middle of the opener of a block or line |
2438 |
|
;; comment. |
2439 |
|
(if (= (char-after check-pos) ?/) |
2440 |
|
(re-search-forward "[\n\r]" bound noerror) |
2441 |
|
(search-forward "*/" bound noerror))) |
2442 |
|
|
2443 |
|
((and not-inside-token |
2444 |
|
(or (< check-pos last-token-end-pos) |
2445 |
|
(< check-pos |
2446 |
|
(save-excursion |
2447 |
|
(goto-char check-pos) |
2448 |
|
(c-end-of-current-token last-token-end-pos) |
2449 |
|
(setq last-token-end-pos (point)))))) |
2450 |
|
;; Match inside a token. |
2451 |
|
(cond ((<= (point) bound) |
2452 |
|
(goto-char (min (1+ pos) bound)) |
2453 |
|
t) |
2454 |
|
(noerror nil) |
2455 |
|
(t (signal 'search-failed "end of token")))) |
2456 |
|
|
2457 |
|
((save-excursion |
2458 |
|
(save-match-data |
2459 |
|
(c-beginning-of-macro start))) |
2460 |
|
;; Match inside a macro. Skip to the end of it. |
2461 |
|
(c-end-of-macro) |
2462 |
|
(cond ((<= (point) bound) t) |
2463 |
|
(noerror nil) |
2464 |
|
(t (signal 'search-failed "end of macro")))) |
2465 |
|
|
2466 |
|
((and paren-level |
2467 |
|
(/= (setq tmp (car check-state)) 0)) |
2468 |
|
(if (> tmp 0) |
2469 |
|
;; Match inside a nested paren sexp. |
2470 |
|
(if lookbehind-submatch |
2471 |
|
(goto-char (min (1+ pos) bound)) |
2472 |
|
;; Skip out of the paren quickly. |
2473 |
|
(setq state (parse-partial-sexp pos bound 0 nil state) |
2474 |
|
pos (point))) |
2475 |
|
;; Have exited the current paren sexp. The |
2476 |
|
;; `parse-partial-sexp' above has left us just after the |
2477 |
|
;; closing paren in this case. Just make |
2478 |
|
;; `re-search-forward' above fail in the appropriate way; |
2479 |
|
;; we'll adjust the leave off point below if necessary. |
2480 |
|
(setq bound (point)))) |
2481 |
|
|
2482 |
|
(t |
2483 |
|
;; A real match. |
2484 |
|
(setq found t) |
2485 |
|
nil))))) |
2486 |
|
|
2487 |
|
(error |
2488 |
|
(goto-char start) |
2489 |
|
(signal (car err) (cdr err)))) |
2490 |
|
|
2491 |
|
;;(message "c-syntactic-re-search-forward done %s" (or match-pos (point))) |
2492 |
|
|
2493 |
|
(if found |
2494 |
|
(progn |
2495 |
|
(goto-char match-pos) |
2496 |
|
match-pos) |
2497 |
|
|
2498 |
|
;; Search failed. Set point as appropriate. |
2499 |
|
(cond ((eq noerror t) |
2500 |
|
(goto-char start)) |
2501 |
|
(paren-level |
2502 |
|
(if (eq (car (parse-partial-sexp pos bound -1 nil state)) -1) |
2503 |
|
(backward-char))) |
2504 |
|
(t |
2505 |
|
(goto-char bound))) |
2506 |
|
nil))) |
2507 |
|
|
2508 |
|
(defun c-syntactic-skip-backward (skip-chars &optional limit) |
2509 |
|
"Like `skip-chars-backward' but only look at syntactically relevant chars, |
2510 |
|
i.e. don't stop at positions inside syntactic whitespace or string |
2511 |
|
literals. Preprocessor directives are also ignored, with the exception |
2512 |
|
of the one that the point starts within, if any. If LIMIT is given, |
2513 |
|
it's assumed to be at a syntactically relevant position. |
2514 |
|
|
2515 |
|
This function does not do any hidden buffer changes." |
2516 |
|
|
2517 |
|
(let ((start (point)) |
2518 |
|
;; A list of syntactically relevant positions in descending |
2519 |
|
;; order. It's used to avoid scanning repeatedly over |
2520 |
|
;; potentially large regions with `parse-partial-sexp' to verify |
2521 |
|
;; each position. |
2522 |
|
safe-pos-list |
2523 |
|
;; The result from `c-beginning-of-macro' at the start position or the |
2524 |
|
;; start position itself if it isn't within a macro. Evaluated on |
2525 |
|
;; demand. |
2526 |
|
start-macro-beg) |
2527 |
|
|
2528 |
|
(while (progn |
2529 |
|
(while (and |
2530 |
|
(< (skip-chars-backward skip-chars limit) 0) |
2531 |
|
|
2532 |
|
;; Use `parse-partial-sexp' from a safe position down to |
2533 |
|
;; the point to check if it's outside comments and |
2534 |
|
;; strings. |
2535 |
|
(let ((pos (point)) safe-pos state) |
2536 |
|
;; Pick a safe position as close to the point as |
2537 |
|
;; possible. |
2538 |
|
;; |
2539 |
|
;; FIXME: Consult `syntax-ppss' here if our |
2540 |
|
;; cache doesn't give a good position. |
2541 |
|
(while (and safe-pos-list |
2542 |
|
(> (car safe-pos-list) (point))) |
2543 |
|
(setq safe-pos-list (cdr safe-pos-list))) |
2544 |
|
(unless (setq safe-pos (car-safe safe-pos-list)) |
2545 |
|
(setq safe-pos (max (or (c-safe-position |
2546 |
|
(point) (or c-state-cache |
2547 |
|
(c-parse-state))) |
2548 |
|
0) |
2549 |
|
(point-min)) |
2550 |
|
safe-pos-list (list safe-pos))) |
2551 |
|
|
2552 |
|
(while (progn |
2553 |
|
(setq state (parse-partial-sexp |
2554 |
|
safe-pos pos 0)) |
2555 |
|
(< (point) pos)) |
2556 |
|
;; Cache positions along the way to use if we have to |
2557 |
|
;; back up more. Every closing paren on the same |
2558 |
|
;; level seems like fairly well spaced positions. |
2559 |
|
(setq safe-pos (point) |
2560 |
|
safe-pos-list (cons safe-pos safe-pos-list))) |
2561 |
|
|
2562 |
|
(cond |
2563 |
|
((or (elt state 3) (elt state 4)) |
2564 |
|
;; Inside string or comment. Continue search at the |
2565 |
|
;; beginning of it. |
2566 |
|
(if (setq pos (nth 8 state)) |
2567 |
|
;; It's an emacs where `parse-partial-sexp' |
2568 |
|
;; supplies the starting position. |
2569 |
|
(goto-char pos) |
2570 |
|
(goto-char (car (c-literal-limits safe-pos)))) |
2571 |
|
t) |
2572 |
|
|
2573 |
|
((c-beginning-of-macro limit) |
2574 |
|
;; Inside a macro. |
2575 |
|
(if (< (point) |
2576 |
|
(or start-macro-beg |
2577 |
|
(setq start-macro-beg |
2578 |
|
(save-excursion |
2579 |
|
(goto-char start) |
2580 |
|
(c-beginning-of-macro limit) |
2581 |
|
(point))))) |
2582 |
|
t |
2583 |
|
;; It's inside the same macro we started in so it's |
2584 |
|
;; a relevant match. |
2585 |
|
(goto-char pos) |
2586 |
|
nil)))))) |
2587 |
|
|
2588 |
|
(> (point) |
2589 |
|
(progn |
2590 |
|
;; Skip syntactic ws afterwards so that we don't stop at the |
2591 |
|
;; end of a comment if `skip-chars' is something like "^/". |
2592 |
|
(c-backward-syntactic-ws) |
2593 |
|
(point))))) |
2594 |
|
|
2595 |
|
(- (point) start))) |
2596 |
|
|
2597 |
|
|
2598 |
|
;; Tools for handling comments and string literals. |
2599 |
|
|
2600 |
|
(defun c-slow-in-literal (&optional lim detect-cpp) |
2601 |
|
"Return the type of literal point is in, if any. |
2602 |
|
The return value is `c' if in a C-style comment, `c++' if in a C++ |
2603 |
|
style comment, `string' if in a string literal, `pound' if DETECT-CPP |
2604 |
|
is non-nil and in a preprocessor line, or nil if somewhere else. |
2605 |
|
Optional LIM is used as the backward limit of the search. If omitted, |
2606 |
|
or nil, `c-beginning-of-defun' is used. |
2607 |
|
|
2608 |
|
The last point calculated is cached if the cache is enabled, i.e. if |
2609 |
|
`c-in-literal-cache' is bound to a two element vector. |
2610 |
|
|
2611 |
|
This function does not do any hidden buffer changes." |
2612 |
|
(if (and (vectorp c-in-literal-cache) |
2613 |
|
(= (point) (aref c-in-literal-cache 0))) |
2614 |
|
(aref c-in-literal-cache 1) |
2615 |
|
(let ((rtn (save-excursion |
2616 |
|
(let* ((pos (point)) |
2617 |
|
(lim (or lim (progn |
2618 |
|
(c-beginning-of-syntax) |
2619 |
|
(point)))) |
2620 |
|
(state (parse-partial-sexp lim pos))) |
2621 |
|
(cond |
2622 |
|
((elt state 3) 'string) |
2623 |
|
((elt state 4) (if (elt state 7) 'c++ 'c)) |
2624 |
|
((and detect-cpp (c-beginning-of-macro lim)) 'pound) |
2625 |
|
(t nil)))))) |
2626 |
|
;; cache this result if the cache is enabled |
2627 |
|
(if (not c-in-literal-cache) |
2628 |
|
(setq c-in-literal-cache (vector (point) rtn))) |
2629 |
|
rtn))) |
2630 |
|
|
2631 |
|
;; XEmacs has a built-in function that should make this much quicker. |
2632 |
|
;; I don't think we even need the cache, which makes our lives more |
2633 |
|
;; complicated anyway. In this case, lim is only used to detect |
2634 |
|
;; cpp directives. |
2635 |
|
;; |
2636 |
|
;; Note that there is a bug in Xemacs's buffer-syntactic-context when used in |
2637 |
|
;; conjunction with syntax-table-properties. The bug is present in, e.g., |
2638 |
|
;; Xemacs 21.4.4. It manifested itself thus: |
2639 |
|
;; |
2640 |
|
;; Starting with an empty AWK Mode buffer, type |
2641 |
|
;; /regexp/ {<C-j> |
2642 |
|
;; Point gets wrongly left at column 0, rather than being indented to tab-width. |
2643 |
|
;; |
2644 |
|
;; AWK Mode is designed such that when the first / is typed, it gets the |
2645 |
|
;; syntax-table property "string fence". When the second / is typed, BOTH /s |
2646 |
|
;; are given the s-t property "string". However, buffer-syntactic-context |
2647 |
|
;; fails to take account of the change of the s-t property on the opening / to |
2648 |
|
;; "string", and reports that the { is within a string started by the second /. |
2649 |
|
;; |
2650 |
|
;; The workaround for this is for the AWK Mode initialisation to switch the |
2651 |
|
;; defalias for c-in-literal to c-slow-in-literal. This will slow down other |
2652 |
|
;; cc-modes in Xemacs whenever an awk-buffer has been initialised. |
2653 |
|
;; |
2654 |
|
;; (Alan Mackenzie, 2003/4/30). |
2655 |
|
|
2656 |
|
(defun c-fast-in-literal (&optional lim detect-cpp) |
2657 |
|
(let ((context (buffer-syntactic-context))) |
2658 |
|
(cond |
2659 |
|
((eq context 'string) 'string) |
2660 |
|
((eq context 'comment) 'c++) |
2661 |
|
((eq context 'block-comment) 'c) |
2662 |
|
((and detect-cpp (save-excursion (c-beginning-of-macro lim))) 'pound)))) |
2663 |
|
|
2664 |
|
(defalias 'c-in-literal |
2665 |
|
(if (fboundp 'buffer-syntactic-context) |
2666 |
|
'c-fast-in-literal ; Xemacs |
2667 |
|
'c-slow-in-literal)) ; GNU Emacs |
2668 |
|
|
2669 |
|
;; The defalias above isn't enough to shut up the byte compiler. |
2670 |
|
(cc-bytecomp-defun c-in-literal) |
2671 |
|
|
2672 |
|
(defun c-literal-limits (&optional lim near not-in-delimiter) |
2673 |
|
"Return a cons of the beginning and end positions of the comment or |
2674 |
|
string surrounding point (including both delimiters), or nil if point |
2675 |
|
isn't in one. If LIM is non-nil, it's used as the \"safe\" position |
2676 |
|
to start parsing from. If NEAR is non-nil, then the limits of any |
2677 |
|
literal next to point is returned. \"Next to\" means there's only |
2678 |
|
spaces and tabs between point and the literal. The search for such a |
2679 |
|
literal is done first in forward direction. If NOT-IN-DELIMITER is |
2680 |
|
non-nil, the case when point is inside a starting delimiter won't be |
2681 |
|
recognized. This only has effect for comments, which have starting |
2682 |
|
delimiters with more than one character. |
2683 |
|
|
2684 |
|
This function does not do any hidden buffer changes." |
2685 |
|
|
2686 |
|
(save-excursion |
2687 |
|
(let* ((pos (point)) |
2688 |
|
(lim (or lim (progn |
2689 |
|
(c-beginning-of-syntax) |
2690 |
|
(point)))) |
2691 |
|
(state (parse-partial-sexp lim pos))) |
2692 |
|
|
2693 |
|
(cond ((elt state 3) |
2694 |
|
;; String. Search backward for the start. |
2695 |
|
(while (elt state 3) |
2696 |
|
(search-backward (make-string 1 (elt state 3))) |
2697 |
|
(setq state (parse-partial-sexp lim (point)))) |
2698 |
|
(cons (point) (or (c-safe (c-forward-sexp 1) (point)) |
2699 |
|
(point-max)))) |
2700 |
|
|
2701 |
|
((elt state 7) |
2702 |
|
;; Line comment. Search from bol for the comment starter. |
2703 |
|
(beginning-of-line) |
2704 |
|
(setq state (parse-partial-sexp lim (point)) |
2705 |
|
lim (point)) |
2706 |
|
(while (not (elt state 7)) |
2707 |
|
(search-forward "//") ; Should never fail. |
2708 |
|
(setq state (parse-partial-sexp |
2709 |
|
lim (point) nil nil state) |
2710 |
|
lim (point))) |
2711 |
|
(backward-char 2) |
2712 |
|
(cons (point) (progn (c-forward-single-comment) (point)))) |
2713 |
|
|
2714 |
|
((elt state 4) |
2715 |
|
;; Block comment. Search backward for the comment starter. |
2716 |
|
(while (elt state 4) |
2717 |
|
(search-backward "/*") ; Should never fail. |
2718 |
|
(setq state (parse-partial-sexp lim (point)))) |
2719 |
|
(cons (point) (progn (c-forward-single-comment) (point)))) |
2720 |
|
|
2721 |
|
((and (not not-in-delimiter) |
2722 |
|
(not (elt state 5)) |
2723 |
|
(eq (char-before) ?/) |
2724 |
|
(looking-at "[/*]")) |
2725 |
|
;; We're standing in a comment starter. |
2726 |
|
(backward-char 1) |
2727 |
|
(cons (point) (progn (c-forward-single-comment) (point)))) |
2728 |
|
|
2729 |
|
(near |
2730 |
|
(goto-char pos) |
2731 |
|
|
2732 |
|
;; Search forward for a literal. |
2733 |
|
(skip-chars-forward " \t") |
2734 |
|
|
2735 |
|
(cond |
2736 |
|
((looking-at c-string-limit-regexp) ; String. |
2737 |
|
(cons (point) (or (c-safe (c-forward-sexp 1) (point)) |
2738 |
|
(point-max)))) |
2739 |
|
|
2740 |
|
((looking-at c-comment-start-regexp) ; Line or block comment. |
2741 |
|
(cons (point) (progn (c-forward-single-comment) (point)))) |
2742 |
|
|
2743 |
|
(t |
2744 |
|
;; Search backward. |
2745 |
|
(skip-chars-backward " \t") |
2746 |
|
|
2747 |
|
(let ((end (point)) beg) |
2748 |
|
(cond |
2749 |
|
((save-excursion |
2750 |
|
(< (skip-syntax-backward c-string-syntax) 0)) ; String. |
2751 |
|
(setq beg (c-safe (c-backward-sexp 1) (point)))) |
2752 |
|
|
2753 |
|
((and (c-safe (forward-char -2) t) |
2754 |
|
(looking-at "*/")) |
2755 |
|
;; Block comment. Due to the nature of line |
2756 |
|
;; comments, they will always be covered by the |
2757 |
|
;; normal case above. |
2758 |
|
(goto-char end) |
2759 |
|
(c-backward-single-comment) |
2760 |
|
;; If LIM is bogus, beg will be bogus. |
2761 |
|
(setq beg (point)))) |
2762 |
|
|
2763 |
|
(if beg (cons beg end)))))) |
2764 |
|
)))) |
2765 |
|
|
2766 |
|
(defun c-literal-limits-fast (&optional lim near not-in-delimiter) |
2767 |
|
;; Like c-literal-limits, but for emacsen whose `parse-partial-sexp' |
2768 |
|
;; returns the pos of the comment start. |
2769 |
|
|
2770 |
|
"Return a cons of the beginning and end positions of the comment or |
2771 |
|
string surrounding point (including both delimiters), or nil if point |
2772 |
|
isn't in one. If LIM is non-nil, it's used as the \"safe\" position |
2773 |
|
to start parsing from. If NEAR is non-nil, then the limits of any |
2774 |
|
literal next to point is returned. \"Next to\" means there's only |
2775 |
|
spaces and tabs between point and the literal. The search for such a |
2776 |
|
literal is done first in forward direction. If NOT-IN-DELIMITER is |
2777 |
|
non-nil, the case when point is inside a starting delimiter won't be |
2778 |
|
recognized. This only has effect for comments, which have starting |
2779 |
|
delimiters with more than one character. |
2780 |
|
|
2781 |
|
This function does not do any hidden buffer changes." |
2782 |
|
|
2783 |
|
(save-excursion |
2784 |
|
(let* ((pos (point)) |
2785 |
|
(lim (or lim (progn |
2786 |
|
(c-beginning-of-syntax) |
2787 |
|
(point)))) |
2788 |
|
(state (parse-partial-sexp lim pos))) |
2789 |
|
|
2790 |
|
(cond ((elt state 3) ; String. |
2791 |
|
(goto-char (elt state 8)) |
2792 |
|
(cons (point) (or (c-safe (c-forward-sexp 1) (point)) |
2793 |
|
(point-max)))) |
2794 |
|
|
2795 |
|
((elt state 4) ; Comment. |
2796 |
|
(goto-char (elt state 8)) |
2797 |
|
(cons (point) (progn (c-forward-single-comment) (point)))) |
2798 |
|
|
2799 |
|
((and (not not-in-delimiter) |
2800 |
|
(not (elt state 5)) |
2801 |
|
(eq (char-before) ?/) |
2802 |
|
(looking-at "[/*]")) |
2803 |
|
;; We're standing in a comment starter. |
2804 |
|
(backward-char 1) |
2805 |
|
(cons (point) (progn (c-forward-single-comment) (point)))) |
2806 |
|
|
2807 |
|
(near |
2808 |
|
(goto-char pos) |
2809 |
|
|
2810 |
|
;; Search forward for a literal. |
2811 |
|
(skip-chars-forward " \t") |
2812 |
|
|
2813 |
|
(cond |
2814 |
|
((looking-at c-string-limit-regexp) ; String. |
2815 |
|
(cons (point) (or (c-safe (c-forward-sexp 1) (point)) |
2816 |
|
(point-max)))) |
2817 |
|
|
2818 |
|
((looking-at c-comment-start-regexp) ; Line or block comment. |
2819 |
|
(cons (point) (progn (c-forward-single-comment) (point)))) |
2820 |
|
|
2821 |
|
(t |
2822 |
|
;; Search backward. |
2823 |
|
(skip-chars-backward " \t") |
2824 |
|
|
2825 |
|
(let ((end (point)) beg) |
2826 |
|
(cond |
2827 |
|
((save-excursion |
2828 |
|
(< (skip-syntax-backward c-string-syntax) 0)) ; String. |
2829 |
|
(setq beg (c-safe (c-backward-sexp 1) (point)))) |
2830 |
|
|
2831 |
|
((and (c-safe (forward-char -2) t) |
2832 |
|
(looking-at "*/")) |
2833 |
|
;; Block comment. Due to the nature of line |
2834 |
|
;; comments, they will always be covered by the |
2835 |
|
;; normal case above. |
2836 |
|
(goto-char end) |
2837 |
|
(c-backward-single-comment) |
2838 |
|
;; If LIM is bogus, beg will be bogus. |
2839 |
|
(setq beg (point)))) |
2840 |
|
|
2841 |
|
(if beg (cons beg end)))))) |
2842 |
|
)))) |
2843 |
|
|
2844 |
|
(if (memq 'pps-extended-state c-emacs-features) |
2845 |
|
(defalias 'c-literal-limits 'c-literal-limits-fast)) |
2846 |
|
|
2847 |
|
(defun c-collect-line-comments (range) |
2848 |
|
"If the argument is a cons of two buffer positions (such as returned by |
2849 |
|
`c-literal-limits'), and that range contains a C++ style line comment, |
2850 |
|
then an extended range is returned that contains all adjacent line |
2851 |
|
comments (i.e. all comments that starts in the same column with no |
2852 |
|
empty lines or non-whitespace characters between them). Otherwise the |
2853 |
|
argument is returned. |
2854 |
|
|
2855 |
|
This function does not do any hidden buffer changes." |
2856 |
|
(save-excursion |
2857 |
|
(condition-case nil |
2858 |
|
(if (and (consp range) (progn |
2859 |
|
(goto-char (car range)) |
2860 |
|
(looking-at "//"))) |
2861 |
|
(let ((col (current-column)) |
2862 |
|
(beg (point)) |
2863 |
|
(bopl (c-point 'bopl)) |
2864 |
|
(end (cdr range))) |
2865 |
|
;; Got to take care in the backward direction to handle |
2866 |
|
;; comments which are preceded by code. |
2867 |
|
(while (and (c-backward-single-comment) |
2868 |
|
(>= (point) bopl) |
2869 |
|
(looking-at "//") |
2870 |
|
(= col (current-column))) |
2871 |
|
(setq beg (point) |
2872 |
|
bopl (c-point 'bopl))) |
2873 |
|
(goto-char end) |
2874 |
|
(while (and (progn (skip-chars-forward " \t") |
2875 |
|
(looking-at "//")) |
2876 |
|
(= col (current-column)) |
2877 |
|
(prog1 (zerop (forward-line 1)) |
2878 |
|
(setq end (point))))) |
2879 |
|
(cons beg end)) |
2880 |
|
range) |
2881 |
|
(error range)))) |
2882 |
|
|
2883 |
|
(defun c-literal-type (range) |
2884 |
|
"Convenience function that given the result of `c-literal-limits', |
2885 |
|
returns nil or the type of literal that the range surrounds. It's |
2886 |
|
much faster than using `c-in-literal' and is intended to be used when |
2887 |
|
you need both the type of a literal and its limits. |
2888 |
|
|
2889 |
|
This function does not do any hidden buffer changes." |
2890 |
|
(if (consp range) |
2891 |
|
(save-excursion |
2892 |
|
(goto-char (car range)) |
2893 |
|
(cond ((looking-at c-string-limit-regexp) 'string) |
2894 |
|
((or (looking-at "//") ; c++ line comment |
2895 |
|
(and (looking-at "\\s<") ; comment starter |
2896 |
|
(looking-at "#"))) ; awk comment. |
2897 |
|
'c++) |
2898 |
|
(t 'c))) ; Assuming the range is valid. |
2899 |
|
range)) |
2900 |
|
|
2901 |
|
|
2902 |
|
;; `c-find-decl-spots' and accompanying stuff. |
2903 |
|
|
2904 |
|
;; Variables used in `c-find-decl-spots' to cache the search done for |
2905 |
|
;; the first declaration in the last call. When that function starts, |
2906 |
|
;; it needs to back up over syntactic whitespace to look at the last |
2907 |
|
;; token before the region being searched. That can sometimes cause |
2908 |
|
;; moves back and forth over a quite large region of comments and |
2909 |
|
;; macros, which would be repeated for each changed character when |
2910 |
|
;; we're called during fontification, since font-lock refontifies the |
2911 |
|
;; current line for each change. Thus it's worthwhile to cache the |
2912 |
|
;; first match. |
2913 |
|
;; |
2914 |
|
;; `c-find-decl-syntactic-pos' is a syntactically relevant position in |
2915 |
|
;; the syntactic whitespace less or equal to some start position. |
2916 |
|
;; There's no cached value if it's nil. |
2917 |
|
;; |
2918 |
|
;; `c-find-decl-match-pos' is the match position if |
2919 |
|
;; `c-find-decl-prefix-search' matched before the syntactic whitespace |
2920 |
|
;; at `c-find-decl-syntactic-pos', or nil if there's no such match. |
2921 |
|
(defvar c-find-decl-syntactic-pos nil) |
2922 |
|
(make-variable-buffer-local 'c-find-decl-syntactic-pos) |
2923 |
|
(defvar c-find-decl-match-pos nil) |
2924 |
|
(make-variable-buffer-local 'c-find-decl-match-pos) |
2925 |
|
|
2926 |
|
(defsubst c-invalidate-find-decl-cache (change-min-pos) |
2927 |
|
(and c-find-decl-syntactic-pos |
2928 |
|
(< change-min-pos c-find-decl-syntactic-pos) |
2929 |
|
(setq c-find-decl-syntactic-pos nil))) |
2930 |
|
|
2931 |
|
; (defface c-debug-decl-spot-face |
2932 |
|
; '((t (:background "Turquoise"))) |
2933 |
|
; "Debug face to mark the spots where `c-find-decl-spots' stopped.") |
2934 |
|
; (defface c-debug-decl-sws-face |
2935 |
|
; '((t (:background "Khaki"))) |
2936 |
|
; "Debug face to mark the syntactic whitespace between the declaration |
2937 |
|
; spots and the preceding token end.") |
2938 |
|
|
2939 |
|
(defmacro c-debug-put-decl-spot-faces (match-pos decl-pos) |
2940 |
|
(when (facep 'c-debug-decl-spot-face) |
2941 |
|
`(let ((match-pos ,match-pos) (decl-pos ,decl-pos)) |
2942 |
|
(c-debug-add-face (max match-pos (point-min)) decl-pos |
2943 |
|
'c-debug-decl-sws-face) |
2944 |
|
(c-debug-add-face decl-pos (min (1+ decl-pos) (point-max)) |
2945 |
|
'c-debug-decl-spot-face)))) |
2946 |
|
(defmacro c-debug-remove-decl-spot-faces (beg end) |
2947 |
|
(when (facep 'c-debug-decl-spot-face) |
2948 |
|
`(progn |
2949 |
|
(c-debug-remove-face ,beg ,end 'c-debug-decl-spot-face) |
2950 |
|
(c-debug-remove-face ,beg ,end 'c-debug-decl-sws-face)))) |
2951 |
|
|
2952 |
|
(defmacro c-find-decl-prefix-search () |
2953 |
|
;; Macro used inside `c-find-decl-spots'. It ought to be a defun, |
2954 |
|
;; but it contains lots of free variables that refer to things |
2955 |
|
;; inside `c-find-decl-spots'. The point is left at `cfd-match-pos' |
2956 |
|
;; if there is a match, otherwise at `cfd-limit'. |
2957 |
|
|
2958 |
|
'(progn |
2959 |
|
;; Find the next property match position if we haven't got one already. |
2960 |
|
(unless cfd-prop-match |
2961 |
|
(save-excursion |
2962 |
|
(while (progn |
2963 |
|
(goto-char (next-single-property-change |
2964 |
|
(point) 'c-type nil cfd-limit)) |
2965 |
|
(and (< (point) cfd-limit) |
2966 |
|
(not (eq (c-get-char-property (1- (point)) 'c-type) |
2967 |
|
'c-decl-end))))) |
2968 |
|
(setq cfd-prop-match (point)))) |
2969 |
|
|
2970 |
|
;; Find the next `c-decl-prefix-re' match if we haven't got one already. |
2971 |
|
(unless cfd-re-match |
2972 |
|
(while (and (setq cfd-re-match |
2973 |
|
(re-search-forward c-decl-prefix-re cfd-limit 'move)) |
2974 |
|
(c-got-face-at (1- (setq cfd-re-match (match-end 1))) |
2975 |
|
c-literal-faces)) |
2976 |
|
;; Search again if the match is within a comment or a string literal. |
2977 |
|
(while (progn |
2978 |
|
(goto-char (next-single-property-change |
2979 |
|
cfd-re-match 'face nil cfd-limit)) |
2980 |
|
(and (< (point) cfd-limit) |
2981 |
|
(c-got-face-at (point) c-literal-faces))) |
2982 |
|
(setq cfd-re-match (point)))) |
2983 |
|
(unless cfd-re-match |
2984 |
|
(setq cfd-re-match cfd-limit))) |
2985 |
|
|
2986 |
|
;; Choose whichever match is closer to the start. |
2987 |
|
(if (< cfd-re-match cfd-prop-match) |
2988 |
|
(setq cfd-match-pos cfd-re-match |
2989 |
|
cfd-re-match nil) |
2990 |
|
(setq cfd-match-pos cfd-prop-match |
2991 |
|
cfd-prop-match nil)) |
2992 |
|
|
2993 |
|
(goto-char cfd-match-pos) |
2994 |
|
|
2995 |
|
(when (< cfd-match-pos cfd-limit) |
2996 |
|
;; Skip forward past comments only so we don't skip macros. |
2997 |
|
(c-forward-comments) |
2998 |
|
;; Set the position to continue at. We can avoid going over |
2999 |
|
;; the comments skipped above a second time, but it's possible |
3000 |
|
;; that the comment skipping has taken us past `cfd-prop-match' |
3001 |
|
;; since the property might be used inside comments. |
3002 |
|
(setq cfd-continue-pos (if cfd-prop-match |
3003 |
|
(min cfd-prop-match (point)) |
3004 |
|
(point)))))) |
3005 |
|
|
3006 |
|
(defun c-find-decl-spots (cfd-limit cfd-decl-re cfd-face-checklist cfd-fun) |
3007 |
|
;; Call CFD-FUN for each possible spot for a declaration from the |
3008 |
|
;; point to CFD-LIMIT. A spot for a declaration is the first token |
3009 |
|
;; in the buffer and each token after the ones matched by |
3010 |
|
;; `c-decl-prefix-re' and after the occurrences of the `c-type' |
3011 |
|
;; property with the value `c-decl-end' (if `c-type-decl-end-used' |
3012 |
|
;; is set). Only a spot that match CFD-DECL-RE and whose face is in |
3013 |
|
;; the CFD-FACE-CHECKLIST list causes CFD-FUN to be called. The |
3014 |
|
;; face check is disabled if CFD-FACE-CHECKLIST is nil. |
3015 |
|
;; |
3016 |
|
;; If the match is inside a macro then the buffer is narrowed to the |
3017 |
|
;; end of it, so that CFD-FUN can investigate the following tokens |
3018 |
|
;; without matching something that begins inside a macro and ends |
3019 |
|
;; outside it. It's to avoid this work that the CFD-DECL-RE and |
3020 |
|
;; CFD-FACE-CHECKLIST checks exist. |
3021 |
|
;; |
3022 |
|
;; CFD-FUN is called with point at the start of the spot. It's |
3023 |
|
;; passed two arguments: The first is the end position of the token |
3024 |
|
;; that `c-decl-prefix-re' matched, or 0 for the implicit match at |
3025 |
|
;; bob. The second is a flag that is t when the match is inside a |
3026 |
|
;; macro. |
3027 |
|
;; |
3028 |
|
;; It's assumed that comment and strings are fontified in the |
3029 |
|
;; searched range. |
3030 |
|
;; |
3031 |
|
;; This is mainly used in fontification, and so has an elaborate |
3032 |
|
;; cache to handle repeated calls from the same start position; see |
3033 |
|
;; the variables above. |
3034 |
|
;; |
3035 |
|
;; All variables in this function begin with `cfd-' to avoid name |
3036 |
|
;; collision with the (dynamically bound) variables used in CFD-FUN. |
3037 |
|
|
3038 |
|
(let ((cfd-buffer-end (point-max)) |
3039 |
|
;; The last regexp match found by `c-find-decl-prefix-search'. |
3040 |
|
cfd-re-match |
3041 |
|
;; The last `c-decl-end' found by `c-find-decl-prefix-search'. |
3042 |
|
;; If searching for the property isn't needed then we disable |
3043 |
|
;; it by faking a first match at the limit. |
3044 |
|
(cfd-prop-match (unless c-type-decl-end-used cfd-limit)) |
3045 |
|
;; The position of the last match found by |
3046 |
|
;; `c-find-decl-prefix-search'. For regexp matches it's the |
3047 |
|
;; end of the matched token, for property matches it's the end |
3048 |
|
;; of the property. 0 for the implicit match at bob. |
3049 |
|
;; `cfd-limit' if there's no match. |
3050 |
|
(cfd-match-pos cfd-limit) |
3051 |
|
;; The position to continue searching at. |
3052 |
|
cfd-continue-pos |
3053 |
|
;; The position of the last "real" token we've stopped at. |
3054 |
|
;; This can be greater than `cfd-continue-pos' when we get |
3055 |
|
;; hits inside macros or at `c-decl-end' positions inside |
3056 |
|
;; comments. |
3057 |
|
(cfd-token-pos 0) |
3058 |
|
;; The end position of the last entered macro. |
3059 |
|
(cfd-macro-end 0)) |
3060 |
|
|
3061 |
|
;; Initialize by finding a syntactically relevant start position |
3062 |
|
;; before the point, and do the first `c-decl-prefix-re' search |
3063 |
|
;; unless we're at bob. |
3064 |
|
|
3065 |
|
(let ((start-pos (point)) syntactic-pos) |
3066 |
|
;; Must back up a bit since we look for the end of the previous |
3067 |
|
;; statement or declaration, which is earlier than the first |
3068 |
|
;; returned match. |
3069 |
|
|
3070 |
|
(when (c-got-face-at (point) c-literal-faces) |
3071 |
|
;; But first we need to move to a syntactically relevant |
3072 |
|
;; position. Use the faces to back up to the start of the |
3073 |
|
;; comment or string literal. |
3074 |
|
(when (and (not (bobp)) |
3075 |
|
(c-got-face-at (1- (point)) c-literal-faces)) |
3076 |
|
(while (progn |
3077 |
|
(goto-char (previous-single-property-change |
3078 |
|
(point) 'face nil (point-min))) |
3079 |
|
(and (> (point) (point-min)) |
3080 |
|
(c-got-face-at (point) c-literal-faces))))) |
3081 |
|
|
3082 |
|
;; XEmacs doesn't fontify the quotes surrounding string |
3083 |
|
;; literals. |
3084 |
|
(and (featurep 'xemacs) |
3085 |
|
(eq (get-text-property (point) 'face) |
3086 |
|
'font-lock-string-face) |
3087 |
|
(not (bobp)) |
3088 |
|
(progn (backward-char) |
3089 |
|
(not (looking-at c-string-limit-regexp))) |
3090 |
|
(forward-char)) |
3091 |
|
|
3092 |
|
;; The font lock package might not have fontified the start of |
3093 |
|
;; the literal at all so check that we have arrived at |
3094 |
|
;; something that looks like a start or else resort to |
3095 |
|
;; `c-literal-limits'. |
3096 |
|
(unless (looking-at c-literal-start-regexp) |
3097 |
|
(let ((range (c-literal-limits))) |
3098 |
|
(if range (goto-char (car range)))))) |
3099 |
|
|
3100 |
|
;; Must back out of any macro so that we don't miss any |
3101 |
|
;; declaration that could follow after it, unless the limit is |
3102 |
|
;; inside the macro. We only check that for the current line to |
3103 |
|
;; save some time; it's enough for the by far most common case |
3104 |
|
;; when font-lock refontifies the current line only. |
3105 |
|
(when (save-excursion |
3106 |
|
(and (= (forward-line 1) 0) |
3107 |
|
(or (< (c-point 'eol) cfd-limit) |
3108 |
|
(progn (backward-char) |
3109 |
|
(not (eq (char-before) ?\\)))))) |
3110 |
|
(c-beginning-of-macro)) |
3111 |
|
|
3112 |
|
;; Clear the cache if it applied further down. |
3113 |
|
(c-invalidate-find-decl-cache start-pos) |
3114 |
|
|
3115 |
|
(setq syntactic-pos (point)) |
3116 |
|
(c-backward-syntactic-ws c-find-decl-syntactic-pos) |
3117 |
|
|
3118 |
|
;; If we hit `c-find-decl-syntactic-pos' and |
3119 |
|
;; `c-find-decl-match-pos' is set then we install the cached |
3120 |
|
;; values. If we hit `c-find-decl-syntactic-pos' and |
3121 |
|
;; `c-find-decl-match-pos' is nil then we know there's no decl |
3122 |
|
;; prefix in the whitespace before `c-find-decl-syntactic-pos' |
3123 |
|
;; and so we can continue the search from this point. If we |
3124 |
|
;; didn't hit `c-find-decl-syntactic-pos' then we're now in the |
3125 |
|
;; right spot to begin searching anyway. |
3126 |
|
(if (and (eq (point) c-find-decl-syntactic-pos) |
3127 |
|
c-find-decl-match-pos) |
3128 |
|
|
3129 |
|
(progn |
3130 |
|
;; The match is always outside macros and comments so we |
3131 |
|
;; start at the next token. The loop below will later go |
3132 |
|
;; back using `cfd-continue-pos' to fix declarations inside |
3133 |
|
;; the syntactic ws. |
3134 |
|
(goto-char syntactic-pos) |
3135 |
|
(c-forward-syntactic-ws) |
3136 |
|
(setq cfd-match-pos c-find-decl-match-pos |
3137 |
|
cfd-continue-pos syntactic-pos) |
3138 |
|
(if (< cfd-continue-pos (point)) |
3139 |
|
(setq cfd-token-pos (point)))) |
3140 |
|
|
3141 |
|
(setq c-find-decl-syntactic-pos syntactic-pos) |
3142 |
|
|
3143 |
|
(when (if (bobp) |
3144 |
|
;; Always consider bob a match to get the first declaration |
3145 |
|
;; in the file. Do this separately instead of letting |
3146 |
|
;; `c-decl-prefix-re' match bob, so that it always can |
3147 |
|
;; consume at least one character to ensure that we won't |
3148 |
|
;; get stuck in an infinite loop. |
3149 |
|
(setq cfd-re-match 0) |
3150 |
|
(backward-char) |
3151 |
|
(c-beginning-of-current-token) |
3152 |
|
(< (point) cfd-limit)) |
3153 |
|
;; Do an initial search now. In the bob case above it's only done |
3154 |
|
;; to search for the `c-type' property. |
3155 |
|
(c-find-decl-prefix-search)) |
3156 |
|
|
3157 |
|
;; Advance `cfd-continue-pos' if we got a hit before the start |
3158 |
|
;; position. The earliest position that could affect after |
3159 |
|
;; the start position is the char before the preceding |
3160 |
|
;; comments. |
3161 |
|
(when (and cfd-continue-pos (< cfd-continue-pos start-pos)) |
3162 |
|
(goto-char syntactic-pos) |
3163 |
|
(c-backward-comments) |
3164 |
|
(unless (bobp) |
3165 |
|
(backward-char) |
3166 |
|
(c-beginning-of-current-token)) |
3167 |
|
(setq cfd-continue-pos (max cfd-continue-pos (point)))) |
3168 |
|
|
3169 |
|
;; If we got a match it's always outside macros and comments so |
3170 |
|
;; advance to the next token and set `cfd-token-pos'. The loop |
3171 |
|
;; below will later go back using `cfd-continue-pos' to fix |
3172 |
|
;; declarations inside the syntactic ws. |
3173 |
|
(when (and (< cfd-match-pos cfd-limit) (< (point) syntactic-pos)) |
3174 |
|
(goto-char syntactic-pos) |
3175 |
|
(c-forward-syntactic-ws) |
3176 |
|
(and cfd-continue-pos |
3177 |
|
(< cfd-continue-pos (point)) |
3178 |
|
(setq cfd-token-pos (point)))) |
3179 |
|
|
3180 |
|
(setq c-find-decl-match-pos (and (< cfd-match-pos start-pos) |
3181 |
|
cfd-match-pos)))) |
3182 |
|
|
3183 |
|
;; Now loop. We already got the first match. |
3184 |
|
|
3185 |
|
(while (progn |
3186 |
|
(while (and |
3187 |
|
(< cfd-match-pos cfd-limit) |
3188 |
|
|
3189 |
|
(or |
3190 |
|
;; Kludge to filter out matches on the "<" that |
3191 |
|
;; aren't open parens, for the sake of languages |
3192 |
|
;; that got `c-recognize-<>-arglists' set. |
3193 |
|
(and (eq (char-before cfd-match-pos) ?<) |
3194 |
|
(not (c-get-char-property (1- cfd-match-pos) |
3195 |
|
'syntax-table))) |
3196 |
|
|
3197 |
|
;; If `cfd-continue-pos' is less or equal to |
3198 |
|
;; `cfd-token-pos', we've got a hit inside a macro |
3199 |
|
;; that's in the syntactic whitespace before the last |
3200 |
|
;; "real" declaration we've checked. If they're equal |
3201 |
|
;; we've arrived at the declaration a second time, so |
3202 |
|
;; there's nothing to do. |
3203 |
|
(= cfd-continue-pos cfd-token-pos) |
3204 |
|
|
3205 |
|
(progn |
3206 |
|
;; If `cfd-continue-pos' is less than `cfd-token-pos' |
3207 |
|
;; we're still searching for declarations embedded in |
3208 |
|
;; the syntactic whitespace. In that case we need |
3209 |
|
;; only to skip comments and not macros, since they |
3210 |
|
;; can't be nested, and that's already been done in |
3211 |
|
;; `c-find-decl-prefix-search'. |
3212 |
|
(when (> cfd-continue-pos cfd-token-pos) |
3213 |
|
(c-forward-syntactic-ws) |
3214 |
|
(setq cfd-token-pos (point))) |
3215 |
|
|
3216 |
|
;; Continue if the following token fails the |
3217 |
|
;; CFD-DECL-RE and CFD-FACE-CHECKLIST checks. |
3218 |
|
(when (or (>= (point) cfd-limit) |
3219 |
|
(not (looking-at cfd-decl-re)) |
3220 |
|
(and cfd-face-checklist |
3221 |
|
(not (c-got-face-at |
3222 |
|
(point) cfd-face-checklist)))) |
3223 |
|
(goto-char cfd-continue-pos) |
3224 |
|
t))) |
3225 |
|
|
3226 |
|
(< (point) cfd-limit)) |
3227 |
|
(c-find-decl-prefix-search)) |
3228 |
|
|
3229 |
|
(< (point) cfd-limit)) |
3230 |
|
|
3231 |
|
(when (progn |
3232 |
|
;; Narrow to the end of the macro if we got a hit inside |
3233 |
|
;; one, to avoid recognizing things that start inside |
3234 |
|
;; the macro and end outside it. |
3235 |
|
(when (> cfd-match-pos cfd-macro-end) |
3236 |
|
;; Not in the same macro as in the previous round. |
3237 |
|
(save-excursion |
3238 |
|
(goto-char cfd-match-pos) |
3239 |
|
(setq cfd-macro-end |
3240 |
|
(if (save-excursion (and (c-beginning-of-macro) |
3241 |
|
(< (point) cfd-match-pos))) |
3242 |
|
(progn (c-end-of-macro) |
3243 |
|
(point)) |
3244 |
|
0)))) |
3245 |
|
|
3246 |
|
(if (zerop cfd-macro-end) |
3247 |
|
t |
3248 |
|
(if (> cfd-macro-end (point)) |
3249 |
|
(progn (narrow-to-region (point-min) cfd-macro-end) |
3250 |
|
t) |
3251 |
|
;; The matched token was the last thing in the |
3252 |
|
;; macro, so the whole match is bogus. |
3253 |
|
(setq cfd-macro-end 0) |
3254 |
|
nil))) |
3255 |
|
|
3256 |
|
(c-debug-put-decl-spot-faces cfd-match-pos (point)) |
3257 |
|
(funcall cfd-fun cfd-match-pos (/= cfd-macro-end 0)) |
3258 |
|
|
3259 |
|
(when (/= cfd-macro-end 0) |
3260 |
|
;; Restore limits if we did macro narrowment above. |
3261 |
|
(narrow-to-region (point-min) cfd-buffer-end))) |
3262 |
|
|
3263 |
|
(goto-char cfd-continue-pos) |
3264 |
|
(if (= cfd-continue-pos cfd-limit) |
3265 |
|
(setq cfd-match-pos cfd-limit) |
3266 |
|
(c-find-decl-prefix-search))))) |
3267 |
|
|
3268 |
|
|
3269 |
|
;; A cache for found types. |
3270 |
|
|
3271 |
|
;; Buffer local variable that contains an obarray with the types we've |
3272 |
|
;; found. If a declaration is recognized somewhere we record the |
3273 |
|
;; fully qualified identifier in it to recognize it as a type |
3274 |
|
;; elsewhere in the file too. This is not accurate since we do not |
3275 |
|
;; bother with the scoping rules of the languages, but in practice the |
3276 |
|
;; same name is seldom used as both a type and something else in a |
3277 |
|
;; file, and we only use this as a last resort in ambiguous cases (see |
3278 |
|
;; `c-font-lock-declarations'). |
3279 |
|
(defvar c-found-types nil) |
3280 |
|
(make-variable-buffer-local 'c-found-types) |
3281 |
|
|
3282 |
|
(defsubst c-clear-found-types () |
3283 |
|
;; Clears `c-found-types'. |
3284 |
|
;; |
3285 |
|
;; This function does not do any hidden buffer changes. |
3286 |
|
(setq c-found-types (make-vector 53 0))) |
3287 |
|
|
3288 |
|
(defun c-add-type (from to) |
3289 |
|
;; Add the given region as a type in `c-found-types'. If the region |
3290 |
|
;; doesn't match an existing type but there is a type which is equal |
3291 |
|
;; to the given one except that the last character is missing, then |
3292 |
|
;; the shorter type is removed. That's done to avoid adding all |
3293 |
|
;; prefixes of a type as it's being entered and font locked. This |
3294 |
|
;; doesn't cover cases like when characters are removed from a type |
3295 |
|
;; or added in the middle. We'd need the position of point when the |
3296 |
|
;; font locking is invoked to solve this well. |
3297 |
|
(unless (and c-recognize-<>-arglists |
3298 |
|
(save-excursion |
3299 |
|
(goto-char from) |
3300 |
|
(c-syntactic-re-search-forward "<" to t))) |
3301 |
|
;; To avoid storing very long strings, do not add a type that |
3302 |
|
;; contains '<' in languages with angle bracket arglists, since |
3303 |
|
;; the type then probably contains a C++ template spec and those |
3304 |
|
;; can be fairly sized programs in themselves. |
3305 |
|
(let ((type (c-syntactic-content from to))) |
3306 |
|
(unless (intern-soft type c-found-types) |
3307 |
|
(unintern (substring type 0 -1) c-found-types) |
3308 |
|
(intern type c-found-types))))) |
3309 |
|
|
3310 |
|
(defsubst c-check-type (from to) |
3311 |
|
;; Return non-nil if the given region contains a type in |
3312 |
|
;; `c-found-types'. |
3313 |
|
(intern-soft (c-syntactic-content from to) c-found-types)) |
3314 |
|
|
3315 |
|
(defun c-list-found-types () |
3316 |
|
;; Return all the types in `c-found-types' as a sorted list of |
3317 |
|
;; strings. |
3318 |
|
(let (type-list) |
3319 |
|
(mapatoms (lambda (type) |
3320 |
|
(setq type-list (cons (symbol-name type) |
3321 |
|
type-list))) |
3322 |
|
c-found-types) |
3323 |
|
(sort type-list 'string-lessp))) |
3324 |
|
|
3325 |
|
|
3326 |
|
;; Handling of small scale constructs like types and names. |
3327 |
|
|
3328 |
|
(defun c-remove-<>-arglist-properties (from to) |
3329 |
|
;; Remove all the properties put by `c-forward-<>-arglist' in the |
3330 |
|
;; specified region. Point is clobbered. |
3331 |
|
(goto-char from) |
3332 |
|
(while (progn (skip-chars-forward "^<>," to) |
3333 |
|
(< (point) to)) |
3334 |
|
(if (eq (char-after) ?,) |
3335 |
|
(when (eq (c-get-char-property (point) 'c-type) 'c-<>-arg-sep) |
3336 |
|
(c-clear-char-property (point) 'c-type)) |
3337 |
|
(c-clear-char-property (point) 'syntax-table)) |
3338 |
|
(forward-char))) |
3339 |
|
|
3340 |
|
;; Dynamically bound variable that instructs `c-forward-type' to also |
3341 |
|
;; treat possible types (i.e. those that it normally returns 'maybe or |
3342 |
|
;; 'found for) as actual types (and always return 'found for them). |
3343 |
|
;; This means that it records them in `c-record-type-identifiers' if |
3344 |
|
;; that is set, and that it adds them to `c-found-types'. |
3345 |
|
(defvar c-promote-possible-types nil) |
3346 |
|
|
3347 |
|
;; Dynamically bound variable that instructs `c-forward-<>-arglist' to |
3348 |
|
;; not accept arglists that contain more than one argument. It's used |
3349 |
|
;; to handle ambiguous cases like "foo (a < b, c > d)" better. |
3350 |
|
(defvar c-disallow-comma-in-<>-arglists nil) |
3351 |
|
|
3352 |
|
;; Dynamically bound variables that instructs `c-forward-name', |
3353 |
|
;; `c-forward-type' and `c-forward-<>-arglist' to record the ranges of |
3354 |
|
;; all the type and reference identifiers they encounter. They will |
3355 |
|
;; build lists on these variables where each element is a cons of the |
3356 |
|
;; buffer positions surrounding each identifier. This recording is |
3357 |
|
;; only activated when `c-record-type-identifiers' is non-nil. |
3358 |
|
;; |
3359 |
|
;; All known types that can't be identifiers are recorded, and also |
3360 |
|
;; other possible types if `c-promote-possible-types' is set. |
3361 |
|
;; Recording is however disabled inside angle bracket arglists that |
3362 |
|
;; are encountered inside names and other angle bracket arglists. |
3363 |
|
;; Such occurences are taken care of by `c-font-lock-<>-arglists' |
3364 |
|
;; instead. |
3365 |
|
;; |
3366 |
|
;; Only the names in C++ template style references (e.g. "tmpl" in |
3367 |
|
;; "tmpl<a,b>::foo") are recorded as references, other references |
3368 |
|
;; aren't handled here. |
3369 |
|
(defvar c-record-type-identifiers nil) |
3370 |
|
(defvar c-record-ref-identifiers nil) |
3371 |
|
|
3372 |
|
;; If `c-record-type-identifiers' is set, this will receive a cons |
3373 |
|
;; cell of the range of the last single identifier symbol stepped over |
3374 |
|
;; by `c-forward-name' if it's successful. This is the range that |
3375 |
|
;; should be put on one of the record lists by the caller. It's |
3376 |
|
;; assigned nil if there's no such symbol in the name. |
3377 |
|
(defvar c-last-identifier-range nil) |
3378 |
|
|
3379 |
|
(defmacro c-record-type-id (range) |
3380 |
|
(if (eq (car-safe range) 'cons) |
3381 |
|
;; Always true. |
3382 |
|
`(setq c-record-type-identifiers |
3383 |
|
(cons ,range c-record-type-identifiers)) |
3384 |
|
`(let ((range ,range)) |
3385 |
|
(if range |
3386 |
|
(setq c-record-type-identifiers |
3387 |
|
(cons range c-record-type-identifiers)))))) |
3388 |
|
|
3389 |
|
(defmacro c-record-ref-id (range) |
3390 |
|
(if (eq (car-safe range) 'cons) |
3391 |
|
;; Always true. |
3392 |
|
`(setq c-record-ref-identifiers |
3393 |
|
(cons ,range c-record-ref-identifiers)) |
3394 |
|
`(let ((range ,range)) |
3395 |
|
(if range |
3396 |
|
(setq c-record-ref-identifiers |
3397 |
|
(cons range c-record-ref-identifiers)))))) |
3398 |
|
|
3399 |
|
;; Dynamically bound variable that instructs `c-forward-type' to |
3400 |
|
;; record the ranges of types that only are found. Behaves otherwise |
3401 |
|
;; like `c-record-type-identifiers'. |
3402 |
|
(defvar c-record-found-types nil) |
3403 |
|
|
3404 |
|
(defmacro c-forward-keyword-prefixed-id (type) |
3405 |
|
;; Used internally in `c-forward-keyword-clause' to move forward |
3406 |
|
;; over a type (if TYPE is 'type) or a name (otherwise) which |
3407 |
|
;; possibly is prefixed by keywords and their associated clauses. |
3408 |
|
;; Try with a type/name first to not trip up on those that begin |
3409 |
|
;; with a keyword. Return t if a known or found type is moved |
3410 |
|
;; over. The point is clobbered if nil is returned. If range |
3411 |
|
;; recording is enabled, the identifier is recorded on as a type |
3412 |
|
;; if TYPE is 'type or as a reference if TYPE is 'ref. |
3413 |
|
`(let (res) |
3414 |
|
(while (if (setq res ,(if (eq type 'type) |
3415 |
|
`(c-forward-type) |
3416 |
|
`(c-forward-name))) |
3417 |
|
nil |
3418 |
|
(and (looking-at c-keywords-regexp) |
3419 |
|
(c-forward-keyword-clause)))) |
3420 |
|
(when (memq res '(t known found prefix)) |
3421 |
|
,(when (eq type 'ref) |
3422 |
|
`(when c-record-type-identifiers |
3423 |
|
(c-record-ref-id c-last-identifier-range))) |
3424 |
|
t))) |
3425 |
|
|
3426 |
|
(defmacro c-forward-id-comma-list (type) |
3427 |
|
;; Used internally in `c-forward-keyword-clause' to move forward |
3428 |
|
;; over a comma separated list of types or names using |
3429 |
|
;; `c-forward-keyword-prefixed-id'. |
3430 |
|
`(while (and (progn |
3431 |
|
(setq safe-pos (point)) |
3432 |
|
(eq (char-after) ?,)) |
3433 |
|
(progn |
3434 |
|
(forward-char) |
3435 |
|
(c-forward-syntactic-ws) |
3436 |
|
(c-forward-keyword-prefixed-id ,type))))) |
3437 |
|
|
3438 |
|
(defun c-forward-keyword-clause () |
3439 |
|
;; The first submatch in the current match data is assumed to |
3440 |
|
;; surround a token. If it's a keyword, move over it and any |
3441 |
|
;; following clauses associated with it, stopping at the next |
3442 |
|
;; following token. t is returned in that case, otherwise the point |
3443 |
|
;; stays and nil is returned. The kind of clauses that are |
3444 |
|
;; recognized are those specified by `c-type-list-kwds', |
3445 |
|
;; `c-ref-list-kwds', `c-colon-type-list-kwds', |
3446 |
|
;; `c-paren-nontype-kwds', `c-paren-type-kwds', `c-<>-type-kwds', |
3447 |
|
;; and `c-<>-arglist-kwds'. |
3448 |
|
|
3449 |
|
(let ((kwd-sym (c-keyword-sym (match-string 1))) safe-pos pos) |
3450 |
|
(when kwd-sym |
3451 |
|
(goto-char (match-end 1)) |
3452 |
|
(c-forward-syntactic-ws) |
3453 |
|
(setq safe-pos (point)) |
3454 |
|
|
3455 |
|
(cond |
3456 |
|
((and (c-keyword-member kwd-sym 'c-type-list-kwds) |
3457 |
|
(c-forward-keyword-prefixed-id type)) |
3458 |
|
;; There's a type directly after a keyword in `c-type-list-kwds'. |
3459 |
|
(c-forward-id-comma-list type)) |
3460 |
|
|
3461 |
|
((and (c-keyword-member kwd-sym 'c-ref-list-kwds) |
3462 |
|
(c-forward-keyword-prefixed-id ref)) |
3463 |
|
;; There's a name directly after a keyword in `c-ref-list-kwds'. |
3464 |
|
(c-forward-id-comma-list ref)) |
3465 |
|
|
3466 |
|
((and (c-keyword-member kwd-sym 'c-paren-any-kwds) |
3467 |
|
(eq (char-after) ?\()) |
3468 |
|
;; There's an open paren after a keyword in `c-paren-any-kwds'. |
3469 |
|
|
3470 |
|
(forward-char) |
3471 |
|
(when (and (setq pos (c-up-list-forward)) |
3472 |
|
(eq (char-before pos) ?\))) |
3473 |
|
(when (and c-record-type-identifiers |
3474 |
|
(c-keyword-member kwd-sym 'c-paren-type-kwds)) |
3475 |
|
;; Use `c-forward-type' on every identifier we can find |
3476 |
|
;; inside the paren, to record the types. |
3477 |
|
(while (c-syntactic-re-search-forward c-symbol-start pos t) |
3478 |
|
(goto-char (match-beginning 0)) |
3479 |
|
(unless (c-forward-type) |
3480 |
|
(looking-at c-symbol-key) ; Always matches. |
3481 |
|
(goto-char (match-end 0))))) |
3482 |
|
|
3483 |
|
(goto-char pos) |
3484 |
|
(c-forward-syntactic-ws) |
3485 |
|
(setq safe-pos (point)))) |
3486 |
|
|
3487 |
|
((and (c-keyword-member kwd-sym 'c-<>-sexp-kwds) |
3488 |
|
(eq (char-after) ?<) |
3489 |
|
(c-forward-<>-arglist (c-keyword-member kwd-sym 'c-<>-type-kwds) |
3490 |
|
(or c-record-type-identifiers |
3491 |
|
c-disallow-comma-in-<>-arglists))) |
3492 |
|
(c-forward-syntactic-ws) |
3493 |
|
(setq safe-pos (point))) |
3494 |
|
|
3495 |
|
((and (c-keyword-member kwd-sym 'c-nonsymbol-sexp-kwds) |
3496 |
|
(not (looking-at c-symbol-start))) |
3497 |
|
(c-forward-sexp) |
3498 |
|
(c-forward-syntactic-ws) |
3499 |
|
(setq safe-pos (point)))) |
3500 |
|
|
3501 |
|
(when (and (c-keyword-member kwd-sym 'c-colon-type-list-kwds) |
3502 |
|
(progn |
3503 |
|
;; If a keyword matched both one of the types above and |
3504 |
|
;; this one, we match `c-colon-type-list-re' after the |
3505 |
|
;; clause matched above. |
3506 |
|
(goto-char safe-pos) |
3507 |
|
(looking-at c-colon-type-list-re)) |
3508 |
|
(progn |
3509 |
|
(goto-char (match-end 0)) |
3510 |
|
(c-forward-syntactic-ws) |
3511 |
|
(c-forward-keyword-prefixed-id type))) |
3512 |
|
;; There's a type after the `c-colon-type-list-re' |
3513 |
|
;; match after a keyword in `c-colon-type-list-kwds'. |
3514 |
|
(c-forward-id-comma-list type)) |
3515 |
|
|
3516 |
|
(goto-char safe-pos) |
3517 |
|
t))) |
3518 |
|
|
3519 |
|
(defun c-forward-<>-arglist (all-types reparse) |
3520 |
|
;; The point is assumed to be at a '<'. Try to treat it as the open |
3521 |
|
;; paren of an angle bracket arglist and move forward to the the |
3522 |
|
;; corresponding '>'. If successful, the point is left after the |
3523 |
|
;; '>' and t is returned, otherwise the point isn't moved and nil is |
3524 |
|
;; returned. If ALL-TYPES is t then all encountered arguments in |
3525 |
|
;; the arglist that might be types are treated as found types. |
3526 |
|
;; |
3527 |
|
;; The surrounding '<' and '>' are given syntax-table properties to |
3528 |
|
;; make them behave like parentheses. Each argument separating ',' |
3529 |
|
;; is also set to `c-<>-arg-sep' in the `c-type' property. These |
3530 |
|
;; properties are also cleared in a relevant region forward from the |
3531 |
|
;; point if they seems to be set and it turns out to not be an |
3532 |
|
;; arglist. |
3533 |
|
;; |
3534 |
|
;; If the arglist has been successfully parsed before then paren |
3535 |
|
;; syntax properties will be exploited to quickly jump to the end, |
3536 |
|
;; but that can be disabled by setting REPARSE to t. That is |
3537 |
|
;; necessary if the various side effects, e.g. recording of type |
3538 |
|
;; ranges, are important. Setting REPARSE to t only applies |
3539 |
|
;; recursively to nested angle bracket arglists if |
3540 |
|
;; `c-disallow-comma-in-<>-arglists' is set. |
3541 |
|
;; |
3542 |
|
;; This is primarily used in C++ to mark up template arglists. C++ |
3543 |
|
;; disambiguates them by checking whether the preceding name is a |
3544 |
|
;; template or not. We can't do that, so we assume it is a template |
3545 |
|
;; if it can be parsed as one. This usually works well since |
3546 |
|
;; comparison expressions on the forms "a < b > c" or "a < b, c > d" |
3547 |
|
;; in almost all cases would be pointless. Cases like function |
3548 |
|
;; calls on the form "foo (a < b, c > d)" needs to be handled |
3549 |
|
;; specially through the `c-disallow-comma-in-<>-arglists' variable. |
3550 |
|
|
3551 |
|
(let ((start (point)) |
3552 |
|
;; If `c-record-type-identifiers' is set then activate |
3553 |
|
;; recording of any found types that constitute an argument in |
3554 |
|
;; the arglist. |
3555 |
|
(c-record-found-types (if c-record-type-identifiers t))) |
3556 |
|
(if (catch 'angle-bracket-arglist-escape |
3557 |
|
(setq c-record-found-types |
3558 |
|
(c-forward-<>-arglist-recur all-types reparse))) |
3559 |
|
(progn |
3560 |
|
(when (consp c-record-found-types) |
3561 |
|
(setq c-record-type-identifiers |
3562 |
|
;; `nconc' doesn't mind that the tail of |
3563 |
|
;; `c-record-found-types' is t. |
3564 |
|
(nconc c-record-found-types c-record-type-identifiers))) |
3565 |
|
t) |
3566 |
|
|
3567 |
|
(goto-char start) |
3568 |
|
nil))) |
3569 |
|
|
3570 |
|
(defun c-forward-<>-arglist-recur (all-types reparse) |
3571 |
|
;; Recursive part of `c-forward-<>-arglist'. |
3572 |
|
|
3573 |
|
(let ((start (point)) res pos tmp |
3574 |
|
;; Cover this so that any recorded found type ranges are |
3575 |
|
;; automatically lost if it turns out to not be an angle |
3576 |
|
;; bracket arglist. It's propagated through the return value |
3577 |
|
;; on successful completion. |
3578 |
|
(c-record-found-types c-record-found-types) |
3579 |
|
;; List that collects the positions after the argument |
3580 |
|
;; separating ',' in the arglist. |
3581 |
|
arg-start-pos) |
3582 |
|
|
3583 |
|
;; If the '<' has paren open syntax then we've marked it as an |
3584 |
|
;; angle bracket arglist before, so try to skip to the end and see |
3585 |
|
;; that the close paren matches. |
3586 |
|
(if (and (c-get-char-property (point) 'syntax-table) |
3587 |
|
(progn |
3588 |
|
(forward-char) |
3589 |
|
(if (and (not (looking-at c-<-op-cont-regexp)) |
3590 |
|
(if (c-parse-sexp-lookup-properties) |
3591 |
|
(c-go-up-list-forward) |
3592 |
|
(catch 'at-end |
3593 |
|
(let ((depth 1)) |
3594 |
|
(while (c-syntactic-re-search-forward |
3595 |
|
"[<>]" nil t t) |
3596 |
|
(when (c-get-char-property (1- (point)) |
3597 |
|
'syntax-table) |
3598 |
|
(if (eq (char-before) ?<) |
3599 |
|
(setq depth (1+ depth)) |
3600 |
|
(setq depth (1- depth)) |
3601 |
|
(when (= depth 0) (throw 'at-end t))))) |
3602 |
|
nil))) |
3603 |
|
(not (looking-at c->-op-cont-regexp)) |
3604 |
|
(save-excursion |
3605 |
|
(backward-char) |
3606 |
|
(= (point) |
3607 |
|
(progn (c-beginning-of-current-token) |
3608 |
|
(point))))) |
3609 |
|
|
3610 |
|
;; Got an arglist that appears to be valid. |
3611 |
|
(if reparse |
3612 |
|
;; Reparsing is requested, so zap the properties in the |
3613 |
|
;; region and go on to redo it. It's done here to |
3614 |
|
;; avoid leaving it behind if we exit through |
3615 |
|
;; `angle-bracket-arglist-escape' below. |
3616 |
|
(progn |
3617 |
|
(c-remove-<>-arglist-properties start (point)) |
3618 |
|
(goto-char start) |
3619 |
|
nil) |
3620 |
|
t) |
3621 |
|
|
3622 |
|
;; Got unmatched paren brackets or either paren was |
3623 |
|
;; actually some other token. Recover by clearing the |
3624 |
|
;; syntax properties on all the '<' and '>' in the |
3625 |
|
;; range where we'll search for the arglist below. |
3626 |
|
(goto-char start) |
3627 |
|
(while (progn (skip-chars-forward "^<>,;{}") |
3628 |
|
(looking-at "[<>,]")) |
3629 |
|
(if (eq (char-after) ?,) |
3630 |
|
(when (eq (c-get-char-property (point) 'c-type) |
3631 |
|
'c-<>-arg-sep) |
3632 |
|
(c-clear-char-property (point) 'c-type)) |
3633 |
|
(c-clear-char-property (point) 'syntax-table)) |
3634 |
|
(forward-char)) |
3635 |
|
(goto-char start) |
3636 |
|
nil))) |
3637 |
|
t |
3638 |
|
|
3639 |
|
(forward-char) |
3640 |
|
(unless (looking-at c-<-op-cont-regexp) |
3641 |
|
(while (and |
3642 |
|
(progn |
3643 |
|
|
3644 |
|
(when c-record-type-identifiers |
3645 |
|
(if all-types |
3646 |
|
|
3647 |
|
;; All encountered identifiers are types, so set the |
3648 |
|
;; promote flag and parse the type. |
3649 |
|
(progn |
3650 |
|
(c-forward-syntactic-ws) |
3651 |
|
(when (looking-at c-identifier-start) |
3652 |
|
(let ((c-promote-possible-types t)) |
3653 |
|
(c-forward-type)))) |
3654 |
|
|
3655 |
|
;; Check if this arglist argument is a sole type. If |
3656 |
|
;; it's known then it's recorded in |
3657 |
|
;; `c-record-type-identifiers'. If it only is found |
3658 |
|
;; then it's recorded in `c-record-found-types' which we |
3659 |
|
;; might roll back if it turns out that this isn't an |
3660 |
|
;; angle bracket arglist afterall. |
3661 |
|
(when (memq (char-before) '(?, ?<)) |
3662 |
|
(let ((orig-record-found-types c-record-found-types)) |
3663 |
|
(c-forward-syntactic-ws) |
3664 |
|
(and (memq (c-forward-type) '(known found)) |
3665 |
|
(not (looking-at "[,>]")) |
3666 |
|
;; A found type was recorded but it's not the |
3667 |
|
;; only thing in the arglist argument, so reset |
3668 |
|
;; `c-record-found-types'. |
3669 |
|
(setq c-record-found-types |
3670 |
|
orig-record-found-types)))))) |
3671 |
|
|
3672 |
|
(setq pos (point)) |
3673 |
|
(or (when (eq (char-after) ?>) |
3674 |
|
;; Must check for '>' at the very start separately, |
3675 |
|
;; since the regexp below has to avoid ">>" without |
3676 |
|
;; using \\=. |
3677 |
|
(forward-char) |
3678 |
|
t) |
3679 |
|
|
3680 |
|
;; Note: This regexp exploits the match order in |
3681 |
|
;; \| so that "<>" is matched by "<" rather than |
3682 |
|
;; "[^>:-]>". |
3683 |
|
(c-syntactic-re-search-forward |
3684 |
|
"[<;{},]\\|\\([^>:-]>\\)" nil 'move t t 1) |
3685 |
|
|
3686 |
|
;; If the arglist starter has lost its open paren |
3687 |
|
;; syntax but not the closer, we won't find the |
3688 |
|
;; closer above since we only search in the |
3689 |
|
;; balanced sexp. In that case we stop just short |
3690 |
|
;; of it so check if the following char is the closer. |
3691 |
|
(when (eq (char-after) ?>) |
3692 |
|
;; Remove its syntax so that we don't enter the |
3693 |
|
;; recovery code below. That's not necessary |
3694 |
|
;; since there's no real reason to suspect that |
3695 |
|
;; things inside the arglist are unbalanced. |
3696 |
|
(c-clear-char-property (point) 'syntax-table) |
3697 |
|
(forward-char) |
3698 |
|
t))) |
3699 |
|
|
3700 |
|
(cond |
3701 |
|
((eq (char-before) ?>) |
3702 |
|
;; Either an operator starting with '>' or the end of |
3703 |
|
;; the angle bracket arglist. |
3704 |
|
|
3705 |
|
(if (and (/= (1- (point)) pos) |
3706 |
|
(c-get-char-property (1- (point)) 'syntax-table) |
3707 |
|
(progn |
3708 |
|
(c-clear-char-property (1- (point)) 'syntax-table) |
3709 |
|
(c-parse-sexp-lookup-properties))) |
3710 |
|
|
3711 |
|
;; We've skipped past a list that ended with '>'. It |
3712 |
|
;; must be unbalanced since nested arglists are handled |
3713 |
|
;; in the case below. Recover by removing all paren |
3714 |
|
;; properties on '<' and '>' in the searched region and |
3715 |
|
;; redo the search. |
3716 |
|
(progn |
3717 |
|
(c-remove-<>-arglist-properties pos (point)) |
3718 |
|
(goto-char pos) |
3719 |
|
t) |
3720 |
|
|
3721 |
|
(if (looking-at c->-op-cont-regexp) |
3722 |
|
(progn |
3723 |
|
(when (text-property-not-all |
3724 |
|
(1- (point)) (match-end 0) 'syntax-table nil) |
3725 |
|
(c-remove-<>-arglist-properties (1- (point)) |
3726 |
|
(match-end 0))) |
3727 |
|
(goto-char (match-end 0)) |
3728 |
|
t) |
3729 |
|
|
3730 |
|
;; The angle bracket arglist is finished. |
3731 |
|
(while arg-start-pos |
3732 |
|
(c-put-char-property (1- (car arg-start-pos)) |
3733 |
|
'c-type 'c-<>-arg-sep) |
3734 |
|
(setq arg-start-pos (cdr arg-start-pos))) |
3735 |
|
(c-mark-<-as-paren start) |
3736 |
|
(c-mark->-as-paren (1- (point))) |
3737 |
|
(setq res t) |
3738 |
|
nil))) |
3739 |
|
|
3740 |
|
((eq (char-before) ?<) |
3741 |
|
;; Either an operator starting with '<' or a nested arglist. |
3742 |
|
|
3743 |
|
(setq pos (point)) |
3744 |
|
(let (id-start id-end subres keyword-match) |
3745 |
|
(if (if (looking-at c-<-op-cont-regexp) |
3746 |
|
(setq tmp (match-end 0)) |
3747 |
|
(setq tmp pos) |
3748 |
|
(backward-char) |
3749 |
|
(not |
3750 |
|
(and |
3751 |
|
|
3752 |
|
(save-excursion |
3753 |
|
;; There's always an identifier before a angle |
3754 |
|
;; bracket arglist, or a keyword in |
3755 |
|
;; `c-<>-type-kwds' or `c-<>-arglist-kwds'. |
3756 |
|
(c-backward-syntactic-ws) |
3757 |
|
(setq id-end (point)) |
3758 |
|
(c-simple-skip-symbol-backward) |
3759 |
|
(when (or (setq keyword-match |
3760 |
|
(looking-at c-opt-<>-sexp-key)) |
3761 |
|
(not (looking-at c-keywords-regexp))) |
3762 |
|
(setq id-start (point)))) |
3763 |
|
|
3764 |
|
(setq subres |
3765 |
|
(let ((c-record-type-identifiers nil) |
3766 |
|
(c-record-found-types nil)) |
3767 |
|
(c-forward-<>-arglist-recur |
3768 |
|
(and keyword-match |
3769 |
|
(c-keyword-member |
3770 |
|
(c-keyword-sym (match-string 1)) |
3771 |
|
'c-<>-type-kwds)) |
3772 |
|
(and reparse |
3773 |
|
c-disallow-comma-in-<>-arglists)))) |
3774 |
|
))) |
3775 |
|
|
3776 |
|
;; It was not an angle bracket arglist. |
3777 |
|
(progn |
3778 |
|
(when (text-property-not-all |
3779 |
|
(1- pos) tmp 'syntax-table nil) |
3780 |
|
(if (c-parse-sexp-lookup-properties) |
3781 |
|
;; Got an invalid open paren syntax on this |
3782 |
|
;; '<'. We'll probably get an unbalanced '>' |
3783 |
|
;; further ahead if we just remove the syntax |
3784 |
|
;; here, so recover by removing all paren |
3785 |
|
;; properties up to and including the |
3786 |
|
;; balancing close paren. |
3787 |
|
(parse-partial-sexp pos (point-max) -1) |
3788 |
|
(goto-char tmp)) |
3789 |
|
(c-remove-<>-arglist-properties pos (point))) |
3790 |
|
(goto-char tmp)) |
3791 |
|
|
3792 |
|
;; It was an angle bracket arglist. |
3793 |
|
(setq c-record-found-types subres) |
3794 |
|
|
3795 |
|
;; Record the identifier before the template as a type |
3796 |
|
;; or reference depending on whether the arglist is last |
3797 |
|
;; in a qualified identifier. |
3798 |
|
(when (and c-record-type-identifiers |
3799 |
|
(not keyword-match)) |
3800 |
|
(if (and c-opt-identifier-concat-key |
3801 |
|
(progn |
3802 |
|
(c-forward-syntactic-ws) |
3803 |
|
(looking-at c-opt-identifier-concat-key))) |
3804 |
|
(c-record-ref-id (cons id-start id-end)) |
3805 |
|
(c-record-type-id (cons id-start id-end)))))) |
3806 |
|
t) |
3807 |
|
|
3808 |
|
((and (eq (char-before) ?,) |
3809 |
|
(not c-disallow-comma-in-<>-arglists)) |
3810 |
|
;; Just another argument. Record the position. The |
3811 |
|
;; type check stuff that made us stop at it is at |
3812 |
|
;; the top of the loop. |
3813 |
|
(setq arg-start-pos (cons (point) arg-start-pos))) |
3814 |
|
|
3815 |
|
(t |
3816 |
|
;; Got a character that can't be in an angle bracket |
3817 |
|
;; arglist argument. Abort using `throw', since |
3818 |
|
;; it's useless to try to find a surrounding arglist |
3819 |
|
;; if we're nested. |
3820 |
|
(throw 'angle-bracket-arglist-escape nil)))))) |
3821 |
|
|
3822 |
|
(if res |
3823 |
|
(or c-record-found-types t))))) |
3824 |
|
|
3825 |
|
(defun c-forward-name () |
3826 |
|
;; Move forward over a complete name if at the beginning of one, |
3827 |
|
;; stopping at the next following token. If the point is not at |
3828 |
|
;; something that are recognized as name then it stays put. A name |
3829 |
|
;; could be something as simple as "foo" in C or something as |
3830 |
|
;; complex as "X<Y<class A<int>::B, BIT_MAX >> b>, ::operator<> :: |
3831 |
|
;; Z<(a>b)> :: operator const X<&foo>::T Q::G<unsigned short |
3832 |
|
;; int>::*volatile const" in C++ (this function is actually little |
3833 |
|
;; more than a `looking-at' call in all modes except those that, |
3834 |
|
;; like C++, have `c-recognize-<>-arglists' set). Return nil if no |
3835 |
|
;; name is found, 'template if it's an identifier ending with an |
3836 |
|
;; angle bracket arglist, 'operator of it's an operator identifier, |
3837 |
|
;; or t if it's some other kind of name. |
3838 |
|
|
3839 |
|
(let ((pos (point)) res id-start id-end |
3840 |
|
;; Turn off `c-promote-possible-types' here since we might |
3841 |
|
;; call `c-forward-<>-arglist' and we don't want it to promote |
3842 |
|
;; every suspect thing in the arglist to a type. We're |
3843 |
|
;; typically called from `c-forward-type' in this case, and |
3844 |
|
;; the caller only wants the top level type that it finds to |
3845 |
|
;; be promoted. |
3846 |
|
c-promote-possible-types) |
3847 |
|
(while |
3848 |
|
(and |
3849 |
|
(looking-at c-identifier-key) |
3850 |
|
|
3851 |
|
(progn |
3852 |
|
;; Check for keyword. We go to the last symbol in |
3853 |
|
;; `c-identifier-key' first. |
3854 |
|
(if (eq c-identifier-key c-symbol-key) |
3855 |
|
(setq id-start (point) |
3856 |
|
id-end (match-end 0)) |
3857 |
|
(goto-char (setq id-end (match-end 0))) |
3858 |
|
(c-simple-skip-symbol-backward) |
3859 |
|
(setq id-start (point))) |
3860 |
|
|
3861 |
|
(if (looking-at c-keywords-regexp) |
3862 |
|
(when (and (c-major-mode-is 'c++-mode) |
3863 |
|
(looking-at |
3864 |
|
(cc-eval-when-compile |
3865 |
|
(concat "\\(operator\\|\\(template\\)\\)" |
3866 |
|
"\\(" (c-lang-const c-nonsymbol-key c++) |
3867 |
|
"\\|$\\)"))) |
3868 |
|
(if (match-beginning 2) |
3869 |
|
;; "template" is only valid inside an |
3870 |
|
;; identifier if preceded by "::". |
3871 |
|
(save-excursion |
3872 |
|
(c-backward-syntactic-ws) |
3873 |
|
(and (c-safe (backward-char 2) t) |
3874 |
|
(looking-at "::"))) |
3875 |
|
t)) |
3876 |
|
|
3877 |
|
;; Handle a C++ operator or template identifier. |
3878 |
|
(goto-char id-end) |
3879 |
|
(c-forward-syntactic-ws) |
3880 |
|
(cond ((eq (char-before id-end) ?e) |
3881 |
|
;; Got "... ::template". |
3882 |
|
(let ((subres (c-forward-name))) |
3883 |
|
(when subres |
3884 |
|
(setq pos (point) |
3885 |
|
res subres)))) |
3886 |
|
|
3887 |
|
((looking-at c-identifier-start) |
3888 |
|
;; Got a cast operator. |
3889 |
|
(when (c-forward-type) |
3890 |
|
(setq pos (point) |
3891 |
|
res 'operator) |
3892 |
|
;; Now we should match a sequence of either |
3893 |
|
;; '*', '&' or a name followed by ":: *", |
3894 |
|
;; where each can be followed by a sequence |
3895 |
|
;; of `c-opt-type-modifier-key'. |
3896 |
|
(while (cond ((looking-at "[*&]") |
3897 |
|
(goto-char (match-end 0)) |
3898 |
|
t) |
3899 |
|
((looking-at c-identifier-start) |
3900 |
|
(and (c-forward-name) |
3901 |
|
(looking-at "::") |
3902 |
|
(progn |
3903 |
|
(goto-char (match-end 0)) |
3904 |
|
(c-forward-syntactic-ws) |
3905 |
|
(eq (char-after) ?*)) |
3906 |
|
(progn |
3907 |
|
(forward-char) |
3908 |
|
t)))) |
3909 |
|
(while (progn |
3910 |
|
(c-forward-syntactic-ws) |
3911 |
|
(setq pos (point)) |
3912 |
|
(looking-at c-opt-type-modifier-key)) |
3913 |
|
(goto-char (match-end 1)))))) |
3914 |
|
|
3915 |
|
((looking-at c-overloadable-operators-regexp) |
3916 |
|
;; Got some other operator. |
3917 |
|
(when c-record-type-identifiers |
3918 |
|
(setq c-last-identifier-range |
3919 |
|
(cons (point) (match-end 0)))) |
3920 |
|
(goto-char (match-end 0)) |
3921 |
|
(c-forward-syntactic-ws) |
3922 |
|
(setq pos (point) |
3923 |
|
res 'operator))) |
3924 |
|
|
3925 |
|
nil) |
3926 |
|
|
3927 |
|
(when c-record-type-identifiers |
3928 |
|
(setq c-last-identifier-range |
3929 |
|
(cons id-start id-end))) |
3930 |
|
(goto-char id-end) |
3931 |
|
(c-forward-syntactic-ws) |
3932 |
|
(setq pos (point) |
3933 |
|
res t))) |
3934 |
|
|
3935 |
|
(progn |
3936 |
|
(goto-char pos) |
3937 |
|
(when (or c-opt-identifier-concat-key |
3938 |
|
c-recognize-<>-arglists) |
3939 |
|
|
3940 |
|
(cond |
3941 |
|
((and c-opt-identifier-concat-key |
3942 |
|
(looking-at c-opt-identifier-concat-key)) |
3943 |
|
;; Got a concatenated identifier. This handles the |
3944 |
|
;; cases with tricky syntactic whitespace that aren't |
3945 |
|
;; covered in `c-identifier-key'. |
3946 |
|
(goto-char (match-end 0)) |
3947 |
|
(c-forward-syntactic-ws) |
3948 |
|
t) |
3949 |
|
|
3950 |
|
((and c-recognize-<>-arglists |
3951 |
|
(eq (char-after) ?<)) |
3952 |
|
;; Maybe an angle bracket arglist. |
3953 |
|
(when (let ((c-record-type-identifiers nil) |
3954 |
|
(c-record-found-types nil)) |
3955 |
|
(c-forward-<>-arglist |
3956 |
|
nil c-disallow-comma-in-<>-arglists)) |
3957 |
|
(c-forward-syntactic-ws) |
3958 |
|
(setq pos (point)) |
3959 |
|
(if (and c-opt-identifier-concat-key |
3960 |
|
(looking-at c-opt-identifier-concat-key)) |
3961 |
|
;; Continue if there's an identifier concatenation |
3962 |
|
;; operator after the template argument. |
3963 |
|
(progn |
3964 |
|
(when c-record-type-identifiers |
3965 |
|
(c-record-ref-id (cons id-start id-end)) |
3966 |
|
(setq c-last-identifier-range nil)) |
3967 |
|
(forward-char 2) |
3968 |
|
(c-forward-syntactic-ws) |
3969 |
|
t) |
3970 |
|
;; `c-add-type' isn't called here since we don't |
3971 |
|
;; want to add types containing angle bracket |
3972 |
|
;; arglists. |
3973 |
|
(when c-record-type-identifiers |
3974 |
|
(c-record-type-id (cons id-start id-end)) |
3975 |
|
(setq c-last-identifier-range nil)) |
3976 |
|
(setq res 'template) |
3977 |
|
nil))) |
3978 |
|
))))) |
3979 |
|
|
3980 |
|
(goto-char pos) |
3981 |
|
res)) |
3982 |
|
|
3983 |
|
(defun c-forward-type () |
3984 |
|
;; Move forward over a type spec if at the beginning of one, |
3985 |
|
;; stopping at the next following token. Return t if it's a known |
3986 |
|
;; type that can't be a name, 'known if it's an otherwise known type |
3987 |
|
;; (according to `*-font-lock-extra-types'), 'prefix if it's a known |
3988 |
|
;; prefix of a type, 'found if it's a type that matches one in |
3989 |
|
;; `c-found-types', 'maybe if it's an identfier that might be a |
3990 |
|
;; type, or nil if it can't be a type (the point isn't moved then). |
3991 |
|
;; The point is assumed to be at the beginning of a token. |
3992 |
|
;; |
3993 |
|
;; Note that this function doesn't skip past the brace definition |
3994 |
|
;; that might be considered part of the type, e.g. |
3995 |
|
;; "enum {a, b, c} foo". |
3996 |
|
(let ((start (point)) pos res res2 id-start id-end id-range) |
3997 |
|
|
3998 |
|
;; Skip leading type modifiers. If any are found we know it's a |
3999 |
|
;; prefix of a type. |
4000 |
|
(when c-opt-type-modifier-key |
4001 |
|
(while (looking-at c-opt-type-modifier-key) |
4002 |
|
(goto-char (match-end 1)) |
4003 |
|
(c-forward-syntactic-ws) |
4004 |
|
(setq res 'prefix))) |
4005 |
|
|
4006 |
|
(cond |
4007 |
|
((looking-at c-type-prefix-key) |
4008 |
|
;; Looking at a keyword that prefixes a type identifier, |
4009 |
|
;; e.g. "class". |
4010 |
|
(goto-char (match-end 1)) |
4011 |
|
(c-forward-syntactic-ws) |
4012 |
|
(setq pos (point)) |
4013 |
|
(if (memq (setq res2 (c-forward-name)) '(t template)) |
4014 |
|
(progn |
4015 |
|
(when (eq res2 t) |
4016 |
|
;; In many languages the name can be used without the |
4017 |
|
;; prefix, so we add it to `c-found-types'. |
4018 |
|
(c-add-type pos (point)) |
4019 |
|
(when c-record-type-identifiers |
4020 |
|
(c-record-type-id c-last-identifier-range))) |
4021 |
|
(setq res t)) |
4022 |
|
;; Invalid syntax. |
4023 |
|
(goto-char start) |
4024 |
|
(setq res nil))) |
4025 |
|
|
4026 |
|
((progn |
4027 |
|
(setq pos nil) |
4028 |
|
(if (looking-at c-identifier-start) |
4029 |
|
(save-excursion |
4030 |
|
(setq id-start (point) |
4031 |
|
res2 (c-forward-name)) |
4032 |
|
(when res2 |
4033 |
|
(setq id-end (point) |
4034 |
|
id-range c-last-identifier-range)))) |
4035 |
|
(and (cond ((looking-at c-primitive-type-key) |
4036 |
|
(setq res t)) |
4037 |
|
((c-with-syntax-table c-identifier-syntax-table |
4038 |
|
(looking-at c-known-type-key)) |
4039 |
|
(setq res 'known))) |
4040 |
|
(or (not id-end) |
4041 |
|
(>= (save-excursion |
4042 |
|
(save-match-data |
4043 |
|
(goto-char (match-end 1)) |
4044 |
|
(c-forward-syntactic-ws) |
4045 |
|
(setq pos (point)))) |
4046 |
|
id-end) |
4047 |
|
(setq res nil)))) |
4048 |
|
;; Looking at a primitive or known type identifier. We've |
4049 |
|
;; checked for a name first so that we don't go here if the |
4050 |
|
;; known type match only is a prefix of another name. |
4051 |
|
|
4052 |
|
(setq id-end (match-end 1)) |
4053 |
|
|
4054 |
|
(when (and c-record-type-identifiers |
4055 |
|
(or c-promote-possible-types (eq res t))) |
4056 |
|
(c-record-type-id (cons (match-beginning 1) (match-end 1)))) |
4057 |
|
|
4058 |
|
(if (and c-opt-type-component-key |
4059 |
|
(save-match-data |
4060 |
|
(looking-at c-opt-type-component-key))) |
4061 |
|
;; There might be more keywords for the type. |
4062 |
|
(let (safe-pos) |
4063 |
|
(c-forward-keyword-clause) |
4064 |
|
(while (progn |
4065 |
|
(setq safe-pos (point)) |
4066 |
|
(looking-at c-opt-type-component-key)) |
4067 |
|
(when (and c-record-type-identifiers |
4068 |
|
(looking-at c-primitive-type-key)) |
4069 |
|
(c-record-type-id (cons (match-beginning 1) |
4070 |
|
(match-end 1)))) |
4071 |
|
(c-forward-keyword-clause)) |
4072 |
|
(if (looking-at c-primitive-type-key) |
4073 |
|
(progn |
4074 |
|
(when c-record-type-identifiers |
4075 |
|
(c-record-type-id (cons (match-beginning 1) |
4076 |
|
(match-end 1)))) |
4077 |
|
(c-forward-keyword-clause) |
4078 |
|
(setq res t)) |
4079 |
|
(goto-char safe-pos) |
4080 |
|
(setq res 'prefix))) |
4081 |
|
(unless (save-match-data (c-forward-keyword-clause)) |
4082 |
|
(if pos |
4083 |
|
(goto-char pos) |
4084 |
|
(goto-char (match-end 1)) |
4085 |
|
(c-forward-syntactic-ws))))) |
4086 |
|
|
4087 |
|
(res2 |
4088 |
|
(cond ((eq res2 t) |
4089 |
|
;; A normal identifier. |
4090 |
|
(goto-char id-end) |
4091 |
|
(if (or res c-promote-possible-types) |
4092 |
|
(progn |
4093 |
|
(c-add-type id-start id-end) |
4094 |
|
(when c-record-type-identifiers |
4095 |
|
(c-record-type-id id-range)) |
4096 |
|
(unless res |
4097 |
|
(setq res 'found))) |
4098 |
|
(setq res (if (c-check-type id-start id-end) |
4099 |
|
;; It's an identifier that has been used as |
4100 |
|
;; a type somewhere else. |
4101 |
|
'found |
4102 |
|
;; It's an identifier that might be a type. |
4103 |
|
'maybe)))) |
4104 |
|
((eq res2 'template) |
4105 |
|
;; A template is a type. |
4106 |
|
(goto-char id-end) |
4107 |
|
(setq res t)) |
4108 |
|
(t |
4109 |
|
;; Otherwise it's an operator identifier, which is not a type. |
4110 |
|
(goto-char start) |
4111 |
|
(setq res nil))))) |
4112 |
|
|
4113 |
|
(when res |
4114 |
|
;; Skip trailing type modifiers. If any are found we know it's |
4115 |
|
;; a type. |
4116 |
|
(when c-opt-type-modifier-key |
4117 |
|
(while (looking-at c-opt-type-modifier-key) |
4118 |
|
(goto-char (match-end 1)) |
4119 |
|
(c-forward-syntactic-ws) |
4120 |
|
(setq res t))) |
4121 |
|
|
4122 |
|
;; Step over any type suffix operator. Do not let the existence |
4123 |
|
;; of these alter the classification of the found type, since |
4124 |
|
;; these operators typically are allowed in normal expressions |
4125 |
|
;; too. |
4126 |
|
(when c-opt-type-suffix-key |
4127 |
|
(while (looking-at c-opt-type-suffix-key) |
4128 |
|
(goto-char (match-end 1)) |
4129 |
|
(c-forward-syntactic-ws))) |
4130 |
|
|
4131 |
|
(when c-opt-type-concat-key |
4132 |
|
;; Look for a trailing operator that concatenate the type with |
4133 |
|
;; a following one, and if so step past that one through a |
4134 |
|
;; recursive call. |
4135 |
|
(setq pos (point)) |
4136 |
|
(let* ((c-promote-possible-types (or (memq res '(t known)) |
4137 |
|
c-promote-possible-types)) |
4138 |
|
;; If we can't promote then set `c-record-found-types' so that |
4139 |
|
;; we can merge in the types from the second part afterwards if |
4140 |
|
;; it turns out to be a known type there. |
4141 |
|
(c-record-found-types (and c-record-type-identifiers |
4142 |
|
(not c-promote-possible-types)))) |
4143 |
|
(if (and (looking-at c-opt-type-concat-key) |
4144 |
|
|
4145 |
|
(progn |
4146 |
|
(goto-char (match-end 1)) |
4147 |
|
(c-forward-syntactic-ws) |
4148 |
|
(setq res2 (c-forward-type)))) |
4149 |
|
|
4150 |
|
(progn |
4151 |
|
;; If either operand certainly is a type then both are, but we |
4152 |
|
;; don't let the existence of the operator itself promote two |
4153 |
|
;; uncertain types to a certain one. |
4154 |
|
(cond ((eq res t)) |
4155 |
|
((or (eq res 'known) (memq res2 '(t known))) |
4156 |
|
(c-add-type id-start id-end) |
4157 |
|
(when c-record-type-identifiers |
4158 |
|
(c-record-type-id id-range)) |
4159 |
|
(setq res t)) |
4160 |
|
((eq res 'found)) |
4161 |
|
((eq res2 'found) |
4162 |
|
(setq res 'found)) |
4163 |
|
(t |
4164 |
|
(setq res 'maybe))) |
4165 |
|
|
4166 |
|
(when (and (eq res t) |
4167 |
|
(consp c-record-found-types)) |
4168 |
|
;; Merge in the ranges of any types found by the second |
4169 |
|
;; `c-forward-type'. |
4170 |
|
(setq c-record-type-identifiers |
4171 |
|
;; `nconc' doesn't mind that the tail of |
4172 |
|
;; `c-record-found-types' is t. |
4173 |
|
(nconc c-record-found-types |
4174 |
|
c-record-type-identifiers)))) |
4175 |
|
|
4176 |
|
(goto-char pos)))) |
4177 |
|
|
4178 |
|
(when (and c-record-found-types (memq res '(known found)) id-range) |
4179 |
|
(setq c-record-found-types |
4180 |
|
(cons id-range c-record-found-types)))) |
4181 |
|
|
4182 |
|
;;(message "c-forward-type %s -> %s: %s" start (point) res) |
4183 |
|
|
4184 |
|
res)) |
4185 |
|
|
4186 |
|
|
4187 |
|
;; Handling of large scale constructs like statements and declarations. |
4188 |
|
|
4189 |
(defun c-beginning-of-inheritance-list (&optional lim) |
(defun c-beginning-of-inheritance-list (&optional lim) |
4190 |
;; Go to the first non-whitespace after the colon that starts a |
;; Go to the first non-whitespace after the colon that starts a |
4191 |
;; multiple inheritance introduction. Optional LIM is the farthest |
;; multiple inheritance introduction. Optional LIM is the farthest |
4192 |
;; back we should search. |
;; back we should search. |
4193 |
(let* ((lim (or lim (c-point 'bod)))) |
(let* ((lim (or lim (save-excursion |
4194 |
|
(c-beginning-of-syntax) |
4195 |
|
(point))))) |
4196 |
(c-with-syntax-table c++-template-syntax-table |
(c-with-syntax-table c++-template-syntax-table |
4197 |
(c-backward-token-1 0 t lim) |
(c-backward-token-2 0 t lim) |
4198 |
(while (and (looking-at "[_a-zA-Z<,]") |
(while (and (or (looking-at c-symbol-start) |
4199 |
(= (c-backward-token-1 1 t lim) 0))) |
(looking-at "[<,]")) |
4200 |
|
(zerop (c-backward-token-2 1 t lim)))) |
4201 |
(skip-chars-forward "^:")))) |
(skip-chars-forward "^:")))) |
4202 |
|
|
4203 |
(defun c-in-method-def-p () |
(defun c-in-method-def-p () |
4230 |
(defun c-at-toplevel-p () |
(defun c-at-toplevel-p () |
4231 |
"Return a determination as to whether point is at the `top-level'. |
"Return a determination as to whether point is at the `top-level'. |
4232 |
Being at the top-level means that point is either outside any |
Being at the top-level means that point is either outside any |
4233 |
enclosing block (such function definition), or inside a class, |
enclosing block (such function definition), or only inside a class, |
4234 |
namespace or extern definition, but outside any method blocks. |
namespace or other block that contains another declaration level. |
4235 |
|
|
4236 |
If point is not at the top-level (e.g. it is inside a method |
If point is not at the top-level (e.g. it is inside a method |
4237 |
definition), then nil is returned. Otherwise, if point is at a |
definition), then nil is returned. Otherwise, if point is at a |
4244 |
(or (not (c-most-enclosing-brace paren-state)) |
(or (not (c-most-enclosing-brace paren-state)) |
4245 |
(c-search-uplist-for-classkey paren-state)))) |
(c-search-uplist-for-classkey paren-state)))) |
4246 |
|
|
4247 |
(defun c-forward-to-cpp-define-body () |
(defun c-just-after-func-arglist-p (&optional lim) |
|
;; Assuming point is at the "#" that introduces a preprocessor |
|
|
;; directive, it's moved forward to the start of the definition body |
|
|
;; if it's a "#define". Non-nil is returned in this case, in all |
|
|
;; other cases nil is returned and point isn't moved. |
|
|
(when (and (looking-at |
|
|
(concat "#[ \t]*" |
|
|
"define[ \t]+\\(\\sw\\|_\\)+\\(\([^\)]*\)\\)?" |
|
|
"\\([ \t]\\|\\\\\n\\)*")) |
|
|
(not (= (match-end 0) (c-point 'eol)))) |
|
|
(goto-char (match-end 0)))) |
|
|
|
|
|
(defun c-just-after-func-arglist-p (&optional containing lim) |
|
4248 |
;; Return t if we are between a function's argument list closing |
;; Return t if we are between a function's argument list closing |
4249 |
;; paren and its opening brace. Note that the list close brace |
;; paren and its opening brace. Note that the list close brace |
4250 |
;; could be followed by a "const" specifier or a member init hanging |
;; could be followed by a "const" specifier or a member init hanging |
4251 |
;; colon. Optional CONTAINING is position of containing s-exp open |
;; colon. LIM is used as bound for some backward buffer searches; |
4252 |
;; brace. If not supplied, point is used as search start. LIM is |
;; the search might continue past it. |
|
;; used as bound for some backward buffer searches; the search might |
|
|
;; continue past it. |
|
4253 |
;; |
;; |
4254 |
;; Note: This test is easily fooled. It only works reasonably well |
;; Note: This test is easily fooled. It only works reasonably well |
4255 |
;; in the situations where `c-guess-basic-syntax' uses it. |
;; in the situations where `c-guess-basic-syntax' uses it. |
4256 |
(save-excursion |
(save-excursion |
4257 |
(c-backward-syntactic-ws lim) |
(if (c-mode-is-new-awk-p) |
4258 |
(let ((checkpoint (or containing (point)))) |
(c-awk-backward-syntactic-ws lim) |
4259 |
(goto-char checkpoint) |
(c-backward-syntactic-ws lim)) |
4260 |
|
(let ((checkpoint (point))) |
4261 |
;; could be looking at const specifier |
;; could be looking at const specifier |
4262 |
(if (and (eq (char-before) ?t) |
(if (and (eq (char-before) ?t) |
4263 |
(forward-word -1) |
(forward-word -1) |
4313 |
;; position that bounds the backward search for the argument list. |
;; position that bounds the backward search for the argument list. |
4314 |
;; |
;; |
4315 |
;; Note: A declaration level context is assumed; the test can return |
;; Note: A declaration level context is assumed; the test can return |
4316 |
;; false positives for statements and #define headers. This test is |
;; false positives for statements. This test is even more easily |
4317 |
;; even more easily fooled than `c-just-after-func-arglist-p'. |
;; fooled than `c-just-after-func-arglist-p'. |
4318 |
|
|
4319 |
(save-excursion |
(save-excursion |
4320 |
(save-restriction |
(save-restriction |
4321 |
|
|
4322 |
;; Go back to the closest preceding normal parenthesis sexp. We |
;; Go back to the closest preceding normal parenthesis sexp. We |
4323 |
;; take that as the argument list in the function header. Then |
;; take that as the argument list in the function header. Then |
4324 |
;; check that it's followed by some symbol before the next ';' |
;; check that it's followed by some symbol before the next ';' |
4325 |
;; or '{'. If it does, it's the header of the K&R argdecl we're |
;; or '{'. If it does, it's the header of the K&R argdecl we're |
4326 |
;; in. |
;; in. |
4327 |
(if lim (narrow-to-region lim (point))) |
(if lim (narrow-to-region lim (point))) |
4328 |
(let (paren-end) |
(let ((outside-macro (not (c-query-macro-start))) |
4329 |
(and (c-safe (setq paren-end (c-down-list-backward (point)))) |
paren-end) |
4330 |
(eq (char-after paren-end) ?\)) |
|
4331 |
(progn |
(catch 'done |
4332 |
(goto-char (1+ paren-end)) |
(while (if (and (c-safe (setq paren-end |
4333 |
|
(c-down-list-backward (point)))) |
4334 |
|
(eq (char-after paren-end) ?\))) |
4335 |
|
(progn |
4336 |
|
(goto-char (1+ paren-end)) |
4337 |
|
(if outside-macro |
4338 |
|
(c-beginning-of-macro))) |
4339 |
|
(throw 'done nil)))) |
4340 |
|
|
4341 |
|
(and (progn |
4342 |
(c-forward-syntactic-ws) |
(c-forward-syntactic-ws) |
4343 |
(looking-at "\\w\\|\\s_")) |
(looking-at "\\w\\|\\s_")) |
4344 |
(c-safe (c-up-list-backward paren-end)) |
(c-safe (c-up-list-backward paren-end)) |
4345 |
|
|
4346 |
|
(save-excursion |
4347 |
|
;; If it's a K&R declaration then we're now at the |
4348 |
|
;; beginning of the function arglist. Check that there |
4349 |
|
;; isn't a '=' before it in this statement since that |
4350 |
|
;; means it some kind of initialization instead. |
4351 |
|
(c-syntactic-skip-backward "^;=}{") |
4352 |
|
(not (eq (char-before) ?=))) |
4353 |
|
|
4354 |
(point)))))) |
(point)))))) |
4355 |
|
|
4356 |
(defun c-skip-conditional () |
(defun c-skip-conditional () |
4374 |
;; If looking at the token after a conditional then return the |
;; If looking at the token after a conditional then return the |
4375 |
;; position of its start, otherwise return nil. |
;; position of its start, otherwise return nil. |
4376 |
(save-excursion |
(save-excursion |
4377 |
(and (= (c-backward-token-1 1 t lim) 0) |
(and (zerop (c-backward-token-2 1 t lim)) |
4378 |
(or (looking-at c-block-stmt-1-key) |
(or (looking-at c-block-stmt-1-key) |
4379 |
(and (eq (char-after) ?\() |
(and (eq (char-after) ?\() |
4380 |
(= (c-backward-token-1 1 t lim) 0) |
(zerop (c-backward-token-2 1 t lim)) |
4381 |
(looking-at c-block-stmt-2-key))) |
(looking-at c-block-stmt-2-key))) |
4382 |
(point)))) |
(point)))) |
4383 |
|
|
4417 |
;; semicolon. I.e. search forward for the closest following |
;; semicolon. I.e. search forward for the closest following |
4418 |
;; (syntactically relevant) '{', '=' or ';' token. Point is left |
;; (syntactically relevant) '{', '=' or ';' token. Point is left |
4419 |
;; _after_ the first found token, or at point-max if none is found. |
;; _after_ the first found token, or at point-max if none is found. |
4420 |
(c-with-syntax-table (if (c-major-mode-is 'c++-mode) |
(if (c-major-mode-is 'c++-mode) |
4421 |
c++-template-syntax-table |
;; In C++ we need to take special care to handle those pesky |
4422 |
(syntax-table)) |
;; template brackets. |
4423 |
(while (and (c-syntactic-re-search-forward "[;{=]" nil 'move 1 t) |
(while (and (c-syntactic-re-search-forward "[;{=<]" nil 'move t) |
4424 |
;; In Pike it can be an operator identifier containing |
(when (eq (char-before) ?<) |
4425 |
;; '='. |
(c-with-syntax-table c++-template-syntax-table |
4426 |
(c-major-mode-is 'pike-mode) |
(if (c-safe (goto-char (c-up-list-forward (point)))) |
4427 |
(eq (char-before) ?=) |
t |
4428 |
(c-on-identifier))))) |
(goto-char (point-max)) |
4429 |
|
nil))))) |
4430 |
|
(c-syntactic-re-search-forward "[;{=]" nil 'move t t))) |
4431 |
|
|
4432 |
(defun c-beginning-of-decl-1 (&optional lim) |
(defun c-beginning-of-decl-1 (&optional lim) |
4433 |
;; Go to the beginning of the current declaration, or the beginning |
;; Go to the beginning of the current declaration, or the beginning |
4445 |
;; declarations, e.g. "struct foo { ... }" and "bar;" in this case. |
;; declarations, e.g. "struct foo { ... }" and "bar;" in this case. |
4446 |
(catch 'return |
(catch 'return |
4447 |
(let* ((start (point)) |
(let* ((start (point)) |
4448 |
(last-stmt-start (point)) |
(last-stmt-start (point)) |
4449 |
(move (c-beginning-of-statement-1 lim t t))) |
(move (c-beginning-of-statement-1 lim t t))) |
4450 |
|
|
|
(while (and (/= last-stmt-start (point)) |
|
|
(save-excursion |
|
|
(c-backward-syntactic-ws lim) |
|
|
(not (memq (char-before) '(?\; ?} ?: nil))))) |
|
4451 |
;; `c-beginning-of-statement-1' stops at a block start, but we |
;; `c-beginning-of-statement-1' stops at a block start, but we |
4452 |
;; want to continue if the block doesn't begin a top level |
;; want to continue if the block doesn't begin a top level |
4453 |
;; construct, i.e. if it isn't preceded by ';', '}', ':', or bob. |
;; construct, i.e. if it isn't preceded by ';', '}', ':', or bob. |
4454 |
(setq last-stmt-start (point) |
(let ((beg (point)) tentative-move) |
4455 |
move (c-beginning-of-statement-1 lim t t))) |
(while (and |
4456 |
|
;; Must check with c-opt-method-key in ObjC mode. |
4457 |
(when c-recognize-knr-p |
(not (and c-opt-method-key |
4458 |
(let ((fallback-pos (point)) knr-argdecl-start) |
(looking-at c-opt-method-key))) |
4459 |
;; Handle K&R argdecls. Back up after the "statement" jumped |
(/= last-stmt-start (point)) |
4460 |
;; over by `c-beginning-of-statement-1', unless it was the |
(progn |
4461 |
;; function body, in which case we're sitting on the opening |
(c-backward-syntactic-ws lim) |
4462 |
;; brace now. Then test if we're in a K&R argdecl region and |
(not (memq (char-before) '(?\; ?} ?: nil)))) |
4463 |
;; that we started at the other side of the first argdecl in |
;; Check that we don't move from the first thing in a |
4464 |
;; it. |
;; macro to its header. |
4465 |
(unless (eq (char-after) ?{) |
(not (eq (setq tentative-move |
4466 |
(goto-char last-stmt-start)) |
(c-beginning-of-statement-1 lim t t)) |
4467 |
(if (and (setq knr-argdecl-start (c-in-knr-argdecl lim)) |
'macro))) |
4468 |
(< knr-argdecl-start start) |
(setq last-stmt-start beg |
4469 |
(progn |
beg (point) |
4470 |
(goto-char knr-argdecl-start) |
move tentative-move)) |
4471 |
(not (eq (c-beginning-of-statement-1 lim t t) 'macro)))) |
(goto-char beg)) |
4472 |
(throw 'return |
|
4473 |
(cons (if (eq (char-after fallback-pos) ?{) |
(when c-recognize-knr-p |
4474 |
'previous |
(let ((fallback-pos (point)) knr-argdecl-start) |
4475 |
'same) |
;; Handle K&R argdecls. Back up after the "statement" jumped |
4476 |
knr-argdecl-start)) |
;; over by `c-beginning-of-statement-1', unless it was the |
4477 |
(goto-char fallback-pos)))) |
;; function body, in which case we're sitting on the opening |
4478 |
|
;; brace now. Then test if we're in a K&R argdecl region and |
4479 |
(when c-opt-access-key |
;; that we started at the other side of the first argdecl in |
4480 |
;; Might have ended up before a protection label. This should |
;; it. |
4481 |
;; perhaps be checked before `c-recognize-knr-p' to be really |
(unless (eq (char-after) ?{) |
4482 |
;; accurate, but we know that no language has both. |
(goto-char last-stmt-start)) |
4483 |
(while (looking-at c-opt-access-key) |
(if (and (setq knr-argdecl-start (c-in-knr-argdecl lim)) |
4484 |
(goto-char (match-end 0)) |
(< knr-argdecl-start start) |
4485 |
(c-forward-syntactic-ws) |
(progn |
4486 |
(when (>= (point) start) |
(goto-char knr-argdecl-start) |
4487 |
(goto-char start) |
(not (eq (c-beginning-of-statement-1 lim t t) 'macro)))) |
4488 |
(throw 'return (cons 'same nil))))) |
(throw 'return |
4489 |
|
(cons (if (eq (char-after fallback-pos) ?{) |
4490 |
;; `c-beginning-of-statement-1' counts each brace block as a |
'previous |
4491 |
;; separate statement, so the result will be 'previous if we've |
'same) |
4492 |
;; moved over any. If they were brace list initializers we might |
knr-argdecl-start)) |
4493 |
;; not have moved over a declaration boundary though, so change it |
(goto-char fallback-pos)))) |
4494 |
;; to 'same if we've moved past a '=' before '{', but not ';'. |
|
4495 |
;; (This ought to be integrated into `c-beginning-of-statement-1', |
(when c-opt-access-key |
4496 |
;; so we avoid this extra pass which potentially can search over a |
;; Might have ended up before a protection label. This should |
4497 |
;; large amount of text.) |
;; perhaps be checked before `c-recognize-knr-p' to be really |
4498 |
(if (and (eq move 'previous) |
;; accurate, but we know that no language has both. |
4499 |
(c-with-syntax-table (if (c-major-mode-is 'c++-mode) |
(while (looking-at c-opt-access-key) |
4500 |
c++-template-syntax-table |
(goto-char (match-end 0)) |
4501 |
(syntax-table)) |
(c-forward-syntactic-ws) |
4502 |
(save-excursion |
(when (>= (point) start) |
4503 |
(and (c-syntactic-re-search-forward "[;={]" start t 1 t) |
(goto-char start) |
4504 |
(eq (char-before) ?=) |
(throw 'return (cons 'same nil))))) |
4505 |
(c-syntactic-re-search-forward "[;{]" start t 1 t) |
|
4506 |
(eq (char-before) ?{) |
;; `c-beginning-of-statement-1' counts each brace block as a |
4507 |
(c-safe (goto-char (c-up-list-forward (point))) t) |
;; separate statement, so the result will be 'previous if we've |
4508 |
(not (c-syntactic-re-search-forward ";" start t 1 t)))))) |
;; moved over any. If they were brace list initializers we might |
4509 |
(cons 'same nil) |
;; not have moved over a declaration boundary though, so change it |
4510 |
(cons move nil))))) |
;; to 'same if we've moved past a '=' before '{', but not ';'. |
4511 |
|
;; (This ought to be integrated into `c-beginning-of-statement-1', |
4512 |
|
;; so we avoid this extra pass which potentially can search over a |
4513 |
|
;; large amount of text.) |
4514 |
|
(if (and (eq move 'previous) |
4515 |
|
(c-with-syntax-table (if (c-major-mode-is 'c++-mode) |
4516 |
|
c++-template-syntax-table |
4517 |
|
(syntax-table)) |
4518 |
|
(save-excursion |
4519 |
|
(and (c-syntactic-re-search-forward "[;={]" start t t t) |
4520 |
|
(eq (char-before) ?=) |
4521 |
|
(c-syntactic-re-search-forward "[;{]" start t t) |
4522 |
|
(eq (char-before) ?{) |
4523 |
|
(c-safe (goto-char (c-up-list-forward (point))) t) |
4524 |
|
(not (c-syntactic-re-search-forward ";" start t t)))))) |
4525 |
|
(cons 'same nil) |
4526 |
|
(cons move nil))))) |
4527 |
|
|
4528 |
(defun c-end-of-decl-1 () |
(defun c-end-of-decl-1 () |
4529 |
;; Assuming point is at the start of a declaration (as detected by |
;; Assuming point is at the start of a declaration (as detected by |
4548 |
;; detected using the same criteria as in |
;; detected using the same criteria as in |
4549 |
;; `c-beginning-of-decl-1'. Move to the following block |
;; `c-beginning-of-decl-1'. Move to the following block |
4550 |
;; start. |
;; start. |
4551 |
(c-syntactic-re-search-forward "{" nil 'move 1 t)) |
(c-syntactic-re-search-forward "{" nil 'move t)) |
4552 |
|
|
4553 |
(when (eq (char-before) ?{) |
(when (eq (char-before) ?{) |
4554 |
;; Encountered a block in the declaration. Jump over it. |
;; Encountered a block in the declaration. Jump over it. |
4555 |
(condition-case nil |
(condition-case nil |
4556 |
(goto-char (c-up-list-forward (point))) |
(goto-char (c-up-list-forward (point))) |
4557 |
(goto-char (point-max)) |
(error (goto-char (point-max)) |
4558 |
(throw 'return nil)) |
(throw 'return nil))) |
4559 |
(if (or (not c-opt-block-decls-with-vars-key) |
(if (or (not c-opt-block-decls-with-vars-key) |
4560 |
(save-excursion |
(save-excursion |
4561 |
(c-with-syntax-table decl-syntax-table |
(c-with-syntax-table decl-syntax-table |
4565 |
;; Check for `c-opt-block-decls-with-vars-key' |
;; Check for `c-opt-block-decls-with-vars-key' |
4566 |
;; before the first paren. |
;; before the first paren. |
4567 |
(c-syntactic-re-search-forward |
(c-syntactic-re-search-forward |
4568 |
(concat "[;=\(\[{]\\|\\<\\(" |
(concat "[;=\(\[{]\\|\\(" |
4569 |
c-opt-block-decls-with-vars-key |
c-opt-block-decls-with-vars-key |
4570 |
"\\)") |
"\\)") |
4571 |
lim t 1 t) |
lim t t t) |
4572 |
(match-beginning 1) |
(match-beginning 1) |
4573 |
(not (eq (char-before) ?_)) |
(not (eq (char-before) ?_)) |
4574 |
;; Check that the first following paren is the block. |
;; Check that the first following paren is |
4575 |
(c-syntactic-re-search-forward "[;=\(\[{]" lim t 1 t) |
;; the block. |
4576 |
|
(c-syntactic-re-search-forward "[;=\(\[{]" |
4577 |
|
lim t t t) |
4578 |
(eq (char-before) ?{))))))) |
(eq (char-before) ?{))))))) |
4579 |
;; The declaration doesn't have any of the |
;; The declaration doesn't have any of the |
4580 |
;; `c-opt-block-decls-with-vars' keywords in the |
;; `c-opt-block-decls-with-vars' keywords in the |
4585 |
(while (progn |
(while (progn |
4586 |
(if (eq (char-before) ?\;) |
(if (eq (char-before) ?\;) |
4587 |
(throw 'return t)) |
(throw 'return t)) |
4588 |
(c-syntactic-re-search-forward ";" nil 'move 1 t)))) |
(c-syntactic-re-search-forward ";" nil 'move t)))) |
4589 |
nil))) |
nil))) |
4590 |
|
|
4591 |
(defun c-beginning-of-member-init-list (&optional limit) |
(defun c-beginning-of-member-init-list (&optional limit) |
4592 |
;; Goes to the beginning of a member init list (i.e. just after the |
;; Goes to the beginning of a member init list (i.e. just after the |
4593 |
;; ':') if inside one. Returns t in that case, nil otherwise. |
;; ':') if inside one. Returns t in that case, nil otherwise. |
4594 |
(or limit |
(or limit |
4595 |
(setq limit (point-min))) |
(setq limit (point-min))) |
4596 |
(skip-chars-forward " \t") |
(skip-chars-forward " \t") |
4597 |
|
|
4598 |
(if (eq (char-after) ?,) |
(if (eq (char-after) ?,) |
4599 |
(forward-char 1) |
(forward-char 1) |
4600 |
(c-backward-syntactic-ws limit)) |
(c-backward-syntactic-ws limit)) |
4601 |
(while (and (< limit (point)) |
|
4602 |
(eq (char-before) ?,)) |
(catch 'exit |
4603 |
;; this will catch member inits with multiple |
(while (and (< limit (point)) |
4604 |
;; line arglists |
(eq (char-before) ?,)) |
4605 |
(forward-char -1) |
|
4606 |
(c-backward-syntactic-ws limit) |
;; this will catch member inits with multiple |
4607 |
(if (eq (char-before) ?\)) |
;; line arglists |
4608 |
(c-backward-sexp 1)) |
(forward-char -1) |
4609 |
(c-backward-syntactic-ws limit) |
(c-backward-syntactic-ws limit) |
4610 |
;; Skip over any template arg to the class. |
(if (eq (char-before) ?\)) |
4611 |
(if (eq (char-before) ?>) |
(unless (c-safe (c-backward-sexp 1)) |
4612 |
(c-with-syntax-table c++-template-syntax-table |
(throw 'exit nil))) |
4613 |
(c-backward-sexp 1))) |
(c-backward-syntactic-ws limit) |
4614 |
(c-backward-sexp 1) |
|
4615 |
(c-backward-syntactic-ws limit) |
;; Skip over any template arg to the class. This way with a |
4616 |
;; Skip backwards over a fully::qualified::name. |
;; syntax table is bogus but it'll have to do for now. |
4617 |
(while (and (eq (char-before) ?:) |
(if (and (eq (char-before) ?>) |
4618 |
(save-excursion |
(c-major-mode-is 'c++-mode)) |
4619 |
(forward-char -1) |
(c-with-syntax-table c++-template-syntax-table |
4620 |
(eq (char-before) ?:))) |
(unless (c-safe (c-backward-sexp 1)) |
4621 |
(backward-char 2) |
(throw 'exit nil)))) |
4622 |
(c-backward-sexp 1)) |
(c-safe (c-backward-sexp 1)) |
4623 |
;; now continue checking |
(c-backward-syntactic-ws limit) |
4624 |
(c-backward-syntactic-ws limit)) |
|
4625 |
(and (< limit (point)) |
;; Skip backwards over a fully::qualified::name. |
4626 |
(eq (char-before) ?:))) |
(while (and (eq (char-before) ?:) |
4627 |
|
(save-excursion |
4628 |
|
(forward-char -1) |
4629 |
|
(eq (char-before) ?:))) |
4630 |
|
(backward-char 2) |
4631 |
|
(c-safe (c-backward-sexp 1))) |
4632 |
|
|
4633 |
|
;; If we've stepped over a number then this is a bitfield. |
4634 |
|
(when (and c-opt-bitfield-key |
4635 |
|
(looking-at "[0-9]")) |
4636 |
|
(throw 'exit nil)) |
4637 |
|
|
4638 |
|
;; now continue checking |
4639 |
|
(c-backward-syntactic-ws limit)) |
4640 |
|
|
4641 |
|
(and (< limit (point)) |
4642 |
|
(eq (char-before) ?:)))) |
4643 |
|
|
4644 |
(defun c-search-uplist-for-classkey (paren-state) |
(defun c-search-uplist-for-classkey (paren-state) |
4645 |
;; search for the containing class, returning a 2 element vector if |
;; search for the containing class, returning a 2 element vector if |
4663 |
search-end (nth 0 paren-state))) |
search-end (nth 0 paren-state))) |
4664 |
;; if search-end is nil, or if the search-end character isn't an |
;; if search-end is nil, or if the search-end character isn't an |
4665 |
;; open brace, we are definitely not in a class |
;; open brace, we are definitely not in a class |
4666 |
(when (consp search-end) |
(if (or (not search-end) |
4667 |
(setq search-end (car search-end))) |
(< search-end (point-min)) |
4668 |
(unless (or (not search-end) |
(not (eq (char-after search-end) ?{))) |
4669 |
(< search-end (point-min)) |
nil |
|
(not (eq (char-after search-end) ?{))) |
|
4670 |
;; now, we need to look more closely at search-start. if |
;; now, we need to look more closely at search-start. if |
4671 |
;; search-start is nil, then our start boundary is really |
;; search-start is nil, then our start boundary is really |
4672 |
;; point-min. |
;; point-min. |
4676 |
;; searching from the end of the balanced sexp just ahead of |
;; searching from the end of the balanced sexp just ahead of |
4677 |
;; us |
;; us |
4678 |
(if (consp search-start) |
(if (consp search-start) |
4679 |
(setq search-start (cdr search-start)))) |
(setq search-start (cdr search-start)) |
4680 |
|
;; Otherwise we start searching within the surrounding paren sexp. |
4681 |
|
(setq search-start (1+ search-start)))) |
4682 |
;; now we can do a quick regexp search from search-start to |
;; now we can do a quick regexp search from search-start to |
4683 |
;; search-end and see if we can find a class key. watch for |
;; search-end and see if we can find a class key. watch for |
4684 |
;; class like strings in literals |
;; class like strings in literals |
4690 |
(progn |
(progn |
4691 |
(c-forward-syntactic-ws search-end) |
(c-forward-syntactic-ws search-end) |
4692 |
(> search-end (point))) |
(> search-end (point))) |
4693 |
(re-search-forward c-decl-block-key search-end t)) |
;; Add one to the search limit, to allow |
4694 |
|
;; matching of the "{" in the regexp. |
4695 |
|
(re-search-forward c-decl-block-key |
4696 |
|
(1+ search-end) |
4697 |
|
t)) |
4698 |
(setq class (match-beginning 0) |
(setq class (match-beginning 0) |
4699 |
match-end (match-end 0)) |
match-end (match-end 0)) |
4700 |
(goto-char class) |
(goto-char class) |
4718 |
;; Check if this is an anonymous inner class. |
;; Check if this is an anonymous inner class. |
4719 |
((and c-opt-inexpr-class-key |
((and c-opt-inexpr-class-key |
4720 |
(looking-at c-opt-inexpr-class-key)) |
(looking-at c-opt-inexpr-class-key)) |
4721 |
(while (and (= (c-forward-token-1 1 t) 0) |
(while (and (zerop (c-forward-token-2 1 t)) |
4722 |
(looking-at "(\\|\\w\\|\\s_\\|\\."))) |
(looking-at "(\\|\\w\\|\\s_\\|\\."))) |
4723 |
(if (eq (point) search-end) |
(if (eq (point) search-end) |
4724 |
;; We're done. Just trap this case in the cond. |
;; We're done. Just trap this case in the cond. |
4761 |
;; places in inconvenient locations. Its a trade-off we make for |
;; places in inconvenient locations. Its a trade-off we make for |
4762 |
;; speed. |
;; speed. |
4763 |
(or |
(or |
4764 |
;; this will pick up enum lists |
;; This will pick up brace list declarations. |
4765 |
(c-safe |
(c-safe |
4766 |
(save-excursion |
(save-excursion |
4767 |
(goto-char containing-sexp) |
(goto-char containing-sexp) |
4768 |
(c-forward-sexp -1) |
(c-forward-sexp -1) |
4769 |
(let (bracepos) |
(let (bracepos) |
4770 |
(if (and (or (looking-at "enum\\>[^_]") |
(if (and (or (looking-at c-brace-list-key) |
4771 |
(progn (c-forward-sexp -1) |
(progn (c-forward-sexp -1) |
4772 |
(looking-at "enum\\>[^_]"))) |
(looking-at c-brace-list-key))) |
4773 |
(setq bracepos (c-down-list-forward (point))) |
(setq bracepos (c-down-list-forward (point))) |
4774 |
(not (c-crosses-statement-barrier-p (point) |
(not (c-crosses-statement-barrier-p (point) |
4775 |
(- bracepos 2)))) |
(- bracepos 2)))) |
4802 |
;; see if the open brace is preceded by = or [...] in |
;; see if the open brace is preceded by = or [...] in |
4803 |
;; this statement, but watch out for operator= |
;; this statement, but watch out for operator= |
4804 |
(setq braceassignp 'dontknow) |
(setq braceassignp 'dontknow) |
4805 |
(c-backward-token-1 1 t lim) |
(c-backward-token-2 1 t lim) |
4806 |
;; Checks to do only on the first sexp before the brace. |
;; Checks to do only on the first sexp before the brace. |
4807 |
(when (and (c-major-mode-is 'java-mode) |
(when (and c-opt-inexpr-brace-list-key |
4808 |
(eq (char-after) ?\[)) |
(eq (char-after) ?\[)) |
4809 |
;; In Java, an initialization brace list may follow |
;; In Java, an initialization brace list may follow |
4810 |
;; directly after "new Foo[]", so check for a "new" |
;; directly after "new Foo[]", so check for a "new" |
4811 |
;; earlier. |
;; earlier. |
4812 |
(while (eq braceassignp 'dontknow) |
(while (eq braceassignp 'dontknow) |
4813 |
(setq braceassignp |
(setq braceassignp |
4814 |
(cond ((/= (c-backward-token-1 1 t lim) 0) nil) |
(cond ((/= (c-backward-token-2 1 t lim) 0) nil) |
4815 |
((looking-at "new\\>[^_]") t) |
((looking-at c-opt-inexpr-brace-list-key) t) |
4816 |
((looking-at "\\sw\\|\\s_\\|[.[]") |
((looking-at "\\sw\\|\\s_\\|[.[]") |
4817 |
;; Carry on looking if this is an |
;; Carry on looking if this is an |
4818 |
;; identifier (may contain "." in Java) |
;; identifier (may contain "." in Java) |
4832 |
;; that it isn't something that should be ignored. |
;; that it isn't something that should be ignored. |
4833 |
(setq braceassignp 'maybe) |
(setq braceassignp 'maybe) |
4834 |
(while (and (eq braceassignp 'maybe) |
(while (and (eq braceassignp 'maybe) |
4835 |
(zerop (c-backward-token-1 1 t lim))) |
(zerop (c-backward-token-2 1 t lim))) |
4836 |
(setq braceassignp |
(setq braceassignp |
4837 |
(cond |
(cond |
4838 |
;; Check for operator = |
;; Check for operator = |
4864 |
nil) |
nil) |
4865 |
(t t)))))) |
(t t)))))) |
4866 |
(if (and (eq braceassignp 'dontknow) |
(if (and (eq braceassignp 'dontknow) |
4867 |
(/= (c-backward-token-1 1 t lim) 0)) |
(/= (c-backward-token-2 1 t lim) 0)) |
4868 |
(setq braceassignp nil))) |
(setq braceassignp nil))) |
4869 |
(if (not braceassignp) |
(if (not braceassignp) |
4870 |
(if (eq (char-after) ?\;) |
(if (eq (char-after) ?\;) |
4982 |
;; in-expression class. |
;; in-expression class. |
4983 |
(let ((prev (point))) |
(let ((prev (point))) |
4984 |
(while (and |
(while (and |
4985 |
(= (c-backward-token-1 1 nil closest-lim) 0) |
(= (c-backward-token-2 1 nil closest-lim) 0) |
4986 |
(eq (char-syntax (char-after)) ?w)) |
(eq (char-syntax (char-after)) ?w)) |
4987 |
(setq prev (point))) |
(setq prev (point))) |
4988 |
(goto-char prev) |
(goto-char prev) |
4993 |
(save-excursion |
(save-excursion |
4994 |
(and (c-major-mode-is 'pike-mode) |
(and (c-major-mode-is 'pike-mode) |
4995 |
(progn (goto-char block-follows) |
(progn (goto-char block-follows) |
4996 |
(= (c-forward-token-1 1 t) 0)) |
(zerop (c-forward-token-2 1 t))) |
4997 |
(eq (char-after) ?\()))) |
(eq (char-after) ?\()))) |
4998 |
(cons 'inexpr-class (point)))) |
(cons 'inexpr-class (point)))) |
4999 |
((and c-opt-inexpr-block-key |
((and c-opt-inexpr-block-key |
5044 |
paren-state) |
paren-state) |
5045 |
containing-sexp))))) |
containing-sexp))))) |
5046 |
|
|
|
(defun c-on-identifier () |
|
|
"Return non-nil if we're on or directly after an identifier. |
|
|
Keywords are recognized and not considered identifiers." |
|
|
(if (or (memq (char-syntax (or (char-after) ? )) '(?w ?_)) |
|
|
(memq (char-syntax (or (char-before) ? )) '(?w ?_))) |
|
|
(save-excursion |
|
|
(skip-syntax-backward "w_") |
|
|
(not (looking-at c-keywords-regexp))) |
|
|
(if (c-major-mode-is 'pike-mode) |
|
|
;; Handle the `<operator> syntax in Pike. |
|
|
(save-excursion |
|
|
(if (eq (char-after) ?\`) (forward-char)) |
|
|
(skip-chars-backward "!%&*+\\-/<=>^|~") |
|
|
(let ((pos (point))) |
|
|
(cond ((memq (char-before) '(?\) ?\])) |
|
|
(c-safe (backward-char 2))) |
|
|
((memq (char-before) '(?\( ?\[)) |
|
|
(c-safe (backward-char 1)))) |
|
|
(if (not (looking-at "()\\|\\[]")) |
|
|
(goto-char pos))) |
|
|
(and (eq (char-before) ?\`) |
|
|
(looking-at "[-!%&*+/<=>^|~]\\|()\\|\\[]")))))) |
|
|
|
|
|
|
|
|
(defun c-most-enclosing-brace (paren-state &optional bufpos) |
|
|
;; Return the bufpos of the innermost enclosing brace before bufpos |
|
|
;; that hasn't been narrowed out, or nil if none was found. |
|
|
(let (enclosingp) |
|
|
(or bufpos (setq bufpos 134217727)) |
|
|
(while paren-state |
|
|
(setq enclosingp (car paren-state) |
|
|
paren-state (cdr paren-state)) |
|
|
(if (or (consp enclosingp) |
|
|
(>= enclosingp bufpos)) |
|
|
(setq enclosingp nil) |
|
|
(if (< enclosingp (point-min)) |
|
|
(setq enclosingp nil)) |
|
|
(setq paren-state nil))) |
|
|
enclosingp)) |
|
|
|
|
|
(defun c-least-enclosing-brace (paren-state &optional bufpos) |
|
|
;; Return the bufpos of the outermost enclosing brace before bufpos |
|
|
;; that hasn't been narrowed out, or nil if none was found. |
|
|
(let (pos elem) |
|
|
(or bufpos (setq bufpos 134217727)) |
|
|
(while paren-state |
|
|
(setq elem (car paren-state) |
|
|
paren-state (cdr paren-state)) |
|
|
(unless (or (consp elem) |
|
|
(>= elem bufpos)) |
|
|
(if (>= elem (point-min)) |
|
|
(setq pos elem)))) |
|
|
pos)) |
|
|
|
|
|
(defun c-safe-position (bufpos paren-state) |
|
|
;; Return the closest known safe position higher up than BUFPOS, or |
|
|
;; nil if PAREN-STATE doesn't contain one. Return nil if BUFPOS is |
|
|
;; nil, which is useful to find the closest limit before a given |
|
|
;; limit that might be nil. |
|
|
(when bufpos |
|
|
(let ((c-macro-start (c-query-macro-start)) safepos) |
|
|
(if (and c-macro-start |
|
|
(< c-macro-start bufpos)) |
|
|
;; Make sure bufpos is outside the macro we might be in. |
|
|
(setq bufpos c-macro-start)) |
|
|
(catch 'done |
|
|
(while paren-state |
|
|
(setq safepos |
|
|
(if (consp (car paren-state)) |
|
|
(cdr (car paren-state)) |
|
|
(car paren-state))) |
|
|
(if (< safepos bufpos) |
|
|
(throw 'done safepos) |
|
|
(setq paren-state (cdr paren-state)))) |
|
|
(if (eq c-macro-start bufpos) |
|
|
;; Backed up bufpos to the macro start and got outside the |
|
|
;; state. We know the macro is at the top level in this case, |
|
|
;; so we can use the macro start as the safe position. |
|
|
c-macro-start))))) |
|
|
|
|
5047 |
(defun c-narrow-out-enclosing-class (paren-state lim) |
(defun c-narrow-out-enclosing-class (paren-state lim) |
5048 |
;; Narrow the buffer so that the enclosing class is hidden. Uses |
;; Narrow the buffer so that the enclosing class is hidden. Uses |
5049 |
;; and returns the value from c-search-uplist-for-classkey. |
;; and returns the value from c-search-uplist-for-classkey. |
5070 |
inclass-p)) |
inclass-p)) |
5071 |
|
|
5072 |
|
|
5073 |
;; c-guess-basic-syntax implements the main decision tree for |
;; `c-guess-basic-syntax' and the functions that precedes it below |
5074 |
;; determining the syntactic analysis of the current line of code. |
;; implements the main decision tree for determining the syntactic |
5075 |
;; Yes, it's huge and bloated! |
;; analysis of the current line of code. |
5076 |
|
|
5077 |
;; It's useful to break out some parts of the decision tree to |
;; Dynamically bound to t when `c-guess-basic-syntax' is called during |
5078 |
;; separate functions, which are all collected below. Use dynamic |
;; auto newline analysis. |
5079 |
;; binding to propagate back the syntax results from them. |
(defvar c-auto-newline-analysis nil) |
5080 |
(defvar syntax) |
|
5081 |
(defvar syntactic-relpos) |
(defsubst c-add-syntax (symbol &rest args) |
5082 |
|
;; A simple function to prepend a new syntax element to |
5083 |
|
;; `c-syntactic-context'. Using `setq' on it is unsafe since it |
5084 |
|
;; should always be dynamically bound but since we read it first |
5085 |
|
;; we'll fail properly anyway if this function is misused. |
5086 |
|
(setq c-syntactic-context (cons (cons symbol args) |
5087 |
|
c-syntactic-context))) |
5088 |
|
|
5089 |
|
(defsubst c-append-syntax (symbol &rest args) |
5090 |
|
;; Like `c-add-syntax' but appends to the end of the syntax list. |
5091 |
|
;; (Normally not necessary.) |
5092 |
|
(setq c-syntactic-context (nconc c-syntactic-context |
5093 |
|
(list (cons symbol args))))) |
5094 |
|
|
5095 |
(defun c-add-stmt-syntax (syntax-symbol |
(defun c-add-stmt-syntax (syntax-symbol |
5096 |
|
syntax-extra-args |
5097 |
stop-at-boi-only |
stop-at-boi-only |
5098 |
|
at-block-start |
5099 |
containing-sexp |
containing-sexp |
5100 |
paren-state |
paren-state) |
|
&optional at-block-start) |
|
5101 |
;; Do the generic processing to anchor the given syntax symbol on |
;; Do the generic processing to anchor the given syntax symbol on |
5102 |
;; the preceding statement: Skip over any labels and containing |
;; the preceding statement: Skip over any labels and containing |
5103 |
;; statements on the same line, and then search backward until we |
;; statements on the same line, and then search backward until we |
5106 |
;; |
;; |
5107 |
;; Point is assumed to be at the prospective anchor point for the |
;; Point is assumed to be at the prospective anchor point for the |
5108 |
;; given SYNTAX-SYMBOL. More syntax entries are added if we need to |
;; given SYNTAX-SYMBOL. More syntax entries are added if we need to |
5109 |
;; skip past block opens and containing statement. All the added |
;; skip past open parens and containing statements. All the added |
5110 |
;; syntax elements will get the same anchor point. |
;; syntax elements will get the same anchor point. |
5111 |
;; |
;; |
5112 |
|
;; SYNTAX-EXTRA-ARGS are a list of the extra arguments for the |
5113 |
|
;; syntax symbol. They are appended after the anchor point. |
5114 |
|
;; |
5115 |
;; If STOP-AT-BOI-ONLY is nil, we might stop in the middle of the |
;; If STOP-AT-BOI-ONLY is nil, we might stop in the middle of the |
5116 |
;; line if another statement precedes the current one on this line. |
;; line if another statement precedes the current one on this line. |
5117 |
;; |
;; |
5122 |
(if (= (point) (c-point 'boi)) |
(if (= (point) (c-point 'boi)) |
5123 |
;; This is by far the most common case, so let's give it special |
;; This is by far the most common case, so let's give it special |
5124 |
;; treatment. |
;; treatment. |
5125 |
(c-add-syntax syntax-symbol (point)) |
(apply 'c-add-syntax syntax-symbol (point) syntax-extra-args) |
5126 |
|
|
5127 |
(let* ((savepos (point)) |
(let ((savepos (point)) |
5128 |
(syms (list syntax-symbol)) |
(syntax-last c-syntactic-context) |
5129 |
(syms-tail syms) |
(boi (c-point 'boi)) |
5130 |
(boi (c-point 'boi)) |
(prev-paren (if at-block-start ?{ (char-after))) |
5131 |
(prev-paren (if at-block-start ?{ (char-after))) |
step-type step-tmp at-comment special-list) |
5132 |
step-type step-tmp at-comment add-inexpr-stmt) |
(apply 'c-add-syntax syntax-symbol nil syntax-extra-args) |
5133 |
|
|
5134 |
;; Begin by skipping any labels and containing statements that |
;; Begin by skipping any labels and containing statements that |
5135 |
;; are on the same line. |
;; are on the same line. |
5148 |
;; Loop if we have to back out of the containing block. |
;; Loop if we have to back out of the containing block. |
5149 |
(while |
(while |
5150 |
(progn |
(progn |
5151 |
|
|
5152 |
;; Loop if we have to back up another statement. |
;; Loop if we have to back up another statement. |
5153 |
(while |
(while |
5154 |
(progn |
(progn |
5156 |
;; Always start by skipping over any comments that |
;; Always start by skipping over any comments that |
5157 |
;; stands between the statement and boi. |
;; stands between the statement and boi. |
5158 |
(while (and (/= (setq savepos (point)) boi) |
(while (and (/= (setq savepos (point)) boi) |
5159 |
(c-forward-comment -1)) |
(c-backward-single-comment)) |
5160 |
(setq at-comment t |
(setq at-comment t |
5161 |
boi (c-point 'boi))) |
boi (c-point 'boi))) |
5162 |
(goto-char savepos) |
(goto-char savepos) |
5195 |
;; if" clauses won't indent deeper and deeper. |
;; if" clauses won't indent deeper and deeper. |
5196 |
(when (and (eq step-type 'up) |
(when (and (eq step-type 'up) |
5197 |
(< (point) boi)) |
(< (point) boi)) |
5198 |
(setcdr syms-tail (list 'substatement)) |
(c-add-syntax 'substatement nil)) |
|
(setq syms-tail (cdr syms-tail))) |
|
5199 |
|
|
5200 |
(setq boi (c-point 'boi)) |
(setq boi (c-point 'boi)) |
5201 |
(/= (point) savepos))))) |
(/= (point) savepos))))) |
5207 |
(when (and (eq step-type 'same) |
(when (and (eq step-type 'same) |
5208 |
containing-sexp) |
containing-sexp) |
5209 |
(goto-char containing-sexp) |
(goto-char containing-sexp) |
|
(setq paren-state (c-whack-state-after containing-sexp |
|
|
paren-state) |
|
|
containing-sexp (c-most-enclosing-brace paren-state)) |
|
5210 |
|
|
5211 |
|
;; Don't stop in the middle of a special brace list opener |
5212 |
|
;; like "({". |
5213 |
|
(when (and c-special-brace-lists |
5214 |
|
(setq special-list |
5215 |
|
(c-looking-at-special-brace-list))) |
5216 |
|
(setq containing-sexp (car (car special-list))) |
5217 |
|
(goto-char containing-sexp)) |
5218 |
|
|
5219 |
(when (eq (setq prev-paren (char-after)) ?\() |
(setq paren-state (c-whack-state-after containing-sexp |
5220 |
(c-backward-syntactic-ws containing-sexp) |
paren-state) |
5221 |
(when (c-on-identifier) |
containing-sexp (c-most-enclosing-brace paren-state) |
5222 |
;; Arrived at a function arglist start. Exit with |
savepos (point) |
5223 |
;; the position of the first argument inside it. |
boi (c-point 'boi)) |
|
(goto-char savepos) |
|
|
(throw 'done t)) |
|
|
;; We're in an in-expression statement. Remember |
|
|
;; this. We'll iterate below, but won't add any |
|
|
;; syntax element. |
|
|
(setq add-inexpr-stmt t)) |
|
5224 |
|
|
5225 |
(setq savepos (point) |
(if (eq (setq prev-paren (char-after)) ?\() |
5226 |
boi (c-point 'boi) |
(progn |
5227 |
step-type (c-beginning-of-statement-1 containing-sexp)) |
(c-backward-syntactic-ws containing-sexp) |
5228 |
|
(when (/= savepos boi) |
5229 |
|
(if (and (or (not (looking-at "\\>")) |
5230 |
|
(not (c-on-identifier))) |
5231 |
|
(not special-list) |
5232 |
|
(save-excursion |
5233 |
|
(c-forward-syntactic-ws) |
5234 |
|
(forward-char) |
5235 |
|
(c-forward-syntactic-ws) |
5236 |
|
(eq (char-after) ?{))) |
5237 |
|
;; We're in an in-expression statement. |
5238 |
|
;; This syntactic element won't get an anchor pos. |
5239 |
|
(c-add-syntax 'inexpr-statement) |
5240 |
|
(c-add-syntax 'arglist-cont-nonempty nil savepos))) |
5241 |
|
(goto-char (max boi |
5242 |
|
(if containing-sexp |
5243 |
|
(1+ containing-sexp) |
5244 |
|
(point-min)))) |
5245 |
|
(setq step-type 'same)) |
5246 |
|
(setq step-type |
5247 |
|
(c-beginning-of-statement-1 containing-sexp))) |
5248 |
|
|
5249 |
(let ((at-bod (and (eq step-type 'same) |
(let ((at-bod (and (eq step-type 'same) |
5250 |
(/= savepos (point)) |
(/= savepos (point)) |
5251 |
(eq prev-paren ?{)))) |
(eq prev-paren ?{)))) |
5252 |
|
|
5253 |
(when (= savepos boi) |
(when (= savepos boi) |
5254 |
;; If the open brace was at boi, we're always |
;; If the open brace was at boi, we're always |
5255 |
;; done. The c-beginning-of-statement-1 call |
;; done. The c-beginning-of-statement-1 call |
5259 |
(setq savepos nil)) |
(setq savepos nil)) |
5260 |
|
|
5261 |
(when (eq prev-paren ?{) |
(when (eq prev-paren ?{) |
5262 |
(setcdr syms-tail (list (if at-bod |
(c-add-syntax (if at-bod |
5263 |
'defun-block-intro |
'defun-block-intro |
5264 |
'statement-block-intro))) |
'statement-block-intro) |
5265 |
(setq syms-tail (cdr syms-tail))) |
nil)) |
5266 |
|
|
5267 |
(when (and (not at-bod) savepos) |
(when (and (not at-bod) savepos) |
5268 |
;; Loop if the brace wasn't at boi, and we didn't |
;; Loop if the brace wasn't at boi, and we didn't |
5278 |
(setq boi (c-point 'boi))))) |
(setq boi (c-point 'boi))))) |
5279 |
))) |
))) |
5280 |
|
|
5281 |
(while syms |
;; Fill in the current point as the anchor for all the symbols |
5282 |
(c-add-syntax (car syms) (point)) |
;; added above. |
5283 |
(setq syms (cdr syms))) |
(let ((p c-syntactic-context)) |
5284 |
(if add-inexpr-stmt |
(while (not (eq p syntax-last)) |
5285 |
(c-add-syntax 'inexpr-statement)) |
(if (cdr (car p)) |
5286 |
|
(setcar (cdr (car p)) (point))) |
5287 |
|
(setq p (cdr p)))) |
5288 |
|
|
5289 |
))) |
))) |
5290 |
|
|
5291 |
(defun c-add-class-syntax (symbol classkey paren-state) |
(defun c-add-class-syntax (symbol classkey paren-state) |
5318 |
;; This function contains the decision tree reached through both |
;; This function contains the decision tree reached through both |
5319 |
;; cases 18 and 10. It's a continued statement or top level |
;; cases 18 and 10. It's a continued statement or top level |
5320 |
;; construct of some kind. |
;; construct of some kind. |
5321 |
|
|
5322 |
(let (special-brace-list) |
(let (special-brace-list) |
5323 |
(goto-char indent-point) |
(goto-char indent-point) |
5324 |
(skip-chars-forward " \t") |
(skip-chars-forward " \t") |
5325 |
|
|
5326 |
(cond |
(cond |
5327 |
;; (CASE A removed.) |
;; (CASE A removed.) |
5328 |
;; CASE B: open braces for class or brace-lists |
;; CASE B: open braces for class or brace-lists |
5330 |
(or (and c-special-brace-lists |
(or (and c-special-brace-lists |
5331 |
(c-looking-at-special-brace-list)) |
(c-looking-at-special-brace-list)) |
5332 |
(eq char-after-ip ?{))) |
(eq char-after-ip ?{))) |
5333 |
|
|
5334 |
(cond |
(cond |
5335 |
;; CASE B.1: class-open |
;; CASE B.1: class-open |
5336 |
((save-excursion |
((save-excursion |
5337 |
(goto-char indent-point) |
(skip-chars-forward "{") |
|
(skip-chars-forward " \t{") |
|
5338 |
(let ((decl (c-search-uplist-for-classkey (c-parse-state)))) |
(let ((decl (c-search-uplist-for-classkey (c-parse-state)))) |
5339 |
(and decl |
(and decl |
5340 |
(setq beg-of-same-or-containing-stmt (aref decl 0))) |
(setq beg-of-same-or-containing-stmt (aref decl 0))) |
5341 |
)) |
)) |
5342 |
(c-add-syntax 'class-open beg-of-same-or-containing-stmt)) |
(c-add-syntax 'class-open beg-of-same-or-containing-stmt)) |
5343 |
|
|
5344 |
;; CASE B.2: brace-list-open |
;; CASE B.2: brace-list-open |
5345 |
((or (consp special-brace-list) |
((or (consp special-brace-list) |
5346 |
(save-excursion |
(save-excursion |
5347 |
(goto-char beg-of-same-or-containing-stmt) |
(goto-char beg-of-same-or-containing-stmt) |
5348 |
(looking-at "enum\\>[^_]")) |
(c-syntactic-re-search-forward "=\\([^=]\\|$\\)" |
5349 |
(save-excursion |
indent-point t t t))) |
|
(goto-char indent-point) |
|
|
(while (and (> (point) beg-of-same-or-containing-stmt) |
|
|
(= (c-backward-token-1 1 t) 0) |
|
|
(/= (char-after) ?=))) |
|
|
(eq (char-after) ?=))) |
|
5350 |
;; The most semantically accurate symbol here is |
;; The most semantically accurate symbol here is |
5351 |
;; brace-list-open, but we report it simply as a statement-cont. |
;; brace-list-open, but we normally report it simply as a |
5352 |
;; The reason is that one normally adjusts brace-list-open for |
;; statement-cont. The reason is that one normally adjusts |
5353 |
;; brace lists as top-level constructs, and brace lists inside |
;; brace-list-open for brace lists as top-level constructs, |
5354 |
;; statements is a completely different context. |
;; and brace lists inside statements is a completely different |
5355 |
|
;; context. C.f. case 5A.3. |
5356 |
(c-beginning-of-statement-1 containing-sexp) |
(c-beginning-of-statement-1 containing-sexp) |
5357 |
(c-add-stmt-syntax 'statement-cont nil containing-sexp paren-state)) |
(c-add-stmt-syntax (if c-auto-newline-analysis |
5358 |
|
;; Turn off the dwim above when we're |
5359 |
|
;; analyzing the nature of the brace |
5360 |
|
;; for the auto newline feature. |
5361 |
|
'brace-list-open |
5362 |
|
'statement-cont) |
5363 |
|
nil nil nil |
5364 |
|
containing-sexp paren-state)) |
5365 |
|
|
5366 |
;; CASE B.3: The body of a function declared inside a normal |
;; CASE B.3: The body of a function declared inside a normal |
5367 |
;; block. Can occur e.g. in Pike and when using gcc |
;; block. Can occur e.g. in Pike and when using gcc |
5368 |
;; extensions. Might also trigger it with some macros followed |
;; extensions. Might also trigger it with some macros followed |
5369 |
;; by blocks, and this gives sane indentation then too. |
;; by blocks, and this gives sane indentation then too. |
5370 |
;; C.f. cases 16F and 17G. |
;; C.f. cases E, 16F and 17G. |
5371 |
((progn |
((and (not (c-looking-at-bos)) |
5372 |
(goto-char indent-point) |
(eq (c-beginning-of-statement-1 containing-sexp nil nil t) |
5373 |
(and (not (c-looking-at-bos)) |
'same)) |
5374 |
(eq (c-beginning-of-statement-1 containing-sexp nil nil t) |
(c-add-stmt-syntax 'defun-open nil t nil |
5375 |
'same))) |
containing-sexp paren-state)) |
5376 |
(c-add-stmt-syntax 'defun-open t containing-sexp paren-state)) |
|
5377 |
;; CASE B.4: Continued statement with block open. |
;; CASE B.4: Continued statement with block open. |
5378 |
(t |
(t |
5379 |
(goto-char beg-of-same-or-containing-stmt) |
(goto-char beg-of-same-or-containing-stmt) |
5380 |
(c-add-stmt-syntax 'statement-cont nil containing-sexp paren-state) |
(c-add-stmt-syntax 'statement-cont nil nil nil |
5381 |
|
containing-sexp paren-state) |
5382 |
(c-add-syntax 'block-open)) |
(c-add-syntax 'block-open)) |
5383 |
)) |
)) |
5384 |
|
|
5385 |
;; CASE C: iostream insertion or extraction operator |
;; CASE C: iostream insertion or extraction operator |
5386 |
((and (looking-at "<<\\|>>") |
((and (looking-at "\\(<<\\|>>\\)\\([^=]\\|$\\)") |
5387 |
(save-excursion |
(save-excursion |
5388 |
(goto-char beg-of-same-or-containing-stmt) |
(goto-char beg-of-same-or-containing-stmt) |
5389 |
(while (and (re-search-forward "<<\\|>>" indent-point 'move) |
;; If there is no preceding streamop in the statement |
5390 |
(c-in-literal beg-of-same-or-containing-stmt))) |
;; then indent this line as a normal statement-cont. |
5391 |
;; if we ended up at indent-point, then the first streamop is on a |
(when (c-syntactic-re-search-forward |
5392 |
;; separate line. Indent the line like a statement-cont instead |
"\\(<<\\|>>\\)\\([^=]\\|$\\)" indent-point 'move t t) |
|
(when (/= (point) indent-point) |
|
5393 |
(c-add-syntax 'stream-op (c-point 'boi)) |
(c-add-syntax 'stream-op (c-point 'boi)) |
5394 |
t)))) |
t)))) |
5395 |
|
|
5396 |
|
;; CASE E: In the "K&R region" of a function declared inside a |
5397 |
|
;; normal block. C.f. case B.3. |
5398 |
|
((and (save-excursion |
5399 |
|
;; Check that the next token is a '{'. This works as |
5400 |
|
;; long as no language that allows nested function |
5401 |
|
;; definitions doesn't allow stuff like member init |
5402 |
|
;; lists, K&R declarations or throws clauses there. |
5403 |
|
;; |
5404 |
|
;; Note that we do a forward search for something ahead |
5405 |
|
;; of the indentation line here. That's not good since |
5406 |
|
;; the user might not have typed it yet. Unfortunately |
5407 |
|
;; it's exceedingly tricky to recognize a function |
5408 |
|
;; prototype in a code block without resorting to this. |
5409 |
|
(c-forward-syntactic-ws) |
5410 |
|
(eq (char-after) ?{)) |
5411 |
|
(not (c-looking-at-bos)) |
5412 |
|
(eq (c-beginning-of-statement-1 containing-sexp nil nil t) |
5413 |
|
'same)) |
5414 |
|
(c-add-stmt-syntax 'func-decl-cont nil t nil |
5415 |
|
containing-sexp paren-state)) |
5416 |
|
|
5417 |
;; CASE D: continued statement. |
;; CASE D: continued statement. |
5418 |
(t |
(t |
5419 |
(c-beginning-of-statement-1 containing-sexp) |
(c-beginning-of-statement-1 containing-sexp) |
5420 |
(c-add-stmt-syntax 'statement-cont nil containing-sexp paren-state)) |
(c-add-stmt-syntax 'statement-cont nil nil nil |
5421 |
|
containing-sexp paren-state)) |
5422 |
))) |
))) |
5423 |
|
|
5424 |
(defun c-guess-basic-syntax () |
(defun c-guess-basic-syntax () |
5430 |
(case-fold-search nil) |
(case-fold-search nil) |
5431 |
(paren-state (c-parse-state)) |
(paren-state (c-parse-state)) |
5432 |
literal containing-sexp char-before-ip char-after-ip lim |
literal containing-sexp char-before-ip char-after-ip lim |
5433 |
syntax placeholder c-in-literal-cache step-type |
c-syntactic-context placeholder c-in-literal-cache step-type |
5434 |
tmpsymbol keyword injava-inher special-brace-list |
tmpsymbol keyword injava-inher special-brace-list |
5435 |
;; narrow out any enclosing class or extern "C" block |
;; narrow out any enclosing class or extern "C" block |
5436 |
(inclass-p (c-narrow-out-enclosing-class paren-state |
(inclass-p (c-narrow-out-enclosing-class paren-state |
5437 |
indent-point)) |
indent-point)) |
5438 |
;; c-state-cache is shadowed here. That means we must |
;; `c-state-cache' is shadowed here so that we don't |
5439 |
;; not do any changes during the execution of this |
;; throw it away due to the narrowing that might be done |
5440 |
;; function, since c-check-state-cache then would change |
;; by the function above. That means we must not do any |
5441 |
;; this local variable and leave a bogus value in the |
;; changes during the execution of this function, since |
5442 |
;; global one. |
;; `c-invalidate-state-cache' then would change this local |
5443 |
|
;; variable and leave a bogus value in the global one. |
5444 |
(c-state-cache (if inclass-p |
(c-state-cache (if inclass-p |
5445 |
(c-whack-state-before (point-min) paren-state) |
(c-whack-state-before (point-min) paren-state) |
5446 |
paren-state)) |
paren-state)) |
5450 |
;; a relpos. It's stored in syntactic-relpos. |
;; a relpos. It's stored in syntactic-relpos. |
5451 |
syntactic-relpos |
syntactic-relpos |
5452 |
(c-stmt-delim-chars c-stmt-delim-chars)) |
(c-stmt-delim-chars c-stmt-delim-chars)) |
5453 |
;; check for meta top-level enclosing constructs, possible |
;; Check for meta top-level enclosing constructs such as |
5454 |
;; extern language definitions, possibly (in C++) namespace |
;; extern language definitions. |
|
;; definitions. |
|
5455 |
(save-excursion |
(save-excursion |
5456 |
(save-restriction |
(save-restriction |
5457 |
(widen) |
(widen) |
5458 |
(if (and inclass-p |
(when (and inclass-p |
5459 |
(progn |
(progn |
5460 |
(goto-char (aref inclass-p 0)) |
(goto-char (aref inclass-p 0)) |
5461 |
(looking-at c-other-decl-block-key))) |
(looking-at c-other-decl-block-key))) |
5462 |
(let ((enclosing (match-string 1))) |
(setq inenclosing-p (match-string 1)) |
5463 |
(cond |
(if (string-equal inenclosing-p "extern") |
5464 |
((string-equal enclosing "extern") |
;; Compatibility with legacy choice of name for the |
5465 |
(setq inenclosing-p 'extern)) |
;; extern-lang syntactic symbols. |
5466 |
((string-equal enclosing "namespace") |
(setq inenclosing-p "extern-lang"))))) |
|
(setq inenclosing-p 'namespace)) |
|
|
))))) |
|
5467 |
|
|
5468 |
;; Init some position variables: |
;; Init some position variables: |
5469 |
;; |
;; |
5530 |
((eq literal 'string) |
((eq literal 'string) |
5531 |
(c-add-syntax 'string (c-point 'bopl))) |
(c-add-syntax 'string (c-point 'bopl))) |
5532 |
;; CASE 2: in a C or C++ style comment. |
;; CASE 2: in a C or C++ style comment. |
5533 |
((memq literal '(c c++)) |
((and (memq literal '(c c++)) |
5534 |
(c-add-syntax literal (car (c-literal-limits lim)))) |
;; This is a kludge for XEmacs where we use |
5535 |
|
;; `buffer-syntactic-context', which doesn't correctly |
5536 |
|
;; recognize "\*/" to end a block comment. |
5537 |
|
;; `parse-partial-sexp' which is used by |
5538 |
|
;; `c-literal-limits' will however do that in most |
5539 |
|
;; versions, which results in that we get nil from |
5540 |
|
;; `c-literal-limits' even when `c-in-literal' claims |
5541 |
|
;; we're inside a comment. |
5542 |
|
(setq placeholder (c-literal-limits lim))) |
5543 |
|
(c-add-syntax literal (car placeholder))) |
5544 |
;; CASE 3: in a cpp preprocessor macro continuation. |
;; CASE 3: in a cpp preprocessor macro continuation. |
5545 |
((and (save-excursion |
((and (save-excursion |
5546 |
(when (c-beginning-of-macro) |
(when (c-beginning-of-macro) |
5569 |
;; CASE 11: an else clause? |
;; CASE 11: an else clause? |
5570 |
((looking-at "else\\>[^_]") |
((looking-at "else\\>[^_]") |
5571 |
(c-beginning-of-statement-1 containing-sexp) |
(c-beginning-of-statement-1 containing-sexp) |
5572 |
(c-add-stmt-syntax 'else-clause t containing-sexp paren-state)) |
(c-add-stmt-syntax 'else-clause nil t nil |
5573 |
|
containing-sexp paren-state)) |
5574 |
;; CASE 12: while closure of a do/while construct? |
;; CASE 12: while closure of a do/while construct? |
5575 |
((and (looking-at "while\\>[^_]") |
((and (looking-at "while\\>[^_]") |
5576 |
(save-excursion |
(save-excursion |
5578 |
'beginning) |
'beginning) |
5579 |
(setq placeholder (point))))) |
(setq placeholder (point))))) |
5580 |
(goto-char placeholder) |
(goto-char placeholder) |
5581 |
(c-add-stmt-syntax 'do-while-closure t containing-sexp paren-state)) |
(c-add-stmt-syntax 'do-while-closure nil t nil |
5582 |
|
containing-sexp paren-state)) |
5583 |
;; CASE 13: A catch or finally clause? This case is simpler |
;; CASE 13: A catch or finally clause? This case is simpler |
5584 |
;; than if-else and do-while, because a block is required |
;; than if-else and do-while, because a block is required |
5585 |
;; after every try, catch and finally. |
;; after every try, catch and finally. |
5601 |
(looking-at "\\(try\\|catch\\)\\>[^_]") |
(looking-at "\\(try\\|catch\\)\\>[^_]") |
5602 |
(setq placeholder (point)))) |
(setq placeholder (point)))) |
5603 |
(goto-char placeholder) |
(goto-char placeholder) |
5604 |
(c-add-stmt-syntax 'catch-clause t containing-sexp paren-state)) |
(c-add-stmt-syntax 'catch-clause nil t nil |
5605 |
|
containing-sexp paren-state)) |
5606 |
;; CASE 18: A substatement we can recognize by keyword. |
;; CASE 18: A substatement we can recognize by keyword. |
5607 |
((save-excursion |
((save-excursion |
5608 |
(and c-opt-block-stmt-key |
(and c-opt-block-stmt-key |
5609 |
(not (eq char-before-ip ?\;)) |
(if (c-mode-is-new-awk-p) |
5610 |
|
(c-awk-prev-line-incomplete-p containing-sexp) ; ACM 2002/3/29 |
5611 |
|
(not (eq char-before-ip ?\;))) |
5612 |
(not (memq char-after-ip '(?\) ?\] ?,))) |
(not (memq char-after-ip '(?\) ?\] ?,))) |
5613 |
(or (not (eq char-before-ip ?})) |
(or (not (eq char-before-ip ?})) |
5614 |
(c-looking-at-inexpr-block-backward c-state-cache)) |
(c-looking-at-inexpr-block-backward c-state-cache)) |
5642 |
;; Necessary to catch e.g. synchronized in Java, |
;; Necessary to catch e.g. synchronized in Java, |
5643 |
;; which can be used both as statement and |
;; which can be used both as statement and |
5644 |
;; modifier. |
;; modifier. |
5645 |
(and (= (c-forward-token-1 1 nil) 0) |
(and (zerop (c-forward-token-2 1 nil)) |
5646 |
(eq (char-after) ?\()) |
(eq (char-after) ?\()) |
5647 |
(looking-at c-opt-block-stmt-key)))) |
(looking-at c-opt-block-stmt-key)))) |
5648 |
(if (eq step-type 'up) |
(if (eq step-type 'up) |
5651 |
(goto-char placeholder) |
(goto-char placeholder) |
5652 |
(cond |
(cond |
5653 |
((eq char-after-ip ?{) |
((eq char-after-ip ?{) |
5654 |
(c-add-stmt-syntax 'substatement-open nil |
(c-add-stmt-syntax 'substatement-open nil nil nil |
5655 |
containing-sexp paren-state)) |
containing-sexp paren-state)) |
5656 |
((save-excursion |
((save-excursion |
5657 |
(goto-char indent-point) |
(goto-char indent-point) |
5658 |
(back-to-indentation) |
(back-to-indentation) |
5659 |
(looking-at c-label-key)) |
(looking-at c-label-key)) |
5660 |
(c-add-stmt-syntax 'substatement-label nil |
(c-add-stmt-syntax 'substatement-label nil nil nil |
5661 |
containing-sexp paren-state)) |
containing-sexp paren-state)) |
5662 |
(t |
(t |
5663 |
(c-add-stmt-syntax 'substatement nil |
(c-add-stmt-syntax 'substatement nil nil nil |
5664 |
containing-sexp paren-state)))) |
containing-sexp paren-state)))) |
5665 |
;; CASE 18B: Some other substatement. This is shared |
;; CASE 18B: Some other substatement. This is shared |
5666 |
;; with case 10. |
;; with case 10. |
5691 |
'lambda-intro-cont))) |
'lambda-intro-cont))) |
5692 |
(goto-char (cdr placeholder)) |
(goto-char (cdr placeholder)) |
5693 |
(back-to-indentation) |
(back-to-indentation) |
5694 |
(c-add-stmt-syntax tmpsymbol t |
(c-add-stmt-syntax tmpsymbol nil t nil |
5695 |
(c-most-enclosing-brace c-state-cache (point)) |
(c-most-enclosing-brace c-state-cache (point)) |
5696 |
(c-whack-state-after (point) paren-state)) |
(c-whack-state-after (point) paren-state)) |
5697 |
(unless (eq (point) (cdr placeholder)) |
(unless (eq (point) (cdr placeholder)) |
5706 |
(c-looking-at-special-brace-list)) |
(c-looking-at-special-brace-list)) |
5707 |
(eq char-after-ip ?{))) |
(eq char-after-ip ?{))) |
5708 |
(cond |
(cond |
5709 |
;; CASE 5A.1: extern language or namespace construct |
;; CASE 5A.1: Non-class declaration block open. |
5710 |
((save-excursion |
((save-excursion |
5711 |
(goto-char indent-point) |
(goto-char indent-point) |
5712 |
(skip-chars-forward " \t") |
(skip-chars-forward " \t") |
5713 |
(and (c-safe (progn (c-backward-sexp 2) t)) |
(and (c-safe (c-backward-sexp 2) t) |
5714 |
(looking-at c-other-decl-block-key) |
(looking-at c-other-decl-block-key) |
5715 |
(setq keyword (match-string 1) |
(setq keyword (match-string 1) |
5716 |
placeholder (point)) |
placeholder (point)) |
5717 |
(or (and (string-equal keyword "namespace") |
(if (string-equal keyword "extern") |
5718 |
(setq tmpsymbol 'namespace-open)) |
;; Special case for extern-lang-open. The |
5719 |
(and (string-equal keyword "extern") |
;; check for a following string is disabled |
5720 |
(progn |
;; since it doesn't disambiguate anything. |
5721 |
(c-forward-sexp 1) |
(and ;;(progn |
5722 |
(c-forward-syntactic-ws) |
;; (c-forward-sexp 1) |
5723 |
(eq (char-after) ?\")) |
;; (c-forward-syntactic-ws) |
5724 |
(setq tmpsymbol 'extern-lang-open))) |
;; (eq (char-after) ?\")) |
5725 |
|
(setq tmpsymbol 'extern-lang-open)) |
5726 |
|
(setq tmpsymbol (intern (concat keyword "-open")))) |
5727 |
)) |
)) |
5728 |
(goto-char placeholder) |
(goto-char placeholder) |
5729 |
(c-add-syntax tmpsymbol (c-point 'boi))) |
(c-add-syntax tmpsymbol (c-point 'boi))) |
5738 |
(c-add-syntax 'class-open placeholder)) |
(c-add-syntax 'class-open placeholder)) |
5739 |
;; CASE 5A.3: brace list open |
;; CASE 5A.3: brace list open |
5740 |
((save-excursion |
((save-excursion |
5741 |
(c-beginning-of-statement-1 lim t) |
(c-beginning-of-decl-1 lim) |
5742 |
(if (looking-at "typedef\\>[^_]") |
(while (looking-at c-specifier-key) |
5743 |
(progn (c-forward-sexp 1) |
(goto-char (match-end 1)) |
5744 |
(c-forward-syntactic-ws indent-point))) |
(c-forward-syntactic-ws indent-point)) |
5745 |
(setq placeholder (c-point 'boi)) |
(setq placeholder (c-point 'boi)) |
5746 |
(or (consp special-brace-list) |
(or (consp special-brace-list) |
5747 |
(and (or (save-excursion |
(and (or (save-excursion |
5748 |
(goto-char indent-point) |
(goto-char indent-point) |
5749 |
(setq tmpsymbol nil) |
(setq tmpsymbol nil) |
5750 |
(while (and (> (point) placeholder) |
(while (and (> (point) placeholder) |
5751 |
(= (c-backward-token-1 1 t) 0) |
(zerop (c-backward-token-2 1 t)) |
5752 |
(/= (char-after) ?=)) |
(/= (char-after) ?=)) |
5753 |
(if (and (not tmpsymbol) |
(and c-opt-inexpr-brace-list-key |
5754 |
(looking-at "new\\>[^_]")) |
(not tmpsymbol) |
5755 |
(setq tmpsymbol 'topmost-intro-cont))) |
(looking-at c-opt-inexpr-brace-list-key) |
5756 |
|
(setq tmpsymbol 'topmost-intro-cont))) |
5757 |
(eq (char-after) ?=)) |
(eq (char-after) ?=)) |
5758 |
(looking-at "enum\\>[^_]")) |
(looking-at c-brace-list-key)) |
5759 |
(save-excursion |
(save-excursion |
5760 |
(while (and (< (point) indent-point) |
(while (and (< (point) indent-point) |
5761 |
(= (c-forward-token-1 1 t) 0) |
(zerop (c-forward-token-2 1 t)) |
5762 |
(not (memq (char-after) '(?\; ?\())))) |
(not (memq (char-after) '(?\; ?\())))) |
5763 |
(not (memq (char-after) '(?\; ?\())) |
(not (memq (char-after) '(?\; ?\())) |
5764 |
)))) |
)))) |
5765 |
(if (and (c-major-mode-is 'java-mode) |
(if (and (not c-auto-newline-analysis) |
5766 |
|
(c-major-mode-is 'java-mode) |
5767 |
(eq tmpsymbol 'topmost-intro-cont)) |
(eq tmpsymbol 'topmost-intro-cont)) |
5768 |
;; We're in Java and have found that the open brace |
;; We're in Java and have found that the open brace |
5769 |
;; belongs to a "new Foo[]" initialization list, |
;; belongs to a "new Foo[]" initialization list, |
5772 |
;; therefore treat it as any topmost continuation |
;; therefore treat it as any topmost continuation |
5773 |
;; even though the semantically correct symbol still |
;; even though the semantically correct symbol still |
5774 |
;; is brace-list-open, on the same grounds as in |
;; is brace-list-open, on the same grounds as in |
5775 |
;; case 10B.2. |
;; case B.2. |
5776 |
(progn |
(progn |
5777 |
(c-beginning-of-statement-1 lim) |
(c-beginning-of-statement-1 lim) |
5778 |
(c-add-syntax 'topmost-intro-cont (c-point 'boi))) |
(c-add-syntax 'topmost-intro-cont (c-point 'boi))) |
5790 |
(c-add-syntax 'defun-open (c-point 'bol))) |
(c-add-syntax 'defun-open (c-point 'bol))) |
5791 |
))) |
))) |
5792 |
;; CASE 5B: first K&R arg decl or member init |
;; CASE 5B: first K&R arg decl or member init |
5793 |
((c-just-after-func-arglist-p nil lim) |
((c-just-after-func-arglist-p lim) |
5794 |
(cond |
(cond |
5795 |
;; CASE 5B.1: a member init |
;; CASE 5B.1: a member init |
5796 |
((or (eq char-before-ip ?:) |
((or (eq char-before-ip ?:) |
5842 |
(when (eq char-after-ip ?,) |
(when (eq char-after-ip ?,) |
5843 |
(skip-chars-forward " \t") |
(skip-chars-forward " \t") |
5844 |
(forward-char)) |
(forward-char)) |
5845 |
(looking-at c-opt-decl-spec-key))) |
(looking-at c-opt-postfix-decl-spec-key))) |
5846 |
(and (or (eq char-before-ip ?:) |
(and (or (eq char-before-ip ?:) |
5847 |
;; watch out for scope operator |
;; watch out for scope operator |
5848 |
(save-excursion |
(save-excursion |
5849 |
(and (eq char-after-ip ?:) |
(and (eq char-after-ip ?:) |
5850 |
(c-safe (progn (forward-char 1) t)) |
(c-safe (forward-char 1) t) |
5851 |
(not (eq (char-after) ?:)) |
(not (eq (char-after) ?:)) |
5852 |
))) |
))) |
5853 |
(save-excursion |
(save-excursion |
5866 |
cont done) |
cont done) |
5867 |
(save-excursion |
(save-excursion |
5868 |
(while (not done) |
(while (not done) |
5869 |
(cond ((looking-at c-opt-decl-spec-key) |
(cond ((looking-at c-opt-postfix-decl-spec-key) |
5870 |
(setq injava-inher (cons cont (point)) |
(setq injava-inher (cons cont (point)) |
5871 |
done t)) |
done t)) |
5872 |
((or (not (c-safe (c-forward-sexp -1) t)) |
((or (not (c-safe (c-forward-sexp -1) t)) |
5923 |
(save-excursion |
(save-excursion |
5924 |
;; Note: We use the fact that lim is always after any |
;; Note: We use the fact that lim is always after any |
5925 |
;; preceding brace sexp. |
;; preceding brace sexp. |
5926 |
(while (and (= (c-backward-token-1 1 t lim) 0) |
(while (and (zerop (c-backward-token-2 1 t lim)) |
5927 |
(not (looking-at "[;<,=]")))) |
(not (looking-at "[;<,=]")))) |
5928 |
(or (memq (char-after) '(?, ?=)) |
(or (memq (char-after) '(?, ?=)) |
5929 |
(and (c-major-mode-is 'c++-mode) |
(and (c-major-mode-is 'c++-mode) |
5930 |
(= (c-backward-token-1 1 nil lim) 0) |
(zerop (c-backward-token-2 1 nil lim)) |
5931 |
(eq (char-after) ?<))))) |
(eq (char-after) ?<))))) |
5932 |
(goto-char indent-point) |
(goto-char indent-point) |
5933 |
(c-beginning-of-member-init-list lim) |
(setq placeholder |
5934 |
|
(c-beginning-of-member-init-list lim)) |
5935 |
(cond |
(cond |
5936 |
;; CASE 5D.1: hanging member init colon, but watch out |
;; CASE 5D.1: hanging member init colon, but watch out |
5937 |
;; for bogus matches on access specifiers inside classes. |
;; for bogus matches on access specifiers inside classes. |
5938 |
((and (save-excursion |
((and placeholder |
5939 |
|
(save-excursion |
5940 |
(setq placeholder (point)) |
(setq placeholder (point)) |
5941 |
(c-backward-token-1 1 t lim) |
(c-backward-token-2 1 t lim) |
5942 |
(and (eq (char-after) ?:) |
(and (eq (char-after) ?:) |
5943 |
(not (eq (char-before) ?:)))) |
(not (eq (char-before) ?:)))) |
5944 |
(save-excursion |
(save-excursion |
5986 |
(c-beginning-of-statement-1 lim) |
(c-beginning-of-statement-1 lim) |
5987 |
(setq placeholder (point)) |
(setq placeholder (point)) |
5988 |
(if (looking-at "static\\>[^_]") |
(if (looking-at "static\\>[^_]") |
5989 |
(c-forward-token-1 1 nil indent-point)) |
(c-forward-token-2 1 nil indent-point)) |
5990 |
(and (looking-at c-class-key) |
(and (looking-at c-class-key) |
5991 |
(= (c-forward-token-1 2 nil indent-point) 0) |
(zerop (c-forward-token-2 2 nil indent-point)) |
5992 |
(if (eq (char-after) ?<) |
(if (eq (char-after) ?<) |
5993 |
(c-with-syntax-table c++-template-syntax-table |
(c-with-syntax-table c++-template-syntax-table |
5994 |
(= (c-forward-token-1 1 t indent-point) 0)) |
(zerop (c-forward-token-2 1 t indent-point))) |
5995 |
t) |
t) |
5996 |
(eq (char-after) ?:)))) |
(eq (char-after) ?:)))) |
5997 |
(goto-char placeholder) |
(goto-char placeholder) |
6012 |
;; the first variable declaration. C.f. case 5N. |
;; the first variable declaration. C.f. case 5N. |
6013 |
'topmost-intro-cont |
'topmost-intro-cont |
6014 |
'statement-cont) |
'statement-cont) |
6015 |
nil containing-sexp paren-state)) |
nil nil nil containing-sexp paren-state)) |
6016 |
)) |
)) |
6017 |
;; CASE 5E: we are looking at a access specifier |
;; CASE 5E: we are looking at a access specifier |
6018 |
((and inclass-p |
((and inclass-p |
6021 |
(setq placeholder (c-add-class-syntax 'inclass inclass-p |
(setq placeholder (c-add-class-syntax 'inclass inclass-p |
6022 |
paren-state)) |
paren-state)) |
6023 |
;; Append access-label with the same anchor point as inclass gets. |
;; Append access-label with the same anchor point as inclass gets. |
6024 |
(nconc syntax (list (cons 'access-label placeholder)))) |
(c-append-syntax 'access-label placeholder)) |
6025 |
;; CASE 5F: extern-lang-close or namespace-close? |
;; CASE 5F: Close of a non-class declaration level block. |
6026 |
((and inenclosing-p |
((and inenclosing-p |
6027 |
(eq char-after-ip ?})) |
(eq char-after-ip ?})) |
6028 |
(setq tmpsymbol (if (eq inenclosing-p 'extern) |
(c-add-syntax (intern (concat inenclosing-p "-close")) |
6029 |
'extern-lang-close |
(aref inclass-p 0))) |
|
'namespace-close)) |
|
|
(c-add-syntax tmpsymbol (aref inclass-p 0))) |
|
6030 |
;; CASE 5G: we are looking at the brace which closes the |
;; CASE 5G: we are looking at the brace which closes the |
6031 |
;; enclosing nested class decl |
;; enclosing nested class decl |
6032 |
((and inclass-p |
((and inclass-p |
6035 |
(save-restriction |
(save-restriction |
6036 |
(widen) |
(widen) |
6037 |
(forward-char 1) |
(forward-char 1) |
6038 |
(and (c-safe (progn (c-backward-sexp 1) t)) |
(and (c-safe (c-backward-sexp 1) t) |
6039 |
(= (point) (aref inclass-p 1)) |
(= (point) (aref inclass-p 1)) |
6040 |
)))) |
)))) |
6041 |
(c-add-class-syntax 'class-close inclass-p paren-state)) |
(c-add-class-syntax 'class-close inclass-p paren-state)) |
6059 |
(looking-at c-opt-method-key)) |
(looking-at c-opt-method-key)) |
6060 |
(c-beginning-of-statement-1 lim) |
(c-beginning-of-statement-1 lim) |
6061 |
(c-add-syntax 'objc-method-intro (c-point 'boi))) |
(c-add-syntax 'objc-method-intro (c-point 'boi))) |
6062 |
|
;; CASE 5P: AWK pattern or function or continuation |
6063 |
|
;; thereof. |
6064 |
|
((c-mode-is-new-awk-p) |
6065 |
|
(setq placeholder (point)) |
6066 |
|
(c-add-stmt-syntax |
6067 |
|
(if (and (eq (c-beginning-of-statement-1) 'same) |
6068 |
|
(/= (point) placeholder)) |
6069 |
|
'topmost-intro-cont |
6070 |
|
'topmost-intro) |
6071 |
|
nil nil nil |
6072 |
|
containing-sexp paren-state)) |
6073 |
;; CASE 5N: At a variable declaration that follows a class |
;; CASE 5N: At a variable declaration that follows a class |
6074 |
;; definition or some other block declaration that doesn't |
;; definition or some other block declaration that doesn't |
6075 |
;; end at the closing '}'. C.f. case 5D.5. |
;; end at the closing '}'. C.f. case 5D.5. |
6089 |
(c-end-of-decl-1) |
(c-end-of-decl-1) |
6090 |
(> (point) indent-point)))))) |
(> (point) indent-point)))))) |
6091 |
(goto-char placeholder) |
(goto-char placeholder) |
6092 |
(c-add-stmt-syntax 'topmost-intro-cont nil |
(c-add-stmt-syntax 'topmost-intro-cont nil nil nil |
6093 |
containing-sexp paren-state)) |
containing-sexp paren-state)) |
6094 |
;; CASE 5J: we are at the topmost level, make |
;; CASE 5J: we are at the topmost level, make |
6095 |
;; sure we skip back past any access specifiers |
;; sure we skip back past any access specifiers |
6098 |
c-opt-access-key |
c-opt-access-key |
6099 |
(not (bobp)) |
(not (bobp)) |
6100 |
(save-excursion |
(save-excursion |
6101 |
(c-safe (progn (c-backward-sexp 1) t)) |
(c-safe (c-backward-sexp 1) t) |
6102 |
(looking-at c-opt-access-key))) |
(looking-at c-opt-access-key))) |
6103 |
(c-backward-sexp 1) |
(c-backward-sexp 1) |
6104 |
(c-backward-syntactic-ws lim)) |
(c-backward-syntactic-ws lim)) |
6105 |
(or (bobp) |
(or (bobp) |
6106 |
(memq (char-before) '(?\; ?})) |
(if (c-mode-is-new-awk-p) |
6107 |
|
(not (c-awk-prev-line-incomplete-p)) |
6108 |
|
(memq (char-before) '(?\; ?}))) |
6109 |
(and (c-major-mode-is 'objc-mode) |
(and (c-major-mode-is 'objc-mode) |
6110 |
(progn |
(progn |
6111 |
(c-beginning-of-statement-1 lim) |
(c-beginning-of-statement-1 lim) |
6122 |
(goto-char (aref inclass-p 1)) |
(goto-char (aref inclass-p 1)) |
6123 |
(or (= (point) (c-point 'boi)) |
(or (= (point) (c-point 'boi)) |
6124 |
(goto-char (aref inclass-p 0))) |
(goto-char (aref inclass-p 0))) |
6125 |
(cond |
(if inenclosing-p |
6126 |
((eq inenclosing-p 'extern) |
(c-add-syntax (intern (concat "in" inenclosing-p)) |
6127 |
(c-add-syntax 'inextern-lang (c-point 'boi))) |
(c-point 'boi)) |
6128 |
((eq inenclosing-p 'namespace) |
(c-add-class-syntax 'inclass inclass-p paren-state)) |
|
(c-add-syntax 'innamespace (c-point 'boi))) |
|
|
(t (c-add-class-syntax 'inclass inclass-p paren-state))) |
|
6129 |
)) |
)) |
6130 |
(when (and c-syntactic-indentation-in-macros |
(when (and c-syntactic-indentation-in-macros |
6131 |
macro-start |
macro-start |
6161 |
(c-looking-at-special-brace-list))) |
(c-looking-at-special-brace-list))) |
6162 |
(eq (char-after containing-sexp) ?{))) |
(eq (char-after containing-sexp) ?{))) |
6163 |
(cond |
(cond |
6164 |
;; CASE 7A: we are looking at the arglist closing paren |
;; CASE 7A: we are looking at the arglist closing paren. |
6165 |
|
;; C.f. case 7F. |
6166 |
((memq char-after-ip '(?\) ?\])) |
((memq char-after-ip '(?\) ?\])) |
6167 |
(goto-char containing-sexp) |
(goto-char containing-sexp) |
6168 |
(setq placeholder (c-point 'boi)) |
(setq placeholder (c-point 'boi)) |
6169 |
(when (and (c-safe (backward-up-list 1) t) |
(if (and (c-safe (backward-up-list 1) t) |
6170 |
(> (point) placeholder)) |
(> (point) placeholder)) |
6171 |
(forward-char) |
(progn |
6172 |
(skip-chars-forward " \t") |
(forward-char) |
6173 |
(setq placeholder (point))) |
(skip-chars-forward " \t")) |
6174 |
(c-add-syntax 'arglist-close placeholder)) |
(goto-char placeholder)) |
6175 |
|
(c-add-stmt-syntax 'arglist-close (list containing-sexp) t nil |
6176 |
|
(c-most-enclosing-brace paren-state (point)) |
6177 |
|
(c-whack-state-after (point) paren-state))) |
6178 |
;; CASE 7B: Looking at the opening brace of an |
;; CASE 7B: Looking at the opening brace of an |
6179 |
;; in-expression block or brace list. C.f. cases 4, 16A |
;; in-expression block or brace list. C.f. cases 4, 16A |
6180 |
;; and 17E. |
;; and 17E. |
6196 |
))) |
))) |
6197 |
(goto-char placeholder) |
(goto-char placeholder) |
6198 |
(back-to-indentation) |
(back-to-indentation) |
6199 |
(c-add-stmt-syntax (car tmpsymbol) t |
(c-add-stmt-syntax (car tmpsymbol) nil t nil |
6200 |
(c-most-enclosing-brace paren-state (point)) |
(c-most-enclosing-brace paren-state (point)) |
6201 |
(c-whack-state-after (point) paren-state)) |
(c-whack-state-after (point) paren-state)) |
6202 |
(if (/= (point) placeholder) |
(if (/= (point) placeholder) |
6217 |
;; these things as statements |
;; these things as statements |
6218 |
((progn |
((progn |
6219 |
(goto-char containing-sexp) |
(goto-char containing-sexp) |
6220 |
(and (c-safe (progn (c-forward-sexp -1) t)) |
(and (c-safe (c-forward-sexp -1) t) |
6221 |
(looking-at "\\<for\\>[^_]"))) |
(looking-at "\\<for\\>[^_]"))) |
6222 |
(goto-char (1+ containing-sexp)) |
(goto-char (1+ containing-sexp)) |
6223 |
(c-forward-syntactic-ws indent-point) |
(c-forward-syntactic-ws indent-point) |
6240 |
;; but the preceding argument is on the same line as the |
;; but the preceding argument is on the same line as the |
6241 |
;; opening paren. This case includes multi-line |
;; opening paren. This case includes multi-line |
6242 |
;; mathematical paren groupings, but we could be on a |
;; mathematical paren groupings, but we could be on a |
6243 |
;; for-list continuation line |
;; for-list continuation line. C.f. case 7A. |
6244 |
((progn |
((progn |
6245 |
(goto-char (1+ containing-sexp)) |
(goto-char (1+ containing-sexp)) |
6246 |
(skip-chars-forward " \t") |
(skip-chars-forward " \t") |
6248 |
(not (looking-at "\\\\$")))) |
(not (looking-at "\\\\$")))) |
6249 |
(goto-char containing-sexp) |
(goto-char containing-sexp) |
6250 |
(setq placeholder (c-point 'boi)) |
(setq placeholder (c-point 'boi)) |
6251 |
(when (and (c-safe (backward-up-list 1) t) |
(if (and (c-safe (backward-up-list 1) t) |
6252 |
(> (point) placeholder)) |
(> (point) placeholder)) |
6253 |
(forward-char) |
(progn |
6254 |
(skip-chars-forward " \t") |
(forward-char) |
6255 |
(setq placeholder (point))) |
(skip-chars-forward " \t")) |
6256 |
(c-add-syntax 'arglist-cont-nonempty placeholder)) |
(goto-char placeholder)) |
6257 |
|
(c-add-stmt-syntax 'arglist-cont-nonempty (list containing-sexp) |
6258 |
|
t nil |
6259 |
|
(c-most-enclosing-brace c-state-cache (point)) |
6260 |
|
(c-whack-state-after (point) paren-state))) |
6261 |
;; CASE 7G: we are looking at just a normal arglist |
;; CASE 7G: we are looking at just a normal arglist |
6262 |
;; continuation line |
;; continuation line |
6263 |
(t (c-forward-syntactic-ws indent-point) |
(t (c-forward-syntactic-ws indent-point) |
6268 |
(save-excursion |
(save-excursion |
6269 |
(goto-char indent-point) |
(goto-char indent-point) |
6270 |
(skip-chars-forward " \t") |
(skip-chars-forward " \t") |
6271 |
(looking-at c-opt-decl-spec-key))) |
(looking-at c-opt-postfix-decl-spec-key))) |
6272 |
(goto-char indent-point) |
(goto-char indent-point) |
6273 |
(skip-chars-forward " \t") |
(skip-chars-forward " \t") |
6274 |
(cond |
(cond |
6285 |
(c-add-syntax 'inher-cont (point)) |
(c-add-syntax 'inher-cont (point)) |
6286 |
))) |
))) |
6287 |
;; CASE 9: we are inside a brace-list |
;; CASE 9: we are inside a brace-list |
6288 |
((setq special-brace-list |
((and (not (c-mode-is-new-awk-p)) ; Maybe this isn't needed (ACM, 2002/3/29) |
6289 |
(or (and c-special-brace-lists |
(setq special-brace-list |
6290 |
(save-excursion |
(or (and c-special-brace-lists |
6291 |
(goto-char containing-sexp) |
(save-excursion |
6292 |
(c-looking-at-special-brace-list))) |
(goto-char containing-sexp) |
6293 |
(c-inside-bracelist-p containing-sexp paren-state))) |
(c-looking-at-special-brace-list))) |
6294 |
|
(c-inside-bracelist-p containing-sexp paren-state)))) |
6295 |
(cond |
(cond |
6296 |
;; CASE 9A: In the middle of a special brace list opener. |
;; CASE 9A: In the middle of a special brace list opener. |
6297 |
((and (consp special-brace-list) |
((and (consp special-brace-list) |
6304 |
(if (and (bolp) |
(if (and (bolp) |
6305 |
(assoc 'statement-cont |
(assoc 'statement-cont |
6306 |
(setq placeholder (c-guess-basic-syntax)))) |
(setq placeholder (c-guess-basic-syntax)))) |
6307 |
(setq syntax placeholder) |
(setq c-syntactic-context placeholder) |
6308 |
(c-beginning-of-statement-1 |
(c-beginning-of-statement-1 |
6309 |
(c-safe-position (1- containing-sexp) paren-state)) |
(c-safe-position (1- containing-sexp) paren-state)) |
6310 |
(c-forward-token-1 0) |
(c-forward-token-2 0) |
6311 |
(if (looking-at "typedef\\>[^_]") (c-forward-token-1 1)) |
(while (looking-at c-specifier-key) |
6312 |
|
(goto-char (match-end 1)) |
6313 |
|
(c-forward-syntactic-ws)) |
6314 |
(c-add-syntax 'brace-list-open (c-point 'boi)))) |
(c-add-syntax 'brace-list-open (c-point 'boi)))) |
6315 |
;; CASE 9B: brace-list-close brace |
;; CASE 9B: brace-list-close brace |
6316 |
((if (consp special-brace-list) |
((if (consp special-brace-list) |
6326 |
(eq (1+ (point)) (cdr (car special-brace-list)))) |
(eq (1+ (point)) (cdr (car special-brace-list)))) |
6327 |
;; We were before the special close char. |
;; We were before the special close char. |
6328 |
(and (eq (char-after) (cdr (cdr special-brace-list))) |
(and (eq (char-after) (cdr (cdr special-brace-list))) |
6329 |
(= (c-forward-token-1) 0) |
(zerop (c-forward-token-2)) |
6330 |
(eq (1+ (point)) (cdr (car special-brace-list))))))) |
(eq (1+ (point)) (cdr (car special-brace-list))))))) |
6331 |
;; Normal brace list check. |
;; Normal brace list check. |
6332 |
(and (eq char-after-ip ?}) |
(and (eq char-after-ip ?}) |
6333 |
(c-safe (progn (goto-char (c-up-list-backward (point))) |
(c-safe (goto-char (c-up-list-backward (point))) t) |
|
t)) |
|
6334 |
(= (point) containing-sexp))) |
(= (point) containing-sexp))) |
6335 |
(if (eq (point) (c-point 'boi)) |
(if (eq (point) (c-point 'boi)) |
6336 |
(c-add-syntax 'brace-list-close (point)) |
(c-add-syntax 'brace-list-close (point)) |
6337 |
(setq lim (c-most-enclosing-brace c-state-cache (point))) |
(setq lim (c-most-enclosing-brace c-state-cache (point))) |
6338 |
(c-beginning-of-statement-1 lim) |
(c-beginning-of-statement-1 lim) |
6339 |
(c-add-stmt-syntax 'brace-list-close t lim |
(c-add-stmt-syntax 'brace-list-close nil t t lim |
6340 |
(c-whack-state-after (point) paren-state) |
(c-whack-state-after (point) paren-state)))) |
|
t))) |
|
6341 |
(t |
(t |
6342 |
;; Prepare for the rest of the cases below by going to the |
;; Prepare for the rest of the cases below by going to the |
6343 |
;; token following the opening brace |
;; token following the opening brace |
6344 |
(if (consp special-brace-list) |
(if (consp special-brace-list) |
6345 |
(progn |
(progn |
6346 |
(goto-char (car (car special-brace-list))) |
(goto-char (car (car special-brace-list))) |
6347 |
(c-forward-token-1 1 nil indent-point)) |
(c-forward-token-2 1 nil indent-point)) |
6348 |
(goto-char containing-sexp)) |
(goto-char containing-sexp)) |
6349 |
(forward-char) |
(forward-char) |
6350 |
(let ((start (point))) |
(let ((start (point))) |
6361 |
(c-add-syntax 'brace-list-intro (point)) |
(c-add-syntax 'brace-list-intro (point)) |
6362 |
(setq lim (c-most-enclosing-brace c-state-cache (point))) |
(setq lim (c-most-enclosing-brace c-state-cache (point))) |
6363 |
(c-beginning-of-statement-1 lim) |
(c-beginning-of-statement-1 lim) |
6364 |
(c-add-stmt-syntax 'brace-list-intro t lim |
(c-add-stmt-syntax 'brace-list-intro nil t t lim |
6365 |
(c-whack-state-after (point) paren-state) |
(c-whack-state-after (point) paren-state)))) |
|
t))) |
|
6366 |
;; CASE 9D: this is just a later brace-list-entry or |
;; CASE 9D: this is just a later brace-list-entry or |
6367 |
;; brace-entry-open |
;; brace-entry-open |
6368 |
(t (if (or (eq char-after-ip ?{) |
(t (if (or (eq char-after-ip ?{) |
6376 |
)) |
)) |
6377 |
)))) |
)))) |
6378 |
;; CASE 10: A continued statement or top level construct. |
;; CASE 10: A continued statement or top level construct. |
6379 |
((and (not (memq char-before-ip '(?\; ?:))) |
((and (if (c-mode-is-new-awk-p) |
6380 |
(or (not (eq char-before-ip ?})) |
(c-awk-prev-line-incomplete-p containing-sexp) ; ACM 2002/3/29 |
6381 |
(c-looking-at-inexpr-block-backward c-state-cache)) |
(and (not (memq char-before-ip '(?\; ?:))) |
6382 |
|
(or (not (eq char-before-ip ?})) |
6383 |
|
(c-looking-at-inexpr-block-backward c-state-cache)))) |
6384 |
(> (point) |
(> (point) |
6385 |
(save-excursion |
(save-excursion |
6386 |
(c-beginning-of-statement-1 containing-sexp) |
(c-beginning-of-statement-1 containing-sexp) |
6397 |
(goto-char containing-sexp) |
(goto-char containing-sexp) |
6398 |
(setq lim (c-most-enclosing-brace c-state-cache containing-sexp)) |
(setq lim (c-most-enclosing-brace c-state-cache containing-sexp)) |
6399 |
(c-backward-to-block-anchor lim) |
(c-backward-to-block-anchor lim) |
6400 |
(c-add-stmt-syntax 'case-label t lim paren-state)) |
(c-add-stmt-syntax 'case-label nil t nil |
6401 |
|
lim paren-state)) |
6402 |
;; CASE 15: any other label |
;; CASE 15: any other label |
6403 |
((looking-at c-label-key) |
((looking-at c-label-key) |
6404 |
(goto-char containing-sexp) |
(goto-char containing-sexp) |
6413 |
'case-label |
'case-label |
6414 |
'label))) |
'label))) |
6415 |
(c-backward-to-block-anchor lim) |
(c-backward-to-block-anchor lim) |
6416 |
(c-add-stmt-syntax tmpsymbol t lim paren-state)) |
(c-add-stmt-syntax tmpsymbol nil t nil |
6417 |
|
lim paren-state)) |
6418 |
;; CASE 16: block close brace, possibly closing the defun or |
;; CASE 16: block close brace, possibly closing the defun or |
6419 |
;; the class |
;; the class |
6420 |
((eq char-after-ip ?}) |
((eq char-after-ip ?}) |
6428 |
;; e.g. a macro argument. |
;; e.g. a macro argument. |
6429 |
((c-after-conditional) |
((c-after-conditional) |
6430 |
(c-backward-to-block-anchor lim) |
(c-backward-to-block-anchor lim) |
6431 |
(c-add-stmt-syntax 'block-close t lim paren-state)) |
(c-add-stmt-syntax 'block-close nil t nil |
6432 |
|
lim paren-state)) |
6433 |
;; CASE 16A: closing a lambda defun or an in-expression |
;; CASE 16A: closing a lambda defun or an in-expression |
6434 |
;; block? C.f. cases 4, 7B and 17E. |
;; block? C.f. cases 4, 7B and 17E. |
6435 |
((setq placeholder (c-looking-at-inexpr-block |
((setq placeholder (c-looking-at-inexpr-block |
6444 |
(c-add-syntax tmpsymbol (point)) |
(c-add-syntax tmpsymbol (point)) |
6445 |
(goto-char (cdr placeholder)) |
(goto-char (cdr placeholder)) |
6446 |
(back-to-indentation) |
(back-to-indentation) |
6447 |
(c-add-stmt-syntax tmpsymbol t |
(c-add-stmt-syntax tmpsymbol nil t nil |
6448 |
(c-most-enclosing-brace paren-state (point)) |
(c-most-enclosing-brace paren-state (point)) |
6449 |
(c-whack-state-after (point) paren-state)) |
(c-whack-state-after (point) paren-state)) |
6450 |
(if (/= (point) (cdr placeholder)) |
(if (/= (point) (cdr placeholder)) |
6451 |
(c-add-syntax (car placeholder))))) |
(c-add-syntax (car placeholder))))) |
6452 |
;; CASE 16B: does this close an inline or a function in |
;; CASE 16B: does this close an inline or a function in |
6453 |
;; an extern block or namespace? |
;; a non-class declaration level block? |
6454 |
((setq placeholder (c-search-uplist-for-classkey paren-state)) |
((setq placeholder (c-search-uplist-for-classkey paren-state)) |
6455 |
(c-backward-to-decl-anchor lim) |
(c-backward-to-decl-anchor lim) |
6456 |
(back-to-indentation) |
(back-to-indentation) |
6474 |
(back-to-indentation) |
(back-to-indentation) |
6475 |
(if (/= (point) containing-sexp) |
(if (/= (point) containing-sexp) |
6476 |
(goto-char placeholder)) |
(goto-char placeholder)) |
6477 |
(c-add-stmt-syntax 'defun-close t lim paren-state)) |
(c-add-stmt-syntax 'defun-close nil t nil |
6478 |
|
lim paren-state)) |
6479 |
;; CASE 16C: if there an enclosing brace that hasn't |
;; CASE 16C: if there an enclosing brace that hasn't |
6480 |
;; been narrowed out by a class, then this is a |
;; been narrowed out by a class, then this is a |
6481 |
;; block-close. C.f. case 17H. |
;; block-close. C.f. case 17H. |
6494 |
(goto-char containing-sexp) |
(goto-char containing-sexp) |
6495 |
;; c-backward-to-block-anchor not necessary here; those |
;; c-backward-to-block-anchor not necessary here; those |
6496 |
;; situations are handled in case 16E above. |
;; situations are handled in case 16E above. |
6497 |
(c-add-stmt-syntax 'block-close t lim paren-state))) |
(c-add-stmt-syntax 'block-close nil t nil |
6498 |
|
lim paren-state))) |
6499 |
;; CASE 16D: find out whether we're closing a top-level |
;; CASE 16D: find out whether we're closing a top-level |
6500 |
;; class or a defun |
;; class or a defun |
6501 |
(t |
(t |
6526 |
;; CASE 17B: continued statement |
;; CASE 17B: continued statement |
6527 |
((and (eq step-type 'same) |
((and (eq step-type 'same) |
6528 |
(/= (point) indent-point)) |
(/= (point) indent-point)) |
6529 |
(c-add-stmt-syntax 'statement-cont nil |
(c-add-stmt-syntax 'statement-cont nil nil nil |
6530 |
containing-sexp paren-state)) |
containing-sexp paren-state)) |
6531 |
;; CASE 17A: After a case/default label? |
;; CASE 17A: After a case/default label? |
6532 |
((progn |
((progn |
6538 |
(c-add-stmt-syntax (if (eq char-after-ip ?{) |
(c-add-stmt-syntax (if (eq char-after-ip ?{) |
6539 |
'statement-case-open |
'statement-case-open |
6540 |
'statement-case-intro) |
'statement-case-intro) |
6541 |
t containing-sexp paren-state)) |
nil t nil containing-sexp paren-state)) |
6542 |
;; CASE 17D: any old statement |
;; CASE 17D: any old statement |
6543 |
((progn |
((progn |
6544 |
(while (eq step-type 'label) |
(while (eq step-type 'label) |
6545 |
(setq step-type |
(setq step-type |
6546 |
(c-beginning-of-statement-1 containing-sexp))) |
(c-beginning-of-statement-1 containing-sexp))) |
6547 |
(eq step-type 'previous)) |
(eq step-type 'previous)) |
6548 |
(c-add-stmt-syntax 'statement t containing-sexp paren-state) |
(c-add-stmt-syntax 'statement nil t nil |
6549 |
|
containing-sexp paren-state) |
6550 |
(if (eq char-after-ip ?{) |
(if (eq char-after-ip ?{) |
6551 |
(c-add-syntax 'block-open))) |
(c-add-syntax 'block-open))) |
6552 |
;; CASE 17I: Inside a substatement block. |
;; CASE 17I: Inside a substatement block. |
6557 |
(setq lim (c-most-enclosing-brace paren-state containing-sexp)) |
(setq lim (c-most-enclosing-brace paren-state containing-sexp)) |
6558 |
(c-after-conditional)) |
(c-after-conditional)) |
6559 |
(c-backward-to-block-anchor lim) |
(c-backward-to-block-anchor lim) |
6560 |
(c-add-stmt-syntax 'statement-block-intro t lim paren-state) |
(c-add-stmt-syntax 'statement-block-intro nil t nil |
6561 |
|
lim paren-state) |
6562 |
(if (eq char-after-ip ?{) |
(if (eq char-after-ip ?{) |
6563 |
(c-add-syntax 'block-open))) |
(c-add-syntax 'block-open))) |
6564 |
;; CASE 17E: first statement in an in-expression block. |
;; CASE 17E: first statement in an in-expression block. |
6574 |
(c-add-syntax tmpsymbol (point)) |
(c-add-syntax tmpsymbol (point)) |
6575 |
(goto-char (cdr placeholder)) |
(goto-char (cdr placeholder)) |
6576 |
(back-to-indentation) |
(back-to-indentation) |
6577 |
(c-add-stmt-syntax tmpsymbol t |
(c-add-stmt-syntax tmpsymbol nil t nil |
6578 |
(c-most-enclosing-brace c-state-cache (point)) |
(c-most-enclosing-brace c-state-cache (point)) |
6579 |
(c-whack-state-after (point) paren-state)) |
(c-whack-state-after (point) paren-state)) |
6580 |
(if (/= (point) (cdr placeholder)) |
(if (/= (point) (cdr placeholder)) |
6585 |
;; statement in a top-level defun. we can tell this is it |
;; statement in a top-level defun. we can tell this is it |
6586 |
;; if there are no enclosing braces that haven't been |
;; if there are no enclosing braces that haven't been |
6587 |
;; narrowed out by a class (i.e. don't use bod here). |
;; narrowed out by a class (i.e. don't use bod here). |
|
;; However, we first check for statements that we can |
|
|
;; recognize by keywords. That increases the robustness in |
|
|
;; cases where statements are used on the top level, |
|
|
;; e.g. in macro definitions. |
|
6588 |
((save-excursion |
((save-excursion |
6589 |
(save-restriction |
(save-restriction |
6590 |
(widen) |
(widen) |
6605 |
(back-to-indentation) |
(back-to-indentation) |
6606 |
(if (/= (point) containing-sexp) |
(if (/= (point) containing-sexp) |
6607 |
(goto-char placeholder)) |
(goto-char placeholder)) |
6608 |
(c-add-stmt-syntax 'defun-block-intro t lim paren-state)) |
(c-add-stmt-syntax 'defun-block-intro nil t nil |
6609 |
|
lim paren-state)) |
6610 |
;; CASE 17H: First statement in a block. C.f. case 16C. |
;; CASE 17H: First statement in a block. C.f. case 16C. |
6611 |
(t |
(t |
6612 |
;; If the block is preceded by a case/switch label on the |
;; If the block is preceded by a case/switch label on the |
6622 |
(goto-char containing-sexp) |
(goto-char containing-sexp) |
6623 |
;; c-backward-to-block-anchor not necessary here; those |
;; c-backward-to-block-anchor not necessary here; those |
6624 |
;; situations are handled in case 17I above. |
;; situations are handled in case 17I above. |
6625 |
(c-add-stmt-syntax 'statement-block-intro t lim paren-state)) |
(c-add-stmt-syntax 'statement-block-intro nil t nil |
6626 |
|
lim paren-state)) |
6627 |
(if (eq char-after-ip ?{) |
(if (eq char-after-ip ?{) |
6628 |
(c-add-syntax 'block-open))) |
(c-add-syntax 'block-open))) |
6629 |
)) |
)) |
6633 |
(skip-chars-forward " \t") |
(skip-chars-forward " \t") |
6634 |
;; are we looking at a comment only line? |
;; are we looking at a comment only line? |
6635 |
(when (and (looking-at c-comment-start-regexp) |
(when (and (looking-at c-comment-start-regexp) |
6636 |
(/= (c-forward-token-1 0 nil (c-point 'eol)) 0)) |
(/= (c-forward-token-2 0 nil (c-point 'eol)) 0)) |
6637 |
(c-add-syntax 'comment-intro)) |
(c-append-syntax 'comment-intro)) |
6638 |
;; we might want to give additional offset to friends (in C++). |
;; we might want to give additional offset to friends (in C++). |
6639 |
(when (and c-opt-friend-key |
(when (and c-opt-friend-key |
6640 |
(looking-at c-opt-friend-key)) |
(looking-at c-opt-friend-key)) |
6641 |
(c-add-syntax 'friend)) |
(c-append-syntax 'friend)) |
6642 |
|
|
6643 |
|
;; Set syntactic-relpos. |
6644 |
|
(let ((p c-syntactic-context)) |
6645 |
|
(while (and p |
6646 |
|
(if (integerp (car-safe (cdr-safe (car p)))) |
6647 |
|
(progn |
6648 |
|
(setq syntactic-relpos (car (cdr (car p)))) |
6649 |
|
nil) |
6650 |
|
t)) |
6651 |
|
(setq p (cdr p)))) |
6652 |
|
|
6653 |
;; Start of or a continuation of a preprocessor directive? |
;; Start of or a continuation of a preprocessor directive? |
6654 |
(if (and macro-start |
(if (and macro-start |
6655 |
(eq macro-start (c-point 'boi)) |
(eq macro-start (c-point 'boi)) |
6656 |
(not (and (c-major-mode-is 'pike-mode) |
(not (and (c-major-mode-is 'pike-mode) |
6657 |
(eq (char-after (1+ macro-start)) ?\")))) |
(eq (char-after (1+ macro-start)) ?\")))) |
6658 |
(c-add-syntax 'cpp-macro) |
(c-append-syntax 'cpp-macro) |
6659 |
(when (and c-syntactic-indentation-in-macros macro-start) |
(when (and c-syntactic-indentation-in-macros macro-start) |
6660 |
(if in-macro-expr |
(if in-macro-expr |
6661 |
(when (or (< syntactic-relpos macro-start) |
(when (or |
6662 |
(not (or (assq 'arglist-intro syntax) |
(< syntactic-relpos macro-start) |
6663 |
(assq 'arglist-cont syntax) |
(not (or |
6664 |
(assq 'arglist-cont-nonempty syntax) |
(assq 'arglist-intro c-syntactic-context) |
6665 |
(assq 'arglist-close syntax)))) |
(assq 'arglist-cont c-syntactic-context) |
6666 |
|
(assq 'arglist-cont-nonempty c-syntactic-context) |
6667 |
|
(assq 'arglist-close c-syntactic-context)))) |
6668 |
;; If inside a cpp expression, i.e. anywhere in a |
;; If inside a cpp expression, i.e. anywhere in a |
6669 |
;; cpp directive except a #define body, we only let |
;; cpp directive except a #define body, we only let |
6670 |
;; through the syntactic analysis that is internal |
;; through the syntactic analysis that is internal |
6671 |
;; in the expression. That means the arglist |
;; in the expression. That means the arglist |
6672 |
;; elements, if they are anchored inside the cpp |
;; elements, if they are anchored inside the cpp |
6673 |
;; expression. |
;; expression. |
6674 |
(setq syntax `((cpp-macro-cont . ,macro-start)))) |
(setq c-syntactic-context nil) |
6675 |
|
(c-add-syntax 'cpp-macro-cont macro-start)) |
6676 |
(when (and (eq macro-start syntactic-relpos) |
(when (and (eq macro-start syntactic-relpos) |
6677 |
(not (assq 'cpp-define-intro syntax)) |
(not (assq 'cpp-define-intro c-syntactic-context)) |
6678 |
(save-excursion |
(save-excursion |
6679 |
(goto-char macro-start) |
(goto-char macro-start) |
6680 |
(or (not (c-forward-to-cpp-define-body)) |
(or (not (c-forward-to-cpp-define-body)) |
6685 |
;; indentation of the #define body. |
;; indentation of the #define body. |
6686 |
(c-add-syntax 'cpp-define-intro))))) |
(c-add-syntax 'cpp-define-intro))))) |
6687 |
;; return the syntax |
;; return the syntax |
6688 |
syntax)))) |
c-syntactic-context)))) |
6689 |
|
|
6690 |
|
|
6691 |
(defun c-echo-parsing-error (&optional quiet) |
;; Indentation calculation. |
|
(when (and c-report-syntactic-errors c-parsing-error (not quiet)) |
|
|
(c-benign-error "%s" c-parsing-error)) |
|
|
c-parsing-error) |
|
6692 |
|
|
6693 |
(defun c-evaluate-offset (offset langelem symbol) |
(defun c-evaluate-offset (offset langelem symbol) |
6694 |
;; offset can be a number, a function, a variable, a list, or one of |
;; offset can be a number, a function, a variable, a list, or one of |
6702 |
((eq offset '/) (/ (- c-basic-offset) 2)) |
((eq offset '/) (/ (- c-basic-offset) 2)) |
6703 |
((numberp offset) offset) |
((numberp offset) offset) |
6704 |
((functionp offset) (c-evaluate-offset |
((functionp offset) (c-evaluate-offset |
6705 |
(funcall offset langelem) langelem symbol)) |
(funcall offset |
6706 |
|
(cons (car langelem) |
6707 |
|
(car-safe (cdr langelem)))) |
6708 |
|
langelem symbol)) |
6709 |
((vectorp offset) offset) |
((vectorp offset) offset) |
6710 |
((null offset) nil) |
((null offset) nil) |
6711 |
((listp offset) |
((listp offset) |
6719 |
(t (symbol-value offset)) |
(t (symbol-value offset)) |
6720 |
)) |
)) |
6721 |
|
|
6722 |
(defun c-get-offset (langelem) |
(defun c-calc-offset (langelem) |
6723 |
"Get offset from LANGELEM which is a cons cell of the form: |
;; Get offset from LANGELEM which is a list beginning with the |
6724 |
\(SYMBOL . RELPOS). The symbol is matched against `c-offsets-alist' |
;; syntactic symbol and followed by any analysis data it provides. |
6725 |
and the offset found there is returned." |
;; That data may be zero or more elements, but if at least one is |
6726 |
|
;; given then the first is the relpos (or nil). The symbol is |
6727 |
|
;; matched against `c-offsets-alist' and the offset calculated from |
6728 |
|
;; that is returned. |
6729 |
(let* ((symbol (car langelem)) |
(let* ((symbol (car langelem)) |
6730 |
(match (assq symbol c-offsets-alist)) |
(match (assq symbol c-offsets-alist)) |
6731 |
(offset (cdr-safe match))) |
(offset (cdr-safe match))) |
6741 |
0)) |
0)) |
6742 |
)) |
)) |
6743 |
|
|
6744 |
|
(defun c-get-offset (langelem) |
6745 |
|
;; This is a compatibility wrapper for `c-calc-offset' in case |
6746 |
|
;; someone is calling it directly. It takes an old style syntactic |
6747 |
|
;; element on the form (SYMBOL . RELPOS) and converts it to the new |
6748 |
|
;; list form. |
6749 |
|
(if (cdr langelem) |
6750 |
|
(c-calc-offset (list (car langelem) (cdr langelem))) |
6751 |
|
(c-calc-offset langelem))) |
6752 |
|
|
6753 |
(defun c-get-syntactic-indentation (langelems) |
(defun c-get-syntactic-indentation (langelems) |
6754 |
"Apply `c-get-offset' to a list of langelem cells to get the total |
;; Calculate the syntactic indentation from a syntactic description |
6755 |
syntactic indentation. The anchor position, whose column is used as a |
;; as returned by `c-guess-syntax'. |
6756 |
base for all the collected offsets, is taken from the first element |
;; |
|
with a relpos." |
|
6757 |
;; Note that topmost-intro always has a relpos at bol, for |
;; Note that topmost-intro always has a relpos at bol, for |
6758 |
;; historical reasons. It's often used together with other symbols |
;; historical reasons. It's often used together with other symbols |
6759 |
;; that has more sane positions. Since we always use the first |
;; that has more sane positions. Since we always use the first |
6760 |
;; found relpos, we rely on that these other symbols always precede |
;; found relpos, we rely on that these other symbols always precede |
6761 |
;; topmost-intro in the LANGELEMS list. |
;; topmost-intro in the LANGELEMS list. |
6762 |
(let ((indent 0) anchor) |
(let ((indent 0) anchor) |
6763 |
(catch 'done |
|
6764 |
(while langelems |
(while langelems |
6765 |
(let ((res (c-get-offset (car langelems)))) |
(let* ((c-syntactic-element (car langelems)) |
6766 |
(if (vectorp res) |
(res (c-calc-offset c-syntactic-element))) |
6767 |
(throw 'done (elt res 0)) |
|
6768 |
(unless anchor |
(if (vectorp res) |
6769 |
(let ((relpos (cdr (car langelems)))) |
;; Got an absolute column that overrides any indentation |
6770 |
(if relpos |
;; we've collected so far, but not the relative |
6771 |
(setq anchor relpos)))) |
;; indentation we might get for the nested structures |
6772 |
(setq indent (+ indent res) |
;; further down the langelems list. |
6773 |
langelems (cdr langelems))))) |
(setq indent (elt res 0) |
6774 |
(+ indent |
anchor (point-min)) ; A position at column 0. |
6775 |
(if anchor |
|
6776 |
(save-excursion |
;; Got a relative change of the current calculated |
6777 |
(goto-char anchor) |
;; indentation. |
6778 |
(current-column)) |
(setq indent (+ indent res)) |
6779 |
0))))) |
|
6780 |
|
;; Use the anchor position from the first syntactic |
6781 |
|
;; element with one. |
6782 |
|
(unless anchor |
6783 |
|
(let ((relpos (car-safe (cdr (car langelems))))) |
6784 |
|
(if relpos |
6785 |
|
(setq anchor relpos))))) |
6786 |
|
|
6787 |
|
(setq langelems (cdr langelems)))) |
6788 |
|
|
6789 |
|
(if anchor |
6790 |
|
(+ indent (save-excursion |
6791 |
|
(goto-char anchor) |
6792 |
|
(current-column))) |
6793 |
|
indent))) |
6794 |
|
|
6795 |
|
|
6796 |
(cc-provide 'cc-engine) |
(cc-provide 'cc-engine) |