Function: c-forward-name

c-forward-name is a byte-compiled function defined in cc-engine.el.gz.

Signature

(c-forward-name &optional STOP-AT-END)

Source Code

;; Defined in /usr/src/emacs/lisp/progmodes/cc-engine.el.gz
(defun c-forward-name (&optional stop-at-end)
  ;; Move forward over a complete name if at the beginning of one, stopping
  ;; either at the next following token or (when STOP-AT-END is non-nil) at
  ;; the end of the name.  A keyword, as such, doesn't count as a name.  If
  ;; the point is not at something that is recognized as a name then it stays
  ;; put.
  ;;
  ;; A name could be something as simple as "foo" in C or something as
  ;; complex as "X<Y<class A<int>::B, BIT_MAX >> b>, ::operator<> ::
  ;; Z<(a>b)> :: operator const X<&foo>::T Q::G<unsigned short
  ;; int>::*volatile const" in C++ (this function is actually little
  ;; more than a `looking-at' call in all modes except those that,
  ;; like C++, have `c-recognize-<>-arglists' set).
  ;;
  ;; Return
  ;; o - nil if no name is found;
  ;; o - 'template if it's an identifier ending with an angle bracket
  ;;   arglist;
  ;; o - 'operator if it's an operator identifier;
  ;; o - t if it's some other kind of name.
  ;;
  ;; This function records identifier ranges on
  ;; `c-record-type-identifiers' and `c-record-ref-identifiers' if
  ;; `c-record-type-identifiers' is non-nil.
  ;;
  ;; This function might do hidden buffer changes.

  (let ((pos (point)) pos2 pos3 (start (point)) res id-start id-end
	;; Turn off `c-promote-possible-types' here since we might
	;; call `c-forward-<>-arglist' and we don't want it to promote
	;; every suspect thing in the arglist to a type.  We're
	;; typically called from `c-forward-type' in this case, and
	;; the caller only wants the top level type that it finds to
	;; be promoted.
	c-promote-possible-types
	(lim+ (c-determine-+ve-limit 500)))
    (while
	(and
	 (< (point) lim+)
	 (looking-at c-identifier-key)

	 (progn
	   ;; Check for keyword.  We go to the last symbol in
	   ;; `c-identifier-key' first.
	   (goto-char (setq id-end (match-end 0)))
	   (c-simple-skip-symbol-backward)
	   (setq id-start (point))

	   (if (looking-at c-keywords-regexp)
	       (when (and (c-major-mode-is 'c++-mode)
			  (looking-at
			   (cc-eval-when-compile
			     (concat "\\(operator\\|\\(template\\)\\)"
				     "\\(" (c-lang-const c-nonsymbol-key c++)
				     "\\|$\\)")))
			  (if (match-beginning 2)
			      ;; "template" is only valid inside an
			      ;; identifier if preceded by "::".
			      (save-excursion
				(c-backward-syntactic-ws)
				(and (c-safe (backward-char 2) t)
				     (looking-at "::")))
			    t))

		 ;; Handle a C++ operator or template identifier.
		 (goto-char id-end)
		 (c-forward-syntactic-ws lim+)
		 (cond ((eq (char-before id-end) ?e)
			;; Got "... ::template".
			(let ((subres (c-forward-name t)))
			  (when subres
			    (setq pos (point)
				  res subres))))

		       ((and (looking-at c-identifier-start)
			     (or (not (looking-at
 c-ambiguous-overloadable-or-identifier-prefix-re))
				 (save-excursion
				   (and (eq (c-forward-token-2) 0)
					(not (eq (char-after) ?\())))))
			;; Got a cast operator.
			(when (c-forward-type nil t)
			  (setq pos (point)
				res 'operator)
			  ;; Now we should match a sequence of either
			  ;; '*', '&' or a name followed by ":: *",
			  ;; where each can be followed by a sequence
			  ;; of `c-opt-type-modifier-key'.
			  (while
			      (and
			       (< (point) lim+)
			       (cond ((looking-at "[*&]")
				      (goto-char (match-end 0))
				      t)
				     ((looking-at c-identifier-start)
				      (and (c-forward-name)
					   (looking-at "::")
					   (progn
					     (goto-char (match-end 0))
					     (c-forward-syntactic-ws lim+)
					     (eq (char-after) ?*))
					   (progn
					     (forward-char)
					     t)))))
			    (while (progn
				     (setq pos (point))
				     (c-forward-syntactic-ws lim+)
				     (and
				      (<= (point) lim+)
				      (looking-at c-opt-type-modifier-key)))
			      (goto-char (match-end 1))))))

		       ((looking-at c-overloadable-operators-regexp)
			;; Got some other operator.
			(setq c-last-identifier-range
			      (cons (point) (match-end 0)))
			(if (and (eq (char-after) ?\")
				 (eq (char-after (1+ (point))) ?\"))
			    ;; operator"" has an (?)optional tag after it.
			    (progn
			      (goto-char (match-end 0))
			      (setq pos2 (point))
			      (c-forward-syntactic-ws lim+)
			      (when (c-on-identifier)
				(c-forward-over-token nil lim+)))
			  (goto-char (match-end 0))
			  (setq pos2 (point))
			  (c-forward-syntactic-ws lim+))
			(setq pos pos2
			      res 'operator)))

		 nil)

	     ;; `id-start' is equal to `id-end' if we've jumped over
	     ;; an identifier that doesn't end with a symbol token.
	     ;; That can occur e.g. for Java import directives of the
	     ;; form "foo.bar.*".
	     (when (and id-start (/= id-start id-end))
	       (setq c-last-identifier-range
		     (cons id-start id-end)))
	     (goto-char id-end)
	     (setq pos (point))
	     (c-forward-syntactic-ws lim+)
	     (setq res t)))

	 (progn
	   (goto-char pos)
	   (c-forward-syntactic-ws lim+)
	   (setq pos3 (point))
	   (when (or c-opt-identifier-concat-key
		     c-recognize-<>-arglists)

	     (cond
	      ((and c-opt-identifier-concat-key
		    (looking-at c-opt-identifier-concat-key))
	       ;; Got a concatenated identifier.  This handles the
	       ;; cases with tricky syntactic whitespace that aren't
	       ;; covered in `c-identifier-key'.
	       (goto-char (match-end 0))
	       t)

	      ((and c-recognize-<>-arglists
		    (eq (char-after) ?<))
	       ;; Maybe an angle bracket arglist.
	       (when (let (c-last-identifier-range)
		       (c-forward-<>-arglist nil))
		 ;; <> arglists can legitimately be very long, so recalculate
		 ;; `lim+'.
		 (setq lim+ (c-determine-+ve-limit 500))

		 (setq pos2 (point))
		 (c-forward-syntactic-ws lim+)
		 (unless (eq (char-after) ?\()
		   (setq c-last-identifier-range nil)
		   (c-add-type start (1+ pos3)))
		 (setq pos pos2)

		 (if (and c-opt-identifier-concat-key
			  (looking-at c-opt-identifier-concat-key))

		     ;; Continue if there's an identifier concatenation
		     ;; operator after the template argument.
		     (progn
		       (when (and c-record-type-identifiers id-start)
			 (c-record-ref-id (cons id-start id-end)))
		       (goto-char (match-end 0))
		       (c-forward-syntactic-ws lim+)
		       t)

		   (when (and c-record-type-identifiers id-start
			      (not (eq (char-after) ?\()))
		     (c-record-type-id (cons id-start id-end)))
		   (setq res 'template)
		   nil)))
	      )))))

    (goto-char pos)
    (unless stop-at-end
      (c-forward-syntactic-ws lim+))
    res))