Function: c-looking-at-decl-block

c-looking-at-decl-block is a byte-compiled function defined in cc-engine.el.gz.

Signature

(c-looking-at-decl-block GOTO-START &optional LIMIT)

Source Code

;; Defined in /usr/src/emacs/lisp/progmodes/cc-engine.el.gz
(defun c-looking-at-decl-block (goto-start &optional limit)
  ;; Assuming the point is at an open brace, check if it starts a
  ;; block that contains another declaration level, i.e. that isn't a
  ;; statement block or a brace list, and if so return non-nil.
  ;;
  ;; If the check is successful, the return value is the start of the
  ;; keyword that tells what kind of construct it is, i.e. typically
  ;; what `c-decl-block-key' matched.  Also, if GOTO-START is set then point
  ;; will be left at the start of the construct.  This is often at the
  ;; return value, but if there is a template preceding it, point will be
  ;; left at its start.  If there are Java annotations preceding it, point
  ;; will be left at the last of these.
  ;;
  ;; The point is clobbered if the check is unsuccessful.
  ;;
  ;; CONTAINING-SEXP is the position of the open of the surrounding
  ;; paren, or nil if none.
  ;;
  ;; The optional LIMIT limits the backward search for the start of
  ;; the construct.  It's assumed to be at a syntactically relevant
  ;; position.
  ;;
  ;; If any template arglists are found in the searched region before
  ;; the open brace, they get marked with paren syntax.
  ;;
  ;; This function might do hidden buffer changes.

  (let ((open-brace (point)) kwd-start first-specifier-pos)
    (c-syntactic-skip-backward c-block-prefix-charset limit t)

    (while
	(or
	 ;; Could be after a template arglist....
	 (and c-recognize-<>-arglists
	      (eq (char-before) ?>)
	      (let ((c-parse-and-markup-<>-arglists t))
		(c-backward-<>-arglist nil limit)))
	 ;; .... or after a noise clause with parens.
	 (and c-opt-cpp-prefix
	      (let ((after-paren (point)))
		(if (eq (char-before) ?\))
		    (and
		     (c-go-list-backward)
		     (eq (char-after) ?\()
		     (progn (c-backward-syntactic-ws)
			    (c-simple-skip-symbol-backward))
		     (or (looking-at c-paren-nontype-key) ; e.g. __attribute__
			 (looking-at c-noise-macro-with-parens-name-re)))
		  (goto-char after-paren)
		  nil))))
      (c-syntactic-skip-backward c-block-prefix-charset limit t))

    ;; Note: Can't get bogus hits inside template arglists below since they
    ;; have gotten paren syntax above.
    (when (and
	   ;; If `goto-start' is set we begin by searching for the
	   ;; first possible position of a leading specifier list.
	   ;; The `c-decl-block-key' search continues from there since
	   ;; we know it can't match earlier.
	   (if goto-start
	       (progn
		 (while
		     (and
		      (c-syntactic-re-search-forward c-symbol-start
						     open-brace t t)
		      (goto-char (match-beginning 0))
		      (if (or (looking-at c-noise-macro-name-re)
			      (looking-at c-noise-macro-with-parens-name-re))
			  (c-forward-noise-clause)
			(setq first-specifier-pos (match-beginning 0))
			nil)))
		 first-specifier-pos)
	     t)

	   (cond
	    ((c-syntactic-re-search-forward c-decl-block-key open-brace t t t)
	     (goto-char (setq kwd-start (match-beginning 0)))
	     (and
	      ;; Exclude cases where we matched what would ordinarily
	      ;; be an enum declaration keyword, except where it's not
	      ;; legal because it's part of a "compound keyword" like
	      ;; "enum class".	Of course, if c-after-enum-list-key
	      ;; is nil, we can skip the test.
	      (or (equal c-after-enum-list-key regexp-unmatchable)
		  (save-match-data
		    (save-excursion
		      (not
		       (and
			(looking-at c-after-enum-list-key)
			(= (c-backward-token-2 1 t) 0)
			(looking-at c-enum-list-key))))))
	      (or
	       ;; Found a keyword that can't be a type?
	       (match-beginning 1)

	       ;; Can be a type too, in which case it's the return type of a
	       ;; function (under the assumption that no declaration level
	       ;; block construct starts with a type).
	       (not (c-forward-type))

	       ;; Jumped over a type, but it could be a declaration keyword
	       ;; followed by the declared identifier that we've jumped over
	       ;; instead (e.g. in "class Foo {").  If it indeed is a type
	       ;; then we should be at the declarator now, so check for a
	       ;; valid declarator start.
	       ;;
	       ;; Note: This doesn't cope with the case when a declared
	       ;; identifier is followed by e.g. '(' in a language where '('
	       ;; also might be part of a declarator expression.  Currently
	       ;; there's no such language.
	       (not (or (looking-at c-symbol-start)
			(looking-at c-type-decl-prefix-key)
			(and (eq (char-after) ?{)
			     (not (c-looking-at-statement-block))))))))

	    ;; In Pike a list of modifiers may be followed by a brace
	    ;; to make them apply to many identifiers.	Note that the
	    ;; match data will be empty on return in this case.
	    ((and (c-major-mode-is 'pike-mode)
		  (progn
		    (goto-char open-brace)
		    (= (c-backward-token-2) 0))
		  (looking-at c-specifier-key)
		  ;; Use this variant to avoid yet another special regexp.
		  (c-keyword-member (c-keyword-sym (match-string 1))
				    'c-modifier-kwds))
	     (setq kwd-start (point))
	     t)))

      ;; Got a match.

      (if goto-start
	  ;; Back up over any preceding specifiers and their clauses
	  ;; by going forward from `first-specifier-pos', which is the
	  ;; earliest possible position where the specifier list can
	  ;; start.
	  (progn
	    (goto-char first-specifier-pos)

	    (while (< (point) kwd-start)
	      (cond
	       ((or (looking-at c-noise-macro-name-re)
		    (looking-at c-noise-macro-with-parens-name-re))
		(c-forward-noise-clause))
	       ((looking-at c-symbol-key)
		;; Accept any plain symbol token on the ground that
		;; it's a specifier masked through a macro (just
		;; like `c-forward-decl-or-cast-1' skips forward over
		;; such tokens).
		;;
		;; Could be more restrictive wrt invalid keywords,
		;; but that'd only occur in invalid code so there's
		;; no use spending effort on it.
		(let ((end (match-end 0))
		      (kwd-sym (c-keyword-sym (match-string 0)))
		      (annotation (and c-annotation-re
				       (looking-at c-annotation-re))))
		  (unless
		      (and kwd-sym
			   ;; Moving over a protection kwd and the following
			   ;; ":" (in C++ Mode) to the next token could take
			   ;; us all the way up to `kwd-start', leaving us
			   ;; no chance to update `first-specifier-pos'.
			   (not (c-keyword-member kwd-sym 'c-protection-kwds))
			   (c-forward-keyword-clause 0))
		    (goto-char end)
		    (c-forward-syntactic-ws)
		    (when annotation
		      (setq first-specifier-pos (match-beginning 0))
		      (when (and (eq (char-after) ?\()
				 (c-go-list-forward (point) kwd-start))
			(c-forward-syntactic-ws))))))

	       ((c-syntactic-re-search-forward c-symbol-start
					       kwd-start 'move t)
		;; Can't parse a declaration preamble and is still
		;; before `kwd-start'.  That means `first-specifier-pos'
		;; was in some earlier construct.  Search again.
		(goto-char (setq first-specifier-pos (match-beginning 0))))
	       (t
		  ;; Got no preamble before the block declaration keyword.
		  (setq first-specifier-pos kwd-start))))

	    (goto-char first-specifier-pos))
	(goto-char kwd-start))

      kwd-start)))