;;; cc-engine.el --- core syntax guessing engine for CC mode -*- coding: utf-8 -*-
-;; Copyright (C) 1985, 1987, 1992-2013 Free Software Foundation, Inc.
+;; Copyright (C) 1985, 1987, 1992-2014 Free Software Foundation, Inc.
;; Authors: 2001- Alan Mackenzie
;; 1998- Martin Stjernholm
;; 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))
+ ;; At a CPP construct or a "#" or "##" operator?
+ ((and c-opt-cpp-symbol (looking-at c-opt-cpp-symbol))
+ (if (save-excursion
+ (skip-chars-backward " \t")
+ (and (bolp)
+ (or (bobp)
+ (not (eq (char-before (1- (point))) ?\\)))))
+ (c-end-of-macro)
+ (skip-chars-forward c-opt-cpp-symbol)))
((memq (char-after) non-skip-list)
(throw 'done (point)))))
;; In trailing space after an as yet undetected virtual semicolon?
((and (not not-in-delimiter) ; inside a comment starter
(not (bobp))
(progn (backward-char)
- (looking-at c-comment-start-regexp)))
+ (and (not (and (memq 'category-properties c-emacs-features)
+ (looking-at "\\s!")))
+ (looking-at c-comment-start-regexp))))
(setq ty (if (looking-at c-block-comment-start-regexp) 'c 'c++)
co-st (point))
(forward-comment 1)
;; The return value is a list, one of the following:
;;
;; o - ('forward START-POINT) - scan forward from START-POINT,
- ;; which is not less than the highest position in `c-state-cache' below here.
+ ;; which is not less than the highest position in `c-state-cache' below HERE,
+ ;; which is after GOOD-POS.
;; o - ('backward nil) - scan backwards (from HERE).
+ ;; o - ('back-and-forward START-POINT) - like 'forward, but when HERE is earlier
+ ;; than GOOD-POS.
;; o - ('IN-LIT nil) - point is inside the literal containing point-min.
(let ((cache-pos (c-get-cache-scan-pos here)) ; highest position below HERE in cache (or 1)
strategy ; 'forward, 'backward, or 'IN-LIT.
((< (- good-pos here) (- here cache-pos)) ; FIXME!!! ; apply some sort of weighting.
(setq strategy 'backward))
(t
- (setq strategy 'forward
+ (setq strategy 'back-and-forward
start-point cache-pos)))
- (list strategy (and (eq strategy 'forward) start-point))))
+ (list strategy start-point)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun c-remove-stale-state-cache (start-point here pps-point)
;; Remove stale entries from the `c-cache-state', i.e. those which will
- ;; not be in it when it is amended for position HERE. Additionally, the
- ;; "outermost" open-brace entry before HERE will be converted to a cons if
- ;; the matching close-brace is scanned.
+ ;; not be in it when it is amended for position HERE. This may involve
+ ;; replacing a CONS element for a brace pair containing HERE with its car.
+ ;; Additionally, the "outermost" open-brace entry before HERE will be
+ ;; converted to a cons if the matching close-brace is below HERE.
;;
;; START-POINT is a "maximal" "safe position" - there must be no open
;; parens/braces/brackets between START-POINT and HERE.
;; adjust it to get outside a string/comment. (Sorry about this! The code
;; needs to be FAST).
;;
- ;; Return a list (GOOD-POS SCAN-BACK-POS PPS-STATE), where
+ ;; Return a list (GOOD-POS SCAN-BACK-POS CONS-SEPARATED PPS-STATE), where
;; o - GOOD-POS is a position where the new value `c-state-cache' is known
;; to be good (we aim for this to be as high as possible);
;; o - SCAN-BACK-POS, if not nil, indicates there may be a brace pair
;; position to scan backwards from. It is the position of the "{" of the
;; last element to be removed from `c-state-cache', when that elt is a
;; cons, otherwise nil.
+ ;; o - CONS-SEPARATED is t when a cons element in `c-state-cache' has been
+ ;; replaced by its car because HERE lies inside the brace pair represented
+ ;; by the cons.
;; o - PPS-STATE is the parse-partial-sexp state at PPS-POINT.
(save-excursion
(save-restriction
pos
upper-lim ; ,beyond which `c-state-cache' entries are removed
scan-back-pos
+ cons-separated
pair-beg pps-point-state target-depth)
;; Remove entries beyond HERE. Also remove any entries inside
(consp (car c-state-cache))
(> (cdar c-state-cache) upper-lim))
(setcar c-state-cache (caar c-state-cache))
- (setq scan-back-pos (car c-state-cache)))
+ (setq scan-back-pos (car c-state-cache)
+ cons-separated t))
;; The next loop jumps forward out of a nested level of parens each
;; time round; the corresponding elements in `c-state-cache' are
(setq c-state-cache (cons (cons pair-beg pos)
c-state-cache)))
- (list pos scan-back-pos pps-state)))))
+ (list pos scan-back-pos cons-separated pps-state)))))
(defun c-remove-stale-state-cache-backwards (here)
;; Strip stale elements of `c-state-cache' by moving backwards through the
;; 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))
+ (let (open-paren-in-column-0-is-defun-start
+ (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?
pa)
;; This function might do hidden buffer changes.
(let* ((here (point))
(here-bopl (c-point 'bopl))
+ open-paren-in-column-0-is-defun-start
strategy ; 'forward, 'backward etc..
;; Candidate positions to start scanning from:
cache-pos ; highest position below HERE already existing in
; are no open parens/braces between it and HERE.
bopl-state
res
+ cons-separated
scan-backward-pos scan-forward-p) ; used for 'backward.
;; If POINT-MIN has changed, adjust the cache
(unless (= (point-min) c-state-point-min)
;; SCAN!
(cond
- ((eq strategy 'forward)
+ ((memq strategy '(forward back-and-forward))
(setq res (c-remove-stale-state-cache start-point here here-bopl))
(setq cache-pos (car res)
scan-backward-pos (cadr res)
- bopl-state (car (cddr res))) ; will be nil if (< here-bopl
+ cons-separated (car (cddr res))
+ bopl-state (cadr (cddr res))) ; will be nil if (< here-bopl
; start-point)
- (if scan-backward-pos
+ (if (and scan-backward-pos
+ (or cons-separated (eq strategy 'forward))) ;scan-backward-pos
(c-append-lower-brace-pair-to-state-cache scan-backward-pos here))
(setq good-pos
(c-append-to-state-cache cache-pos here))
(while (let ((pos (or (and (looking-at c-nonsymbol-token-regexp)
(match-end 0))
;; `c-nonsymbol-token-regexp' should always match
- ;; since we've skipped backward over punctuator
+ ;; since we've skipped backward over punctuation
;; or paren syntax, but consume one char in case
;; it doesn't so that we don't leave point before
;; some earlier incorrect token.
(if (looking-at c-nonsymbol-token-regexp)
(goto-char (match-end 0))
;; `c-nonsymbol-token-regexp' should always match since
- ;; we've skipped backward over punctuator or paren
+ ;; we've skipped backward over punctuation or paren
;; syntax, but move forward in case it doesn't so that
;; we don't leave point earlier than we started with.
(forward-char))
;; inside `c-find-decl-spots'. The point is left at `cfd-match-pos'
;; if there is a match, otherwise at `cfd-limit'.
;;
+ ;; The macro moves point forward to the next putative start of a declaration
+ ;; or cfd-limit. This decl start is the next token after a "declaration
+ ;; prefix". The declaration prefix is the earlier of `cfd-prop-match' and
+ ;; `cfd-re-match'. `cfd-match-pos' is set to the decl prefix.
+ ;;
;; This macro might do hidden buffer changes.
'(progn
(if (> cfd-re-match-end (point))
(goto-char cfd-re-match-end))
- (while (if (setq cfd-re-match-end
- (re-search-forward c-decl-prefix-or-start-re
- cfd-limit 'move))
-
- ;; Match. Check if it's inside a comment or string literal.
- (c-got-face-at
- (if (setq cfd-re-match (match-end 1))
- ;; Matched the end of a token preceding a decl spot.
- (progn
- (goto-char cfd-re-match)
- (1- cfd-re-match))
- ;; Matched a token that start a decl spot.
- (goto-char (match-beginning 0))
- (point))
- c-literal-faces)
-
- ;; No match. Finish up and exit the loop.
- (setq cfd-re-match cfd-limit)
- nil)
-
- ;; Skip out of comments and string literals.
- (while (progn
- (goto-char (next-single-property-change
- (point) 'face nil cfd-limit))
- (and (< (point) cfd-limit)
- (c-got-face-at (point) c-literal-faces)))))
+ ;; Each time round, the next `while' moves forward over a pseudo match
+ ;; of `c-decl-prefix-or-start-re' which is either inside a literal, or
+ ;; is a ":" not preceded by "public", etc.. `cfd-re-match' and
+ ;; `cfd-re-match-end' get set.
+ (while
+ (progn
+ (setq cfd-re-match-end (re-search-forward c-decl-prefix-or-start-re
+ cfd-limit 'move))
+ (cond
+ ((null cfd-re-match-end)
+ ;; No match. Finish up and exit the loop.
+ (setq cfd-re-match cfd-limit)
+ nil)
+ ((c-got-face-at
+ (if (setq cfd-re-match (match-end 1))
+ ;; Matched the end of a token preceding a decl spot.
+ (progn
+ (goto-char cfd-re-match)
+ (1- cfd-re-match))
+ ;; Matched a token that start a decl spot.
+ (goto-char (match-beginning 0))
+ (point))
+ c-literal-faces)
+ ;; Pseudo match inside a comment or string literal. Skip out
+ ;; of comments and string literals.
+ (while (progn
+ (goto-char (next-single-property-change
+ (point) 'face nil cfd-limit))
+ (and (< (point) cfd-limit)
+ (c-got-face-at (point) c-literal-faces))))
+ t) ; Continue the loop over pseudo matches.
+ ((and (match-string 1)
+ (string= (match-string 1) ":")
+ (save-excursion
+ (or (/= (c-backward-token-2 2) 0) ; no search limit. :-(
+ (not (looking-at c-decl-start-colon-kwd-re)))))
+ ;; Found a ":" which isn't part of "public:", etc.
+ t)
+ (t nil)))) ;; Found a real match. Exit the pseudo-match loop.
- ;; If we matched at the decl start, we have to back up over the
+ ;; If our match was at the decl start, we have to back up over the
;; preceding syntactic ws to set `cfd-match-pos' and to catch
;; any decl spots in the syntactic ws.
(unless cfd-re-match
;; can happen since we don't know if
;; `c-restricted-<>-arglists' will be correct inside the
;; arglist paren that gets entered.
- c-parse-and-markup-<>-arglists)
+ c-parse-and-markup-<>-arglists
+ ;; Start of the identifier for which `got-identifier' was set.
+ name-start)
(goto-char id-start)
;; If the third submatch matches in C++ then
;; we're looking at an identifier that's a
;; prefix only if it specifies a member pointer.
- (when (setq got-identifier (c-forward-name))
+ (when (progn (setq pos (point))
+ (setq got-identifier (c-forward-name)))
+ (setq name-start pos)
(if (looking-at "\\(::\\)")
;; We only check for a trailing "::" and
;; let the "*" that should follow be
;; Skip over an identifier.
(or got-identifier
(and (looking-at c-identifier-start)
- (setq got-identifier (c-forward-name))))
+ (setq pos (point))
+ (setq got-identifier (c-forward-name))
+ (setq name-start pos)))
;; Skip over type decl suffix operators.
(while (if (looking-at c-type-decl-suffix-key)
;; declaration.
(throw 'at-decl-or-cast t))
- (when (and got-parens
- (not got-prefix)
- (not got-suffix-after-parens)
- (or backup-at-type
- maybe-typeless
- backup-maybe-typeless))
- ;; Got a declaration of the form "foo bar (gnu);" where we've
- ;; recognized "bar" as the type and "gnu" as the declarator.
- ;; In this case it's however more likely that "bar" is the
- ;; declarator and "gnu" a function argument or initializer (if
- ;; `c-recognize-paren-inits' is set), since the parens around
- ;; "gnu" would be superfluous if it's a declarator. Shift the
- ;; type one step backward.
- (c-fdoc-shift-type-backward)))
-
- ;; Found no identifier.
+ (when (and got-parens
+ (not got-prefix)
+ ;; (not got-suffix-after-parens)
+ (or backup-at-type
+ maybe-typeless
+ backup-maybe-typeless
+ (eq at-decl-or-cast t)
+ (save-excursion
+ (goto-char name-start)
+ (not (memq (c-forward-type) '(nil maybe))))))
+ ;; Got a declaration of the form "foo bar (gnu);" or "bar
+ ;; (gnu);" where we've recognized "bar" as the type and "gnu"
+ ;; as the declarator. In this case it's however more likely
+ ;; that "bar" is the declarator and "gnu" a function argument
+ ;; or initializer (if `c-recognize-paren-inits' is set),
+ ;; since the parens around "gnu" would be superfluous if it's
+ ;; a declarator. Shift the type one step backward.
+ (c-fdoc-shift-type-backward)))
+
+ ;; Found no identifier.
(if backup-at-type
(progn
;; interactive refontification.
(c-put-c-type-property (point) 'c-decl-arg-start))
- (when (and c-record-type-identifiers at-type (not (eq at-type t)))
+ (when (and c-record-type-identifiers at-type ;; (not (eq at-type t))
+ ;; There seems no reason to exclude a token from
+ ;; fontification just because it's "a known type that can't
+ ;; be a name or other expression". 2013-09-18.
+ )
(let ((c-promote-possible-types t))
(save-excursion
(goto-char type-start)
(not (looking-at "=")))))
b-pos)))
+(defun c-backward-over-enum-header ()
+ ;; We're at a "{". Move back to the enum-like keyword that starts this
+ ;; declaration and return t, otherwise don't move and return nil.
+ (let ((here (point))
+ up-sexp-pos before-identifier)
+ (while
+ (and
+ (eq (c-backward-token-2) 0)
+ (or (not (looking-at "\\s)"))
+ (c-go-up-list-backward))
+ (cond
+ ((and (looking-at c-symbol-key) (c-on-identifier)
+ (not before-identifier))
+ (setq before-identifier t))
+ ((and before-identifier
+ (or (eq (char-after) ?,)
+ (looking-at c-postfix-decl-spec-key)))
+ (setq before-identifier nil)
+ t)
+ ((looking-at c-brace-list-key) nil)
+ ((and c-recognize-<>-arglists
+ (eq (char-after) ?<)
+ (looking-at "\\s("))
+ t)
+ (t nil))))
+ (or (looking-at c-brace-list-key)
+ (progn (goto-char here) nil))))
+
(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.
;; This function might do hidden buffer changes.
(or
;; This will pick up brace list declarations.
- (c-safe
- (save-excursion
- (goto-char containing-sexp)
- (c-forward-sexp -1)
- (let (bracepos)
- (if (and (or (looking-at c-brace-list-key)
- (progn (c-forward-sexp -1)
- (looking-at c-brace-list-key)))
- (setq bracepos (c-down-list-forward (point)))
- (not (c-crosses-statement-barrier-p (point)
- (- bracepos 2))))
- (point)))))
+ (save-excursion
+ (goto-char containing-sexp)
+ (c-backward-over-enum-header))
;; this will pick up array/aggregate init lists, even if they are nested.
(save-excursion
(let ((class-key
(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)))
+ (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))
(c-save-buffer-state
((indent-point (point))
(case-fold-search nil)
- ;; A whole ugly bunch of various temporary variables. Have
+ open-paren-in-column-0-is-defun-start
+ ;; A whole ugly bunch of various temporary variables. Have
;; to declare them here since it's not possible to declare
;; a variable with only the scope of a cond test and the
;; following result clauses, and most of this function is a
(eq (char-after placeholder) ?<))))))
(c-with-syntax-table c++-template-syntax-table
(goto-char placeholder)
- (c-beginning-of-statement-1 lim t)
- (if (save-excursion
- (c-backward-syntactic-ws lim)
- (eq (char-before) ?<))
- ;; In a nested template arglist.
- (progn
- (goto-char placeholder)
- (c-syntactic-skip-backward "^,;" lim t)
- (c-forward-syntactic-ws))
- (back-to-indentation)))
+ (c-beginning-of-statement-1 lim t))
+ (if (save-excursion
+ (c-backward-syntactic-ws lim)
+ (eq (char-before) ?<))
+ ;; In a nested template arglist.
+ (progn
+ (goto-char placeholder)
+ (c-syntactic-skip-backward "^,;" lim 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))