;;; cc-engine.el --- core syntax guessing engine for CC mode
;; Copyright (C) 1985, 1987, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-;; 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+;; 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
;; Free Software Foundation, Inc.
;; Authors: 2001- Alan Mackenzie
;; This file is part of GNU Emacs.
-;; GNU Emacs is free software; you can redistribute it and/or modify
+;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
-;; along with this program; see the file COPYING. If not, write to
-;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-;; Boston, MA 02110-1301, USA.
+;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;; assume that these text properties are used as described here.
;;
;; 'syntax-table
-;; Used to modify the syntax of some characters. Currently used to
-;; mark the "<" and ">" of angle bracket parens with paren syntax.
+;; Used to modify the syntax of some characters. It is used to
+;; mark the "<" and ">" of angle bracket parens with paren syntax, and
+;; to "hide" obtrusive characters in preprocessor lines.
;;
;; This property is used on single characters and is therefore
;; always treated as front and rear nonsticky (or start and end open
;; (e.g. if).
;;
;;
- ;; The following diagram briefly outlines the PDA.
+ ;; The following diagram briefly outlines the PDA.
;;
;; Common state:
;; "else": Push state, goto state `else'.
For AWK, a statement which is terminated by an EOL (not a \; or a }) is
regarded as having a \"virtual semicolon\" immediately after the last token on
-the line. If this virtual semicolon is _at_ from, the function recognises it.
+the line. If this virtual semicolon is _at_ from, the function recognizes it.
Note that this function might do hidden buffer changes. See the
comment at the start of cc-engine.el for more info."
(defun c-partial-ws-p (beg end)
;; Is the region (beg end) WS, and is there WS (or BOB/EOB) next to the
;; region? This is a "heuristic" function. .....
- ;;
+ ;;
;; The motivation for the second bit is to check whether removing this
;; region would coalesce two symbols.
;;
;; The workaround for this is for the AWK Mode initialisation 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.
-;;
+;;
;; (Alan Mackenzie, 2003/4/30).
(defun c-fast-in-literal (&optional lim detect-cpp)
(if (and (consp range) (progn
(goto-char (car range))
(looking-at c-line-comment-starter)))
- (let ((col (current-column))
+ (let ((col (current-column))
(beg (point))
(bopl (c-point 'bopl))
(end (cdr range)))
c-found-types)
(sort type-list 'string-lessp)))
+;; Shut up the byte compiler.
+(defvar c-maybe-stale-found-type)
+
(defun c-trim-found-types (beg end old-len)
;; An after change function which, in conjunction with the info in
;; c-maybe-stale-found-type (set in c-before-change), removes a type
;; example, this happens to "foo" when "foo \n bar();" becomes
;; "foo(); \n bar();". Such stale types, if not removed, foul up
;; the fontification.
- ;;
+ ;;
;; Have we, perhaps, added non-ws characters to the front/back of a found
;; type?
(when (> end beg)
(c-beginning-of-current-token)))
(c-unfind-type (buffer-substring-no-properties
(point) beg))))))
-
+
(if c-maybe-stale-found-type ; e.g. (c-decl-id-start "foo" 97 107 " (* ooka) " "o")
(cond
;; Changing the amount of (already existing) whitespace - don't do anything.
((and (c-partial-ws-p beg end)
(or (= beg end) ; removal of WS
- ; (string-match "\\s *\\'" (nth 5 c-maybe-stale-found-type))
(string-match "^[ \t\n\r\f\v]*$" (nth 5 c-maybe-stale-found-type)))))
;; The syntactic relationship which defined a "found type" has been
;;
;; The point is left at the first token after the first complete
;; declarator, if there is one. The return value is a cons where
- ;; the car is the position of the first token in the declarator.
+ ;; the car is the position of the first token in the declarator. (See
+ ;; below for the cdr.)
;; Some examples:
;;
;; void foo (int a, char *b) stuff ...
;; Foo::Foo (int b) : Base (b) {}
;; car ^ ^ point
;;
- ;; The cdr of the return value is non-nil iff a
- ;; `c-typedef-decl-kwds' specifier is found in the declaration,
- ;; i.e. the declared identifier(s) are types.
+ ;; The cdr of the return value is non-nil iff a `c-typedef-decl-kwds'
+ ;; specifier (e.g. class, struct, enum, typedef) is found in the
+ ;; declaration, i.e. the declared identifier(s) are types.
;;
;; If a cast is parsed:
;;
;; the first token in (the visible part of) the buffer.
;;
;; CONTEXT is a symbol that describes the context at the point:
- ;; 'decl In a comma-separatded declaration context (typically
+ ;; 'decl In a comma-separated declaration context (typically
;; inside a function declaration arglist).
;; '<> In an angle bracket arglist.
;; 'arglist Some other type of arglist.
;; "private:"/"protected:"/"public:"/"more:" looking like "public slots:".
;; Returns the symbol `qt-2kwds-colon'.
;; (v) QT's construct "signals:". Returns the symbol `qt-1kwd-colon'.
- ;; (v) One of the keywords matched by `c-opt-extra-label-key' (without any
+ ;; (vi) One of the keywords matched by `c-opt-extra-label-key' (without any
;; colon). Currently (2006-03), this applies only to Objective C's
;; keywords "@private", "@protected", and "@public". Returns t.
;;
macro-start ; if we're in one.
label-type)
(cond
- ;; "case" or "default" (Doesn't apply to AWK).
+ ;; "case" or "default" (Doesn't apply to AWK).
((looking-at c-label-kwds-regexp)
(let ((kwd-end (match-end 1)))
;; Record only the keyword itself for fontification, since in
(c-forward-label nil pte start))))))))))
;; Point is still at the beginning of the possible label construct.
- ;;
+ ;;
;; Check that the next nonsymbol token is ":", or that we're in one
;; of QT's "slots" declarations. Allow '(' for the sake of macro
;; arguments. FIXME: Should build this regexp from the language
(and (c-major-mode-is 'c++-mode)
(string-match
"\\(p\\(r\\(ivate\\|otected\\)\\|ublic\\)\\|more\\)\\>"
- (buffer-substring start (point)))))
+ (buffer-substring start (point)))))
(c-forward-syntactic-ws limit)
(cond
((looking-at ":\\([^:]\\|\\'\\)") ; A single colon.
(match-end 0)))))
(c-put-c-type-property (1- (point-max)) 'c-decl-end)
- (goto-char (point-max))
- )))
+ (goto-char (point-max)))))
(t
;; Not a label.
;; the searchable range.
(let* ((macro-start (c-query-macro-start))
(lim (max (or lim (point-min)) (or macro-start (point-min))))
- before-lparen after-rparen)
+ before-lparen after-rparen
+ (pp-count-out 20)) ; Max number of paren/brace constructs before we give up
(narrow-to-region lim (c-point 'eol))
;; Search backwards for the defun's argument list. We give up if we
;; {
(catch 'knr
- (while t ; go round one paren/bracket construct each time round.
+ (while (> pp-count-out 0) ; go back one paren/bracket pair each time.
+ (setq pp-count-out (1- pp-count-out))
(c-syntactic-skip-backward "^)]}")
(cond ((eq (char-before) ?\))
(setq after-rparen (point)))
;; auto newline analysis.
(defvar c-auto-newline-analysis nil)
+(defun c-brace-anchor-point (bracepos)
+ ;; BRACEPOS is the position of a brace in a construct like "namespace
+ ;; Bar {". Return the anchor point in this construct; this is the
+ ;; earliest symbol on the brace's line which isn't earlier than
+ ;; "namespace".
+ ;;
+ ;; Currently (2007-08-17), "like namespace" means "matches
+ ;; c-other-block-decl-kwds". It doesn't work with "class" or "struct"
+ ;; or anything like that.
+ (save-excursion
+ (let ((boi (c-point 'boi bracepos)))
+ (goto-char bracepos)
+ (while (and (> (point) boi)
+ (not (looking-at c-other-decl-block-key)))
+ (c-backward-token-2))
+ (if (> (point) boi) (point) boi))))
+
(defsubst c-add-syntax (symbol &rest args)
;; A simple function to prepend a new syntax element to
;; `c-syntactic-context'. Using `setq' on it is unsafe since it
;; needed with further syntax elements of the types `substatement',
;; `inexpr-statement', `arglist-cont-nonempty', `statement-block-intro', and
;; `defun-block-intro'.
- ;;
+ ;;
;; Do the generic processing to anchor the given syntax symbol on
;; the preceding statement: Skip over any labels and containing
;; statements on the same line, and then search backward until we
;;
;; Point is assumed to be at the prospective anchor point for the
;; given SYNTAX-SYMBOL. More syntax entries are added if we need to
- ;; skip past open parens and containing statements. All the added
- ;; syntax elements will get the same anchor point.
+ ;; skip past open parens and containing statements. Most of the added
+ ;; syntax elements will get the same anchor point - the exception is
+ ;; for an anchor in a construct like "namespace"[*] - this is as early
+ ;; as possible in the construct but on the same line as the {.
+ ;;
+ ;; [*] i.e. with a keyword matching c-other-block-decl-kwds.
;;
;; SYNTAX-EXTRA-ARGS are a list of the extra arguments for the
;; syntax symbol. They are appended after the anchor point.
;; now at the start.
on-label)
- (apply 'c-add-syntax syntax-symbol nil syntax-extra-args)
+ ;; Use point as the anchor point for "namespace", "extern", etc.
+ (apply 'c-add-syntax syntax-symbol
+ (if (rassq syntax-symbol c-other-decl-block-key-in-symbols-alist)
+ (point) nil)
+ syntax-extra-args)
;; Loop while we have to back out of containing blocks.
(while
(setq step-type 'same
on-label nil))
+ ;; Stepped out of a brace block.
(setq step-type (c-beginning-of-statement-1 containing-sexp)
on-label (eq step-type 'label))
(if (and (eq step-type 'same)
(/= paren-pos (point)))
- (save-excursion
- (goto-char paren-pos)
- (let ((inexpr (c-looking-at-inexpr-block
- (c-safe-position containing-sexp
- paren-state)
- containing-sexp)))
- (if (and inexpr
- (not (eq (car inexpr) 'inlambda)))
- (c-add-syntax 'statement-block-intro nil)
- (c-add-syntax 'defun-block-intro nil))))
- (c-add-syntax 'statement-block-intro nil)))
+ (let (inexpr)
+ (cond
+ ((save-excursion
+ (goto-char paren-pos)
+ (setq inexpr (c-looking-at-inexpr-block
+ (c-safe-position containing-sexp paren-state)
+ containing-sexp)))
+ (c-add-syntax (if (eq (car inexpr) 'inlambda)
+ 'defun-block-intro
+ 'statement-block-intro)
+ nil))
+ ((looking-at c-other-decl-block-key)
+ (c-add-syntax
+ (cdr (assoc (match-string 1)
+ c-other-decl-block-key-in-symbols-alist))
+ (max (c-point 'boi paren-pos) (point))))
+ (t (c-add-syntax 'defun-block-intro nil))))
+
+ (c-add-syntax 'statement-block-intro nil)))
(if (= paren-pos boi)
;; Always done if the open brace was at boi. The
;; Fill in the current point as the anchor for all the symbols
;; added above.
- (let ((p c-syntactic-context))
+ (let ((p c-syntactic-context) q)
(while (not (eq p syntax-last))
- (if (cdr (car p))
- (setcar (cdr (car p)) (point)))
+ (setq q (cdr (car p))) ; e.g. (nil 28) [from (arglist-cont-nonempty nil 28)]
+ (while q
+ (unless (car q)
+ (setcar q (point)))
+ (setq q (cdr q)))
(setq p (cdr p))))
)))
;; CASE 5A.5: ordinary defun open
(t
- (goto-char placeholder)
- (if (or containing-decl-open macro-start)
- (c-add-syntax 'defun-open (c-point 'boi))
- ;; Bogus to use bol here, but it's the legacy.
- (c-add-syntax 'defun-open (c-point 'bol)))
- )))
+ (save-excursion
+ (c-beginning-of-decl-1 lim)
+ (while (looking-at c-specifier-key)
+ (goto-char (match-end 1))
+ (c-forward-syntactic-ws indent-point))
+ (c-add-syntax 'defun-open (c-point 'boi))
+ ;; Bogus to use bol here, but it's the legacy. (Resolved,
+ ;; 2007-11-09)
+ ))))
;; CASE 5B: After a function header but before the body (or
;; the ending semicolon if there's no body).
(c-add-syntax 'inher-cont (c-point 'boi)))
;; CASE 5D.5: Continuation of the "expression part" of a
- ;; top level construct.
+ ;; top level construct. Or, perhaps, an unrecognised construct.
(t
- (while (and (eq (car (c-beginning-of-decl-1 containing-sexp))
+ (while (and (setq placeholder (point))
+ (eq (car (c-beginning-of-decl-1 containing-sexp))
'same)
(save-excursion
(c-backward-syntactic-ws)
- (eq (char-before) ?}))))
+ (eq (char-before) ?}))
+ (< (point) placeholder)))
(c-add-stmt-syntax
- (if (eq char-before-ip ?,)
+ (cond
+ ((eq (point) placeholder) 'statement) ; unrecognised 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
;; the first variable declaration. C.f. case 5N.
- 'topmost-intro-cont
- 'statement-cont)
+ ((eq char-before-ip ?,) 'topmost-intro-cont)
+ (t 'statement-cont))
nil nil containing-sexp paren-state))
))
-
+
;; CASE 5F: Close of a non-class declaration level block.
((and (eq char-after-ip ?})
(c-keyword-member containing-decl-kwd
;; CASE 5H: we could be looking at subsequent knr-argdecls
((and c-recognize-knr-p
+ (not containing-sexp) ; can't be knr inside braces.
(not (eq char-before-ip ?}))
(save-excursion
(setq placeholder (cdr (c-beginning-of-decl-1 lim)))
(if (c-keyword-member containing-decl-kwd
'c-other-block-decl-kwds)
(progn
- (goto-char containing-decl-open)
- (unless (= (point) (c-point 'boi))
- (goto-char containing-decl-start))
+ (goto-char (c-brace-anchor-point containing-decl-open))
(c-add-stmt-syntax
(if (string-equal (symbol-name containing-decl-kwd)
"extern")
\f
(cc-provide 'cc-engine)
-;;; arch-tag: 149add18-4673-4da5-ac47-6805e4eae089
+;; arch-tag: 149add18-4673-4da5-ac47-6805e4eae089
;;; cc-engine.el ends here