Function: c-forward-label
c-forward-label is a byte-compiled function defined in
cc-engine.el.gz.
Signature
(c-forward-label &optional ASSUME-MARKUP PRECEDING-TOKEN-END LIMIT)
Source Code
;; Defined in /usr/src/emacs/lisp/progmodes/cc-engine.el.gz
(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 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:" - 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:".
;; 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". Returns t.
;;
;; 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
;; the first submatch in `c-opt-extra-label-key'. The point is directly
;; after the end on return. The terminating char gets marked with
;; `c-decl-end' to improve recognition of the following declaration or
;; statement.
;;
;; If ASSUME-MARKUP is non-nil, it's assumed that the preceding
;; label, if any, has already been marked up like that.
;;
;; If PRECEDING-TOKEN-END is given, it should be the first position
;; after the preceding token, i.e. on the other side of the
;; syntactic ws from the point. Use a value less than or equal to
;; (point-min) if the point is at the first token in (the visible
;; part of) the buffer.
;;
;; The optional LIMIT limits the forward scan for the colon.
;;
;; This function records the ranges of the label symbols on
;; `c-record-ref-identifiers' if `c-record-type-identifiers' (!) is
;; non-nil.
;;
;; This function might do hidden buffer changes.
(let ((start (point))
label-end
qt-symbol-idx
macro-start ; if we're in one.
label-type
kwd)
(cond
;; "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
;; case labels the following is a constant expression and not
;; a label.
(when c-record-type-identifiers
(c-record-ref-id (cons (match-beginning 1) kwd-end)))
;; Find the label end.
(goto-char kwd-end)
(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
(looking-at c-opt-extra-label-key))
;; For a `c-opt-extra-label-key' match, we record the whole
;; thing for fontification. That's to get the leading '@' in
;; Objective-C protection labels fontified.
(goto-char (match-end 1))
(when c-record-type-identifiers
(c-record-ref-id (cons (match-beginning 1) (point))))
(c-put-c-type-property (1- (point)) 'c-decl-end)
(setq label-type t))
;; All other cases of labels.
((and c-recognize-colon-labels ; nil for AWK and IDL, otherwise t.
;; A colon label must have something before the colon.
(not (eq (char-after) ?:))
;; 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))
(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
;; `c-label-prefix-re'. It's done in different order
;; depending on `assume-markup' since the checks have
;; different expensiveness.
(if assume-markup
(or
(eq (c-get-char-property (1- preceding-token-end) 'c-type)
'c-decl-end)
(save-excursion
(goto-char (1- preceding-token-end))
(c-beginning-of-current-token)
(or (looking-at c-label-prefix-re)
(looking-at c-block-stmt-1-key)))
(and (eq (char-before preceding-token-end) ?\))
(c-after-conditional)))
(or
(save-excursion
(goto-char (1- preceding-token-end))
(c-beginning-of-current-token)
(or (looking-at c-label-prefix-re)
(looking-at c-block-stmt-1-key)))
(cond
((eq (char-before preceding-token-end) ?\))
(c-after-conditional))
((eq (char-before preceding-token-end) ?:)
;; Might be after another label, so check it recursively.
(save-restriction
(save-excursion
(goto-char (1- preceding-token-end))
;; Essentially the same as the
;; `c-syntactic-re-search-forward' regexp below.
(setq macro-start
(save-excursion (and (c-beginning-of-macro)
(point))))
(if macro-start (narrow-to-region macro-start (point-max)))
(c-syntactic-skip-backward "^-]:?;}=*/%&|,<>!@+" nil t)
;; Note: the following should work instead of the
;; narrow-to-region above. Investigate why not,
;; sometime. ACM, 2006-03-31.
;; (c-syntactic-skip-backward "^-]:?;}=*/%&|,<>!@+"
;; macro-start t)
(let ((pte (point))
;; If the caller turned on recording for us,
;; it shouldn't apply when we check the
;; preceding label.
c-record-type-identifiers)
;; A label can't start at a cpp directive. Check for
;; this, since c-forward-syntactic-ws would foul up on it.
(unless (and c-opt-cpp-prefix (looking-at c-opt-cpp-prefix))
(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.
(cond
;; public: protected: private:
((and
(c-major-mode-is 'c++-mode)
(search-forward-regexp
"\\=p\\(r\\(ivate\\|otected\\)\\|ublic\\)\\_>" nil t)
(progn (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 (or (string= "signals" ; Special QT macro
(setq kwd (buffer-substring-no-properties start label-end)))
(string= "Q_SIGNALS" kwd))
'qt-1kwd-colon
'goto-target)))
((and qt-symbol-idx
(search-forward-regexp "\\=\\(slots\\|Q_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))
;; Check that `c-nonlabel-token-key' doesn't match anywhere.
(catch 'check-label
(goto-char start)
(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)
t)
(not (eobp)))))
;; Record the identifiers in the label for fontification, unless
;; it begins with `c-label-kwds' in which case the following
;; identifiers are part of a (constant) expression that
;; shouldn't be fontified.
(when (and c-record-type-identifiers
(progn (goto-char start)
(not (looking-at c-label-kwds-regexp))))
(while (c-syntactic-re-search-forward c-symbol-key nil t)
(c-record-ref-id (cons (match-beginning 0)
(match-end 0)))))
(c-put-c-type-property (1- (point-max)) 'c-decl-end)
(goto-char (point-max)))))
(t
;; Not a label.
(goto-char start)))
label-type))