;; The last position where a label is possible provided the
;; statement started there. It's nil as long as no invalid
;; label content has been found (according to
- ;; `c-nonlabel-token-key'. It's `start' if no valid label
+ ;; `c-nonlabel-token-key'). It's `start' if no valid label
;; content was found in the label. Note that we might still
;; regard it a label if it starts with `c-label-kwds'.
label-good-pos
+ ;; Putative positions of the components of a bitfield declaration,
+ ;; e.g. "int foo : NUM_FOO_BITS ;"
+ bitfield-type-pos bitfield-id-pos bitfield-size-pos
;; Symbol just scanned back over (e.g. 'while or 'boundary).
;; See above.
sym
;; Record this as the first token if not starting inside it.
(setq tok start))
- ;; The following while loop goes back one sexp (balanced parens,
- ;; etc. with contents, or symbol or suchlike) each iteration. This
- ;; movement is accomplished with a call to scan-sexps approx 130 lines
- ;; below.
+
+ ;; The following while loop goes back one sexp (balanced parens,
+ ;; etc. with contents, or symbol or suchlike) each iteration. This
+ ;; movement is accomplished with a call to c-backward-sexp approx 170
+ ;; lines below.
+ ;;
+ ;; The loop is exited only by throwing nil to the (catch 'loop ...):
+ ;; 1. On reaching the start of a macro;
+ ;; 2. On having passed a stmt boundary with the PDA stack empty;
+ ;; 3. On reaching the start of an Objective C method def;
+ ;; 4. From macro `c-bos-pop-state'; when the stack is empty;
+ ;; 5. From macro `c-bos-pop-state-and-retry' when the stack is empty.
(while
(catch 'loop ;; Throw nil to break, non-nil to continue.
(cond
+ ;; Are we in a macro, just after the opening #?
((save-excursion
(and macro-start ; Always NIL for AWK.
(progn (skip-chars-backward " \t")
(setq pos saved
ret 'macro
ignore-labels t))
- (throw 'loop nil))
+ (throw 'loop nil)) ; 1. Start of macro.
;; Do a round through the automaton if we've just passed a
;; statement boundary or passed a "while"-like token.
(setq sym (intern (match-string 1)))))
(when (and (< pos start) (null stack))
- (throw 'loop nil))
+ (throw 'loop nil)) ; 2. Statement boundary.
;; The PDA state handling.
;;
;; HERE IS THE SINGLE PLACE INSIDE THE PDA LOOP WHERE WE MOVE
;; BACKWARDS THROUGH THE SOURCE.
- ;; This is typically fast with the caching done by
- ;; c-(backward|forward)-sws.
(c-backward-syntactic-ws)
-
(let ((before-sws-pos (point))
- ;; Set as long as we have to continue jumping by sexps.
- ;; It's the position to use as end in the next round.
- sexp-loop-continue-pos
;; The end position of the area to search for statement
;; barriers in this round.
- (sexp-loop-end-pos pos))
+ (maybe-after-boundary-pos pos))
- ;; The following while goes back one sexp per iteration.
+ ;; Go back over exactly one logical sexp, taking proper
+ ;; account of macros and escaped EOLs.
(while
(progn
(unless (c-safe (c-backward-sexp) t)
;; stack won't be empty the code below will report a
;; suitable error.
(throw 'loop nil))
-
- ;; Check if the sexp movement crossed a statement or
- ;; declaration boundary. But first modify the point
- ;; so that `c-crosses-statement-barrier-p' only looks
- ;; at the non-sexp chars following the sexp.
- (save-excursion
- (when (setq
- boundary-pos
- (cond
- ((if macro-start
- nil
- (save-excursion
- (when (c-beginning-of-macro)
- ;; Set continuation position in case
- ;; `c-crosses-statement-barrier-p'
- ;; doesn't detect anything below.
- (setq sexp-loop-continue-pos (point)))))
- ;; If the sexp movement took us into a
- ;; macro then there were only some non-sexp
- ;; chars after it. Skip out of the macro
- ;; to analyze them but not the non-sexp
- ;; chars that might be inside the macro.
- (c-end-of-macro)
- (c-crosses-statement-barrier-p
- (point) sexp-loop-end-pos))
-
- ((and
- (eq (char-after) ?{)
- (not (c-looking-at-inexpr-block lim nil t)))
- ;; Passed a block sexp. That's a boundary
- ;; alright.
- (point))
-
- ((looking-at "\\s\(")
- ;; Passed some other paren. Only analyze
- ;; the non-sexp chars after it.
- (goto-char (1+ (c-down-list-backward
- before-sws-pos)))
- ;; We're at a valid token start position
- ;; (outside the `save-excursion') if
- ;; `c-crosses-statement-barrier-p' failed.
- (c-crosses-statement-barrier-p
- (point) sexp-loop-end-pos))
-
- (t
- ;; Passed a symbol sexp or line
- ;; continuation. It doesn't matter that
- ;; it's included in the analyzed region.
- (if (c-crosses-statement-barrier-p
- (point) sexp-loop-end-pos)
- t
- ;; If it was a line continuation then we
- ;; have to continue looping.
- (if (looking-at "\\\\$")
- (setq sexp-loop-continue-pos (point)))
- nil))))
-
- (setq pptok ptok
- ptok tok
- tok boundary-pos
- sym 'boundary)
- ;; Like a C "continue". Analyze the next sexp.
- (throw 'loop t)))
-
- sexp-loop-continue-pos) ; End of "go back a sexp" loop condition.
- (goto-char sexp-loop-continue-pos)
- (setq sexp-loop-end-pos sexp-loop-continue-pos
- sexp-loop-continue-pos nil))))
+ (cond
+ ;; Have we moved into a macro?
+ ((and (not macro-start)
+ (c-beginning-of-macro))
+ ;; Have we crossed a statement boundary? If not,
+ ;; keep going back until we find one or a "real" sexp.
+ (and
+ (save-excursion
+ (c-end-of-macro)
+ (not (c-crosses-statement-barrier-p
+ (point) maybe-after-boundary-pos)))
+ (setq maybe-after-boundary-pos (point))))
+ ;; Have we just gone back over an escaped NL? This
+ ;; doesn't count as a sexp.
+ ((looking-at "\\\\$")))))
+
+ ;; Have we crossed a statement boundary?
+ (setq boundary-pos
+ (cond
+ ;; Are we at a macro beginning?
+ ((and (not macro-start)
+ c-opt-cpp-prefix
+ (looking-at c-opt-cpp-prefix))
+ (save-excursion
+ (c-end-of-macro)
+ (c-crosses-statement-barrier-p
+ (point) maybe-after-boundary-pos)))
+ ;; Just gone back over a brace block?
+ ((and
+ (eq (char-after) ?{)
+ (not (c-looking-at-inexpr-block lim nil t)))
+ (save-excursion
+ (c-forward-sexp) (point)))
+ ;; Just gone back over some paren block?
+ ((looking-at "\\s\(")
+ (save-excursion
+ (goto-char (1+ (c-down-list-backward
+ before-sws-pos)))
+ (c-crosses-statement-barrier-p
+ (point) maybe-after-boundary-pos)))
+ ;; Just gone back over an ordinary symbol of some sort?
+ (t (c-crosses-statement-barrier-p
+ (point) maybe-after-boundary-pos))))
+
+ (when boundary-pos
+ (setq pptok ptok
+ ptok tok
+ tok boundary-pos
+ sym 'boundary)
+ ;; Like a C "continue". Analyze the next sexp.
+ (throw 'loop t))))
;; ObjC method def?
(when (and c-opt-method-key
(setq saved (c-in-method-def-p)))
(setq pos saved
ignore-labels t) ; Avoid the label check on exit.
- (throw 'loop nil))
+ (throw 'loop nil)) ; 3. ObjC method def.
+
+ ;; Might we have a bitfield declaration, "<type> <id> : <size>"?
+ (if c-has-bitfields
+ (cond
+ ;; The : <size> and <id> fields?
+ ((and (numberp c-maybe-labelp)
+ (not bitfield-size-pos)
+ (save-excursion
+ (goto-char (or tok start))
+ (not (looking-at c-keywords-regexp)))
+ (not (looking-at c-keywords-regexp))
+ (not (c-punctuation-in (point) c-maybe-labelp)))
+ (setq bitfield-size-pos (or tok start)
+ bitfield-id-pos (point)))
+ ;; The <type> field?
+ ((and bitfield-id-pos
+ (not bitfield-type-pos))
+ (if (and (looking-at c-symbol-key) ; Can only be an integer type. :-)
+ (not (looking-at c-not-primitive-type-keywords-regexp))
+ (not (c-punctuation-in (point) tok)))
+ (setq bitfield-type-pos (point))
+ (setq bitfield-size-pos nil
+ bitfield-id-pos nil)))))
;; Handle labels.
(unless (eq ignore-labels t)
;; (including a case label) or something like C++'s "public:"?
;; A case label might use an expression rather than a token.
(setq after-case:-pos (or tok start))
- (if (looking-at c-nonlabel-token-key) ; e.g. "while" or "'a'"
+ (if (or (looking-at c-nonlabel-token-key) ; e.g. "while" or "'a'"
+ ;; Catch C++'s inheritance construct "class foo : bar".
+ (save-excursion
+ (and
+ (c-safe (c-backward-sexp) t)
+ (looking-at c-nonlabel-token-2-key))))
(setq c-maybe-labelp nil)
(if after-labels-pos ; Have we already encountered a label?
(if (not last-label-pos)
pptok ptok
ptok tok
tok (point)
- pos tok))) ; Not nil (for the while loop).
+ pos tok) ; always non-nil
+ ) ; end of (catch loop ....)
+ ) ; end of sexp-at-a-time (while ....)
;; If the stack isn't empty there might be errors to report.
(while stack
(eq c-maybe-labelp t)
(not (eq ret 'beginning))
after-labels-pos
+ (not bitfield-type-pos) ; Bitfields take precedence over labels.
(or (not label-good-pos)
(<= label-good-pos pos)
(progn
(goto-char pos)
ret)))
+(defun c-punctuation-in (from to)
+ "Return non-nil if there is a non-comment non-macro punctuation character
+between FROM and TO. FROM must not be in a string or comment. The returned
+value is the position of the first such character."
+ (save-excursion
+ (goto-char from)
+ (let ((pos (point)))
+ (while (progn (skip-chars-forward c-symbol-chars to)
+ (c-forward-syntactic-ws to)
+ (> (point) pos))
+ (setq pos (point))))
+ (and (< (point) to) (point))))
+
(defun c-crosses-statement-barrier-p (from to)
"Return non-nil if buffer positions FROM to TO cross one or more
statement or declaration boundaries. The returned value is actually
Note that this function might do hidden buffer changes. See the
comment at the start of cc-engine.el for more info."
- (let ((skip-chars c-stmt-delim-chars)
- lit-range)
- (save-excursion
- (catch 'done
- (goto-char from)
- (while (progn (skip-chars-forward skip-chars to)
- (< (point) to))
- (cond
- ((setq lit-range (c-literal-limits from)) ; Have we landed in a string/comment?
- (goto-char (cdr lit-range)))
- ((eq (char-after) ?:)
- (forward-char)
- (if (and (eq (char-after) ?:)
- (< (point) to))
- ;; Ignore scope operators.
- (forward-char)
- (setq c-maybe-labelp (1- (point)))))
- ((eq (char-after) ??)
- ;; A question mark. Can't be a label, so stop
- ;; looking for more : and ?.
- (setq c-maybe-labelp nil
- skip-chars (substring c-stmt-delim-chars 0 -2)))
- ((memq (char-after) '(?# ?\n ?\r)) ; A virtual semicolon?
- (if (and (eq (char-before) ?\\) (memq (char-after) '(?\n ?\r)))
- (backward-char))
- (skip-chars-backward " \t" from)
- (if (c-at-vsemi-p)
- (throw 'done (point))
- (forward-line)))
- (t (throw 'done (point)))))
- ;; In trailing space after an as yet undetected virtual semicolon?
- (c-backward-syntactic-ws from)
- (if (and (< (point) to)
- (c-at-vsemi-p))
- (point)
- nil)))))
+ (let* ((skip-chars
+ ;; If the current language has CPP macros, insert # into skip-chars.
+ (if c-opt-cpp-symbol
+ (concat (substring c-stmt-delim-chars 0 1) ; "^"
+ c-opt-cpp-symbol ; usually "#"
+ (substring c-stmt-delim-chars 1)) ; e.g. ";{}?:"
+ c-stmt-delim-chars))
+ (non-skip-list
+ (append (substring skip-chars 1) nil)) ; e.g. (?# ?\; ?{ ?} ?? ?:)
+ lit-range vsemi-pos)
+ (save-restriction
+ (widen)
+ (save-excursion
+ (catch 'done
+ (goto-char from)
+ (while (progn (skip-chars-forward
+ skip-chars
+ (min to (c-point 'bonl)))
+ (< (point) to))
+ (cond
+ ;; Virtual semicolon?
+ ((and (bolp)
+ (save-excursion
+ (progn
+ (if (setq lit-range (c-literal-limits from)) ; Have we landed in a string/comment?
+ (goto-char (car lit-range)))
+ (c-backward-syntactic-ws) ; ? put a limit here, maybe?
+ (setq vsemi-pos (point))
+ (c-at-vsemi-p))))
+ (throw 'done vsemi-pos))
+ ;; In a string/comment?
+ ((setq lit-range (c-literal-limits))
+ (goto-char (cdr lit-range)))
+ ((eq (char-after) ?:)
+ (forward-char)
+ (if (and (eq (char-after) ?:)
+ (< (point) to))
+ ;; Ignore scope operators.
+ (forward-char)
+ (setq c-maybe-labelp (1- (point)))))
+ ((eq (char-after) ??)
+ ;; A question mark. Can't be a label, so stop
+ ;; looking for more : and ?.
+ (setq c-maybe-labelp nil
+ skip-chars (substring c-stmt-delim-chars 0 -2)))
+ ;; At a CPP construct?
+ ((and c-opt-cpp-symbol (looking-at c-opt-cpp-symbol)
+ (save-excursion
+ (forward-line 0)
+ (looking-at c-opt-cpp-prefix)))
+ (c-end-of-macro))
+ ((memq (char-after) non-skip-list)
+ (throw 'done (point)))))
+ ;; In trailing space after an as yet undetected virtual semicolon?
+ (c-backward-syntactic-ws from)
+ (if (and (< (point) to)
+ (c-at-vsemi-p))
+ (point)
+ nil))))))
(defun c-at-statement-start-p ()
"Return non-nil if the point is at the first token in a statement
;; same line.
(re-search-forward "\\=\\s *[\n\r]" start t)
- (if (if (forward-comment -1)
+ (if (if (let (open-paren-in-column-0-is-defun-start) (forward-comment -1))
(if (eolp)
;; If forward-comment above succeeded and we're at eol
;; then the newline we moved over above didn't end a
;; line comment, so we give it another go.
- (forward-comment -1)
+ (let (open-paren-in-column-0-is-defun-start)
+ (forward-comment -1))
t))
;; Emacs <= 20 and XEmacs move back over the closer of a
;; return t when moving backwards at bob.
(not (bobp))
- (if (forward-comment -1)
+ (if (let (open-paren-in-column-0-is-defun-start)
+ (forward-comment -1))
(if (looking-at "\\*/")
;; Emacs <= 20 and XEmacs move back over the
;; closer of a block comment that lacks an opener.
rung-is-marked simple-ws-beg cmt-skip-pos)
;; Skip simple horizontal ws and do a quick check on the preceding
- ;; character to see if it's anying that can't end syntactic ws, so we can
+ ;; character to see if it's anything that can't end syntactic ws, so we can
;; bail out early in the majority of cases when there just are a few ws
;; chars. Newlines are complicated in the backward direction, so we can't
;; skip over them.
(defconst c-state-cache-too-far 5000)
;; A maximum comfortable scanning distance, e.g. between
;; `c-state-cache-good-pos' and "HERE" (where we call c-parse-state). When
-;; this distance is exceeded, we take "emergency meausures", e.g. by clearing
+;; this distance is exceeded, we take "emergency measures", e.g. by clearing
;; the cache and starting again from point-min or a beginning of defun. This
;; value can be tuned for efficiency or set to a lower value for testing.
pos))
(defsubst c-state-cache-non-literal-place (pos state)
- ;; Return a position outside of a string/comment at or before POS.
+ ;; Return a position outside of a string/comment/macro at or before POS.
;; STATE is the parse-partial-sexp state at POS.
- (if (or (nth 3 state) ; in a string?
- (nth 4 state)) ; in a comment?
- (nth 8 state)
- pos))
-
+ (let ((res (if (or (nth 3 state) ; in a string?
+ (nth 4 state)) ; in a comment?
+ (nth 8 state)
+ pos)))
+ (save-excursion
+ (goto-char res)
+ (if (c-beginning-of-macro)
+ (point)
+ res))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Stuff to do with point-min, and coping with any literal there.
;; `c-parse-state', or nil.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Defuns which analyse the buffer, yet don't change `c-state-cache'.
+;; Defuns which analyze the buffer, yet don't change `c-state-cache'.
(defun c-get-fallback-scan-pos (here)
;; Return a start position for building `c-state-cache' from
;; scratch. This will be at the top level, 2 defuns back.
;;
;; If there aren't enough opening paren/brace/brackets, return the position
;; of the outermost one found, or HERE- if there are none. If there are no
- ;; closeing p/b/bs between HERE+ and TOP, return HERE-. HERE-/+ and TOP
+ ;; closing p/b/bs between HERE+ and TOP, return HERE-. HERE-/+ and TOP
;; must not be inside literals. Only the accessible portion of the buffer
;; will be scanned.
(defun c-parse-state-get-strategy (here good-pos)
;; Determine the scanning strategy for adjusting `c-parse-state', attempting
- ;; to minimise the amount of scanning. HERE is the pertinent position in
+ ;; to minimize the amount of scanning. HERE is the pertinent position in
;; the buffer, GOOD-POS is a position where `c-state-cache' (possibly with
;; its head trimmed) is known to be good, or nil if there is no such
;; position.
(<= from (cdr c-state-brace-pair-desert)))
;; Only search what we absolutely need to:
(if (and c-state-brace-pair-desert
- (> from (cdr c-state-brace-pair-desert)))
+ (eq cache-pos (car c-state-brace-pair-desert)))
(narrow-to-region (cdr c-state-brace-pair-desert) (point-max)))
;; In the next pair of nested loops, the inner one moves back past a
c-state-cache)))
;; N.B. This defsubst codes one method for the simple, normal case,
;; and a more sophisticated, slower way for the general case. Don't
- ;; eliminate this defsubst - it's a speed optimisation.
+ ;; eliminate this defsubst - it's a speed optimization.
(c-append-lower-brace-pair-to-state-cache (1- bra+1)))))
(defun c-append-to-state-cache (from)
;;
;; This function must only be called only when (> `c-state-cache-good-pos'
;; HERE). Usually the gap between CACHE-POS and HERE is large. It is thus
- ;; optimised to eliminate (or minimise) scanning between these two
+ ;; optimized to eliminate (or minimize) scanning between these two
;; positions.
;;
;; Return a three element list (GOOD-POS SCAN-BACK-POS FWD-FLAG), where:
; or `here' itself.
here- here+ ; start/end of macro around HERE, or HERE
(here-bol (c-point 'bol here))
- (too-far-back (max (- here c-state-cache-too-far) 1)))
+ (too-far-back (max (- here c-state-cache-too-far) (point-min))))
;; Remove completely irrelevant entries from `c-state-cache'.
(while (and c-state-cache
c-state-cache-good-pos nil
c-state-min-scan-pos nil)
-;;; Truncate `c-state-cache' and set `c-state-cache-good-pos' to a value below
-;;; `here'. To maintain its consistency, we may need to insert a new brace
-;;; pair.
+ ;; Truncate `c-state-cache' and set `c-state-cache-good-pos' to a value
+ ;; below `here'. To maintain its consistency, we may need to insert a new
+ ;; brace pair.
(let ((here-bol (c-point 'bol here))
too-high-pa ; recorded {/(/[ next above here, or nil.
dropped-cons ; was the last removed element a brace pair?
(unless (fboundp 'c-real-parse-state)
(fset 'c-real-parse-state (symbol-function 'c-parse-state)))
(cc-bytecomp-defun c-real-parse-state)
+
+(defvar c-parse-state-state nil)
+(defun c-record-parse-state-state ()
+ (setq c-parse-state-state
+ (mapcar
+ (lambda (arg)
+ (cons arg (symbol-value arg)))
+ '(c-state-cache
+ c-state-cache-good-pos
+ c-state-nonlit-pos-cache
+ c-state-nonlit-pos-cache-limit
+ c-state-brace-pair-desert
+ c-state-point-min
+ c-state-point-min-lit-type
+ c-state-point-min-lit-start
+ c-state-min-scan-pos
+ c-state-old-cpp-beg
+ c-state-old-cpp-end))))
+(defun c-replay-parse-state-state ()
+ (message
+ (concat "(setq "
+ (mapconcat
+ (lambda (arg)
+ (format "%s %s%s" (car arg) (if (atom (cdr arg)) "" "'") (cdr arg)))
+ c-parse-state-state " ")
+ ")")))
+
(defun c-debug-parse-state ()
(let ((here (point)) (res1 (c-real-parse-state)) res2)
(let ((c-state-cache nil)
;; The cache can actually go further back due to the ad-hoc way
;; the first paren is found, so try to whack off a bit of its
;; start before complaining.
- (save-excursion
- (goto-char (or (c-least-enclosing-brace res2) (point)))
- (c-beginning-of-defun-1)
- (while (not (or (bobp) (eq (char-after) ?{)))
- (c-beginning-of-defun-1))
- (unless (equal (c-whack-state-before (point) res1) res2)
- (message (concat "c-parse-state inconsistency at %s: "
- "using cache: %s, from scratch: %s")
- here res1 res2))))
+ ;; (save-excursion
+ ;; (goto-char (or (c-least-enclosing-brace res2) (point)))
+ ;; (c-beginning-of-defun-1)
+ ;; (while (not (or (bobp) (eq (char-after) ?{)))
+ ;; (c-beginning-of-defun-1))
+ ;; (unless (equal (c-whack-state-before (point) res1) res2)
+ ;; (message (concat "c-parse-state inconsistency at %s: "
+ ;; "using cache: %s, from scratch: %s")
+ ;; here res1 res2)))
+ (message (concat "c-parse-state inconsistency at %s: "
+ "using cache: %s, from scratch: %s")
+ here res1 res2)
+ (message "Old state:")
+ (c-replay-parse-state-state))
+ (c-record-parse-state-state)
res1))
(defun c-toggle-parse-state-debug (&optional arg)
;; a relevant match.
(goto-char pos)
nil))))))
-
+
(> (point)
(progn
;; Skip syntactic ws afterwards so that we don't stop at the
;; complicated anyway. In this case, lim is only used to detect
;; cpp directives.
;;
-;; Note that there is a bug in Xemacs's buffer-syntactic-context when used in
+;; Note that there is a bug in XEmacs's buffer-syntactic-context when used in
;; conjunction with syntax-table-properties. The bug is present in, e.g.,
-;; Xemacs 21.4.4. It manifested itself thus:
+;; XEmacs 21.4.4. It manifested itself thus:
;;
;; Starting with an empty AWK Mode buffer, type
;; /regexp/ {<C-j>
;; fails to take account of the change of the s-t property on the opening / to
;; "string", and reports that the { is within a string started by the second /.
;;
-;; The workaround for this is for the AWK Mode initialisation to switch the
+;; The workaround for this is for the AWK Mode initialization to switch the
;; defalias for c-in-literal to c-slow-in-literal. This will slow down other
-;; cc-modes in Xemacs whenever an awk-buffer has been initialised.
+;; cc-modes in XEmacs whenever an awk-buffer has been initialized.
;;
;; (Alan Mackenzie, 2003/4/30).
(setq cfd-prop-match nil))
(when (/= cfd-macro-end 0)
- ;; Restore limits if we did macro narrowment above.
+ ;; Restore limits if we did macro narrowing above.
(narrow-to-region (point-min) cfd-buffer-end)))
(goto-char cfd-continue-pos)
;; The strategy now (2010-01) adopted is to mark and unmark < and
;; > IN MATCHING PAIRS ONLY. [Previously, they were marked
;; individually when their context so indicated. This gave rise to
-;; intractible problems when one of a matching pair was deleted, or
+;; intractable problems when one of a matching pair was deleted, or
;; pulled into a literal.]
;;
;; At each buffer change, the syntax-table properties are removed in a
;; `*-font-lock-extra-types');
;; o - 'prefix if it's a known prefix of a type;
;; o - 'found if it's a type that matches one in `c-found-types';
- ;; o - 'maybe if it's an identfier that might be a type; or
+ ;; o - 'maybe if it's an identifier that might be a type; or
;; o - nil if it can't be a type (the point isn't moved then).
;;
;; The point is assumed to be at the beginning of a token.
;; car ^ ^ point
;; Foo::Foo (int b) : Base (b) {}
;; car ^ ^ point
- ;;
+ ;;
;; The cdr of the return value is non-nil when a
;; `c-typedef-decl-kwds' specifier is found in the declaration.
;; Specifically it is a dotted pair (A . B) where B is t when a
;; other `c-typedef-decl-kwds' (e.g. class, struct, enum)
;; specifier is present. I.e., (some of) the declared
;; identifier(s) are types.
- ;;
+ ;;
;; If a cast is parsed:
;;
;; The point is left at the first token after the closing paren of
(let* ((start (point)) kwd-sym kwd-clause-end found-type)
;; Look for a specifier keyword clause.
- (when (looking-at c-prefix-spec-kwds-re)
+ (when (or (looking-at c-prefix-spec-kwds-re)
+ (and (c-major-mode-is 'java-mode)
+ (looking-at "@[A-Za-z0-9]+")))
(if (looking-at c-typedef-key)
(setq at-typedef t))
(setq kwd-sym (c-keyword-sym (match-string 1)))
;; `c-font-lock-declarators'.)
(while (and (looking-at c-type-decl-prefix-key)
(if (and (c-major-mode-is 'c++-mode)
- (match-beginning 2))
+ (match-beginning 3))
;; If the second submatch matches in C++ then
;; we're looking at an identifier that's a
;; prefix only if it specifies a member pointer.
(if backup-at-type
(progn
- ;; CASE 3
- (when (= (point) start)
- ;; Got a plain list of identifiers. If a colon follows it's
- ;; a valid label. Otherwise the last one probably is the
- ;; declared identifier and we should back up to the previous
- ;; type, providing it isn't a cast.
+
+ ;; CASE 3
+ (when (= (point) start)
+ ;; Got a plain list of identifiers. If a colon follows it's
+ ;; a valid label, or maybe a bitfield. Otherwise the last
+ ;; one probably is the declared identifier and we should
+ ;; back up to the previous type, providing it isn't a cast.
(if (and (eq (char-after) ?:)
(not (c-major-mode-is 'java-mode)))
- ;; If we've found a specifier keyword then it's a
- ;; declaration regardless.
- (throw 'at-decl-or-cast (eq at-decl-or-cast t))
- (setq backup-if-not-cast t)
- (throw 'at-decl-or-cast t)))
+ (cond
+ ;; If we've found a specifier keyword then it's a
+ ;; declaration regardless.
+ ((eq at-decl-or-cast t)
+ (throw 'at-decl-or-cast t))
+ ((and c-has-bitfields
+ (eq at-decl-or-cast 'ids)) ; bitfield.
+ (setq backup-if-not-cast t)
+ (throw 'at-decl-or-cast t)))
+
+ (setq backup-if-not-cast t)
+ (throw 'at-decl-or-cast t)))
;; CASE 4
(when (and got-suffix
;; colon). Currently (2006-03), this applies only to Objective C's
;; keywords "@private", "@protected", and "@public". Returns t.
;;
- ;; One of the things which will NOT be recognised as a label is a bit-field
+ ;; One of the things which will NOT be recognized as a label is a bit-field
;; element of a struct, something like "int foo:5".
;;
;; The end of the label is taken to be just after the colon, or the end of
;; Check that we're not after a token that can't precede a label.
(or
;; Trivially succeeds when there's no preceding token.
+ ;; Succeeds when we're at a virtual semicolon.
(if preceding-token-end
(<= preceding-token-end (point-min))
(save-excursion
(c-backward-syntactic-ws)
(setq preceding-token-end (point))
- (bobp)))
+ (or (bobp)
+ (c-at-vsemi-p))))
;; Check if we're after a label, if we're after a closing
;; paren that belong to statement, and with
(back-to-indentation)
(vector (point) open-paren-pos))))))
+(defmacro c-pull-open-brace (ps)
+ ;; Pull the next open brace from PS (which has the form of paren-state),
+ ;; skipping over any brace pairs. Returns NIL when PS is exhausted.
+ `(progn
+ (while (consp (car ,ps))
+ (setq ,ps (cdr ,ps)))
+ (prog1 (car ,ps)
+ (setq ,ps (cdr ,ps)))))
+
+(defun c-most-enclosing-decl-block (paren-state)
+ ;; Return the buffer position of the most enclosing decl-block brace (in the
+ ;; sense of c-looking-at-decl-block) in the PAREN-STATE structure, or nil if
+ ;; none was found.
+ (let* ((open-brace (c-pull-open-brace paren-state))
+ (next-open-brace (c-pull-open-brace paren-state)))
+ (while (and open-brace
+ (save-excursion
+ (goto-char open-brace)
+ (not (c-looking-at-decl-block next-open-brace nil))))
+ (setq open-brace next-open-brace
+ next-open-brace (c-pull-open-brace paren-state)))
+ open-brace))
+
(defun c-inside-bracelist-p (containing-sexp paren-state)
;; return the buffer position of the beginning of the brace list
;; statement if we're inside a brace list, otherwise return nil.
paren-state)
containing-sexp)))))
+(defun c-at-macro-vsemi-p (&optional pos)
+ ;; Is there a "virtual semicolon" at POS or point?
+ ;; (See cc-defs.el for full details of "virtual semicolons".)
+ ;;
+ ;; This is true when point is at the last non syntactic WS position on the
+ ;; line, there is a macro call last on the line, and this particular macro's
+ ;; name is defined by the regexp `c-vs-macro-regexp' as not needing a
+ ;; semicolon.
+ (save-excursion
+ (save-restriction
+ (widen)
+ (if pos
+ (goto-char pos)
+ (setq pos (point)))
+ (and
+ c-macro-with-semi-re
+ (not (c-in-literal))
+ (eq (skip-chars-backward " \t") 0)
+
+ ;; Check we've got nothing after this except comments and empty lines
+ ;; joined by escaped EOLs.
+ (skip-chars-forward " \t") ; always returns non-nil.
+ (progn
+ (while ; go over 1 block comment per iteration.
+ (and
+ (looking-at "\\(\\\\[\n\r][ \t]*\\)*")
+ (goto-char (match-end 0))
+ (cond
+ ((looking-at c-block-comment-start-regexp)
+ (and (forward-comment 1)
+ (skip-chars-forward " \t"))) ; always returns non-nil
+ ((looking-at c-line-comment-start-regexp)
+ (end-of-line)
+ nil)
+ (t nil))))
+ (eolp))
+
+ (goto-char pos)
+ (progn (c-backward-syntactic-ws)
+ (eq (point) pos))
+
+ ;; Check for one of the listed macros being before point.
+ (or (not (eq (char-before) ?\)))
+ (when (c-go-list-backward)
+ (c-backward-syntactic-ws)
+ t))
+ (c-simple-skip-symbol-backward)
+ (looking-at c-macro-with-semi-re)))))
+
+(defun c-macro-vsemi-status-unknown-p () t) ; See cc-defs.el.
+
\f
;; `c-guess-basic-syntax' and the functions that precedes it below
;; implements the main decision tree for determining the syntactic
;; CASE B.4: Continued statement with block open. The most
;; accurate analysis is perhaps `statement-cont' together with
;; `block-open' but we play DWIM and use `substatement-open'
- ;; instead. The rationaly is that this typically is a macro
+ ;; instead. The rationale is that this typically is a macro
;; followed by a block which makes it very similar to a
;; statement with a substatement block.
(t
(c-beginning-of-statement-1 containing-sexp)
(c-add-syntax 'annotation-var-cont (point)))
+ ;; CASE G: a template list continuation?
+ ;; Mostly a duplication of case 5D.3 to fix templates-19:
+ ((and (c-major-mode-is 'c++-mode)
+ (save-excursion
+ (goto-char indent-point)
+ (c-with-syntax-table c++-template-syntax-table
+ (setq placeholder (c-up-list-backward)))
+ (and placeholder
+ (eq (char-after placeholder) ?<)
+ (/= (char-before placeholder) ?<)
+ (progn
+ (goto-char (1+ placeholder))
+ (not (looking-at c-<-op-cont-regexp))))))
+ (c-with-syntax-table c++-template-syntax-table
+ (goto-char placeholder)
+ (c-beginning-of-statement-1 containing-sexp t)
+ (if (save-excursion
+ (c-backward-syntactic-ws containing-sexp)
+ (eq (char-before) ?<))
+ ;; In a nested template arglist.
+ (progn
+ (goto-char placeholder)
+ (c-syntactic-skip-backward "^,;" containing-sexp t)
+ (c-forward-syntactic-ws))
+ (back-to-indentation)))
+ ;; FIXME: Should use c-add-stmt-syntax, but it's not yet
+ ;; template aware.
+ (c-add-syntax 'template-args-cont (point) placeholder))
+
;; CASE D: continued statement.
(t
(c-beginning-of-statement-1 containing-sexp)
(c-add-syntax 'inher-cont (c-point 'boi)))
;; CASE 5D.5: Continuation of the "expression part" of a
- ;; top level construct. Or, perhaps, an unrecognised construct.
+ ;; top level construct. Or, perhaps, an unrecognized construct.
(t
(while (and (setq placeholder (point))
(eq (car (c-beginning-of-decl-1 containing-sexp))
(< (point) placeholder)))
(c-add-stmt-syntax
(cond
- ((eq (point) placeholder) 'statement) ; unrecognised construct
+ ((eq (point) placeholder) 'statement) ; unrecognized construct
;; A preceding comma at the top level means that a
;; new variable declaration starts here. Use
;; topmost-intro-cont for it, for consistency with
(c-most-enclosing-brace paren-state (point))
paren-state))
- ;; CASE 19: line is an expression, not a statement, and is directly
- ;; contained by a template delimiter. Most likely, we are in a
- ;; template arglist within a statement. This case is based on CASE
- ;; 7. At some point in the future, we may wish to create more
- ;; syntactic symbols such as `template-intro',
- ;; `template-cont-nonempty', etc., and distinguish between them as we
- ;; do for `arglist-intro' etc. (2009-12-07).
- ((and c-recognize-<>-arglists
- (setq containing-< (c-up-list-backward indent-point containing-sexp))
- (eq (char-after containing-<) ?\<))
- (setq placeholder (c-point 'boi containing-<))
- (goto-char containing-sexp) ; Most nested Lbrace/Lparen (but not
- ; '<') before indent-point.
- (if (>= (point) placeholder)
- (progn
- (forward-char)
- (skip-chars-forward " \t"))
- (goto-char placeholder))
- (c-add-stmt-syntax 'template-args-cont (list containing-<) t
- (c-most-enclosing-brace c-state-cache (point))
- paren-state))
-
;; CASE 7B: Looking at the opening brace of an
;; in-expression block or brace list. C.f. cases 4, 16A
;; and 17E.
paren-state))
))
+ ;; CASE 19: line is an expression, not a statement, and is directly
+ ;; contained by a template delimiter. Most likely, we are in a
+ ;; template arglist within a statement. This case is based on CASE
+ ;; 7. At some point in the future, we may wish to create more
+ ;; syntactic symbols such as `template-intro',
+ ;; `template-cont-nonempty', etc., and distinguish between them as we
+ ;; do for `arglist-intro' etc. (2009-12-07).
+ ((and c-recognize-<>-arglists
+ (setq containing-< (c-up-list-backward indent-point containing-sexp))
+ (eq (char-after containing-<) ?\<))
+ (setq placeholder (c-point 'boi containing-<))
+ (goto-char containing-sexp) ; Most nested Lbrace/Lparen (but not
+ ; '<') before indent-point.
+ (if (>= (point) placeholder)
+ (progn
+ (forward-char)
+ (skip-chars-forward " \t"))
+ (goto-char placeholder))
+ (c-add-stmt-syntax 'template-args-cont (list containing-<) t
+ (c-most-enclosing-brace c-state-cache (point))
+ paren-state))
+
;; CASE 17: Statement or defun catchall.
(t
(goto-char indent-point)