;; 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)
+;; the Free Software Foundation; either version 3, or (at your option)
;; any later version.
;; GNU Emacs is distributed in the hope that it will be useful,
)))
\f
+;; Other whitespace tools
+(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.
+ ;;
+ ;; FIXME!!! This function doesn't check virtual semicolons in any way. Be
+ ;; careful about using this function for, e.g. AWK. (2007/3/7)
+ (save-excursion
+ (let ((end+1 (min (1+ end) (point-max))))
+ (or (progn (goto-char (max (point-min) (1- beg)))
+ (c-skip-ws-forward end)
+ (eq (point) end))
+ (progn (goto-char beg)
+ (c-skip-ws-forward end+1)
+ (eq (point) end+1))))))
+\f
;; A system for finding noteworthy parens before the point.
(defvar c-state-cache nil)
;; Move to the beginning of the current token. Do not move if not
;; in the middle of one. BACK-LIMIT may be used to bound the
;; backward search; if given it's assumed to be at the boundary
- ;; between two tokens.
+ ;; between two tokens. Return non-nil if the point is move, nil
+ ;; otherwise.
;;
;; This function might do hidden buffer changes.
- (if (looking-at "\\w\\|\\s_")
- (skip-syntax-backward "w_" back-limit)
(let ((start (point)))
- (when (< (skip-syntax-backward ".()" back-limit) 0)
- (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
- ;; or paren syntax, but consume one char in case
- ;; it doesn't so that we don't leave point before
- ;; some earlier incorrect token.
- (1+ (point)))))
- (if (<= pos start)
- (goto-char pos))
- (< pos start)))))))
+ (if (looking-at "\\w\\|\\s_")
+ (skip-syntax-backward "w_" back-limit)
+ (when (< (skip-syntax-backward ".()" back-limit) 0)
+ (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
+ ;; or paren syntax, but consume one char in case
+ ;; it doesn't so that we don't leave point before
+ ;; some earlier incorrect token.
+ (1+ (point)))))
+ (if (<= pos start)
+ (goto-char pos))))))
+ (< (point) start)))
(defun c-end-of-current-token (&optional back-limit)
;; Move to the end of the current token. Do not move if not in the
;; file, and we only use this as a last resort in ambiguous cases (see
;; `c-forward-decl-or-cast-1').
;;
+;; Not every type need be in this cache. However, things which have
+;; ceased to be types must be removed from it.
+;;
;; Template types in C++ are added here too but with the template
;; arglist replaced with "<>" in references or "<" for the one in the
;; primary type. E.g. the type "Foo<A,B>::Bar<C>" is stored as
(unintern (substring type 0 -1) c-found-types)
(intern type c-found-types))))
+(defun c-unfind-type (name)
+ ;; Remove the "NAME" from c-found-types, if present.
+ (unintern name c-found-types))
+
(defsubst c-check-type (from to)
;; Return non-nil if the given region contains a type in
;; `c-found-types'.
c-found-types)
(sort type-list 'string-lessp)))
+(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
+ ;; from `c-found-types', should this type have become stale. For
+ ;; 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)
+ (save-excursion
+ (when (< end (point-max))
+ (goto-char end)
+ (if (and (c-beginning-of-current-token) ; only moves when we started in the middle
+ (progn (goto-char end)
+ (c-end-of-current-token)))
+ (c-unfind-type (buffer-substring-no-properties
+ end (point)))))
+ (when (> beg (point-min))
+ (goto-char beg)
+ (if (and (c-end-of-current-token) ; only moves when we started in the middle
+ (progn (goto-char 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 "^[ \t\n\r\f\v]*$" (nth 5 c-maybe-stale-found-type)))))
+
+ ;; The syntactic relationship which defined a "found type" has been
+ ;; destroyed.
+ ((eq (car c-maybe-stale-found-type) 'c-decl-id-start)
+ (c-unfind-type (cadr c-maybe-stale-found-type)))
+;; ((eq (car c-maybe-stale-found-type) 'c-decl-type-start) FIXME!!!
+ )))
+
\f
;; Handling of small scale constructs like types and names.
;; Foo::Foo (int b) : Base (b) {}
;; car ^ ^ point
;;
- ;; The cdr of the return value is non-nil iff a
+ ;; The cdr of the return value is non-nil if a
;; `c-typedef-decl-kwds' specifier is found in the declaration,
;; i.e. the declared identifier(s) are types.
;;
;; True if there's a prefix match outside the outermost
;; paren pair that surrounds the declarator.
got-prefix-before-parens
-y ;; True if there's a suffix match outside the outermost
+ ;; True if there's a suffix match outside the outermost
;; paren pair that surrounds the declarator. The value is
;; the position of the first suffix match.
got-suffix-after-parens
(defun c-forward-label (&optional assume-markup preceding-token-end limit)
;; Assuming that point is at the beginning of a token, check if it starts a
- ;; label and if so move over it and return t, otherwise don't move and
- ;; return nil. "Label" here means "most things with a colon".
+ ;; label and if so move over it and return non-nil (t in default situations,
+ ;; specific symbols (see below) for interesting situations), otherwise don't
+ ;; move and return nil. "Label" here means "most things with a colon".
;;
;; More precisely, a "label" is regarded as one of:
- ;; (i) a goto target like "foo:";
- ;; (ii) A case label - either the entire construct "case FOO:" or just the
- ;; bare "case", should the colon be missing;
- ;; (iii) a keyword which needs a colon, like "default:" or "private:";
+ ;; (i) a goto target like "foo:" - returns the symbol `goto-target';
+ ;; (ii) A case label - either the entire construct "case FOO:", or just the
+ ;; bare "case", should the colon be missing. We return t;
+ ;; (iii) a keyword which needs a colon, like "default:" or "private:"; We
+ ;; return t;
;; (iv) One of QT's "extended" C++ variants of
- ;; "private:"/"protected:"/"public:"/"more:" looking like "public slots:".
- ;; (v) One of the keywords matched by `c-opt-extra-label-key' (without any
+ ;; "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'.
+ ;; (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".
+ ;; keywords "@private", "@protected", and "@public". Returns t.
;;
;; One of the things which will NOT be recognised as a label is a bit-field
;; element of a struct, something like "int foo:5".
;; This function might do hidden buffer changes.
(let ((start (point))
+ label-end
qt-symbol-idx
- macro-start) ; if we're in one.
+ macro-start ; if we're in one.
+ label-type)
(cond
;; "case" or "default" (Doesn't apply to AWK).
((looking-at c-label-kwds-regexp)
;; Find the label end.
(goto-char kwd-end)
- (if (and (c-syntactic-re-search-forward
- ;; Stop on chars that aren't allowed in expressions,
- ;; and on operator chars that would be meaningless
- ;; there. FIXME: This doesn't cope with ?: operators.
- "[;{=,@]\\|\\(\\=\\|[^:]\\):\\([^:]\\|\\'\\)"
- limit t t nil 1)
- (match-beginning 2))
-
- (progn
- (goto-char (match-beginning 2)) ; just after the :
- (c-put-c-type-property (1- (point)) 'c-decl-end)
- t)
-
- ;; It's an unfinished label. We consider the keyword enough
- ;; to recognize it as a label, so that it gets fontified.
- ;; Leave the point at the end of it, but don't put any
- ;; `c-decl-end' marker.
- (goto-char kwd-end)
- t)))
+ (setq label-type
+ (if (and (c-syntactic-re-search-forward
+ ;; Stop on chars that aren't allowed in expressions,
+ ;; and on operator chars that would be meaningless
+ ;; there. FIXME: This doesn't cope with ?: operators.
+ "[;{=,@]\\|\\(\\=\\|[^:]\\):\\([^:]\\|\\'\\)"
+ limit t t nil 1)
+ (match-beginning 2))
+
+ (progn ; there's a proper :
+ (goto-char (match-beginning 2)) ; just after the :
+ (c-put-c-type-property (1- (point)) 'c-decl-end)
+ t)
+
+ ;; It's an unfinished label. We consider the keyword enough
+ ;; to recognize it as a label, so that it gets fontified.
+ ;; Leave the point at the end of it, but don't put any
+ ;; `c-decl-end' marker.
+ (goto-char kwd-end)
+ t))))
;; @private, @protected, @public, in Objective C, or similar.
((and c-opt-extra-label-key
(when c-record-type-identifiers
(c-record-ref-id (cons (match-beginning 1) (point))))
(c-put-c-type-property (1- (point)) 'c-decl-end)
- t)
+ (setq label-type t))
;; All other cases of labels.
((and c-recognize-colon-labels ; nil for AWK and IDL, otherwise t.
(c-forward-syntactic-ws)
(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
;; constants.
- (when (c-syntactic-re-search-forward
- "[ \t[:?;{=*/%&|,<>!@+-]" limit t t) ; not at EOB
- (backward-char)
- (setq qt-symbol-idx
- (and (c-major-mode-is 'c++-mode)
- (string-match
- "\\(p\\(r\\(ivate\\|otected\\)\\|ublic\\)\\|more\\)\\>"
- (buffer-substring start (point)))))
- (c-forward-syntactic-ws limit)
- (when (or (looking-at ":\\([^:]\\|\\'\\)") ; A single colon.
- (and qt-symbol-idx
- (search-forward-regexp "\\=slots\\>" limit t)
- (progn (c-forward-syntactic-ws limit)
- (looking-at ":\\([^:]\\|\\'\\)")))) ; A single colon
- (forward-char) ; to after the colon.
- t)))
+ (cond
+ ;; public: protected: private:
+ ((and
+ (c-major-mode-is 'c++-mode)
+ (search-forward-regexp
+ "\\=p\\(r\\(ivate\\|otected\\)\\|ublic\\)\\>[^_]" nil t)
+ (progn (backward-char)
+ (c-forward-syntactic-ws limit)
+ (looking-at ":\\([^:]\\|\\'\\)"))) ; A single colon.
+ (forward-char)
+ (setq label-type t))
+ ;; QT double keyword like "protected slots:" or goto target.
+ ((progn (goto-char start) nil))
+ ((when (c-syntactic-re-search-forward
+ "[ \t\n[:?;{=*/%&|,<>!@+-]" limit t t) ; not at EOB
+ (backward-char)
+ (setq label-end (point))
+ (setq qt-symbol-idx
+ (and (c-major-mode-is 'c++-mode)
+ (string-match
+ "\\(p\\(r\\(ivate\\|otected\\)\\|ublic\\)\\|more\\)\\>"
+ (buffer-substring start (point)))))
+ (c-forward-syntactic-ws limit)
+ (cond
+ ((looking-at ":\\([^:]\\|\\'\\)") ; A single colon.
+ (forward-char)
+ (setq label-type
+ (if (string= "signals" ; Special QT macro
+ (buffer-substring-no-properties start label-end))
+ 'qt-1kwd-colon
+ 'goto-target)))
+ ((and qt-symbol-idx
+ (search-forward-regexp "\\=slots\\>" limit t)
+ (progn (c-forward-syntactic-ws limit)
+ (looking-at ":\\([^:]\\|\\'\\)"))) ; A single colon
+ (forward-char)
+ (setq label-type 'qt-2kwds-colon)))))))
(save-restriction
(narrow-to-region start (point))
(while (progn
(when (looking-at c-nonlabel-token-key)
(goto-char start)
+ (setq label-type nil)
(throw 'check-label nil))
(and (c-safe (c-forward-sexp)
(c-forward-syntactic-ws)
(match-end 0)))))
(c-put-c-type-property (1- (point-max)) 'c-decl-end)
- (goto-char (point-max))
- t)))
+ (goto-char (point-max)))))
(t
;; Not a label.
- (goto-char start)
- nil))))
+ (goto-char start)))
+ label-type))
(defun c-forward-objc-directive ()
;; Assuming the point is at the beginning of a token, try to move
;; 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
;;
;; 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))))
)))
(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")