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))