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