Function: c-beginning-of-decl-1

c-beginning-of-decl-1 is a byte-compiled function defined in cc-engine.el.gz.

Signature

(c-beginning-of-decl-1 &optional LIM)

Source Code

;; Defined in /usr/src/emacs/lisp/progmodes/cc-engine.el.gz
(defun c-beginning-of-decl-1 (&optional lim)
  ;; Go to the beginning of the current declaration, or the beginning
  ;; of the previous one if already at the start of it.  Point won't
  ;; be moved out of any surrounding paren.  Return a cons cell of the
  ;; form (MOVE . KNR-POS).  MOVE is like the return value from
  ;; `c-beginning-of-statement-1'.  If point skipped over some K&R
  ;; style argument declarations (and they are to be recognized) then
  ;; KNR-POS is set to the start of the first such argument
  ;; declaration, otherwise KNR-POS is nil.  If LIM is non-nil, it's a
  ;; position that bounds the backward search.
  ;;
  ;; NB: Cases where the declaration continues after the block, as in
  ;; "struct foo { ... } bar;", are currently recognized as two
  ;; declarations, e.g. "struct foo { ... }" and "bar;" in this case.
  ;;
  ;; This function might do hidden buffer changes.
  (catch 'return
    (let* ((start (point))
	   (last-stmt-start (point))
	   (move (c-beginning-of-statement-1 lim nil t)))

      ;; `c-beginning-of-statement-1' stops at a block start, but we
      ;; want to continue if the block doesn't begin a top level
      ;; construct, i.e. if it isn't preceded by ';', '}', ':', bob,
      ;; or an open paren.
      (let ((beg (point)) tentative-move)
	;; Go back one "statement" each time round the loop until we're just
	;; after a ;, }, or :, or at BOB or the start of a macro or start of
	;; an ObjC method.  This will move over a multiple declaration whose
	;; components are comma separated.
	(while (and
		;; Must check with c-opt-method-key in ObjC mode.
		(not (and c-opt-method-key
			  (looking-at c-opt-method-key)))
		(/= last-stmt-start (point))
		(progn
		  (c-backward-syntactic-ws lim)
		  (not (or (memq (char-before) '(?\; ?} ?: nil))
			   (c-at-vsemi-p))))
		(not (and lim (<= (point) lim)))
		(save-excursion
		  (backward-char)
		  (not (looking-at "\\s(")))
		;; Check that we don't move from the first thing in a
		;; macro to its header.
		(not (eq (setq tentative-move
			       (c-beginning-of-statement-1 lim nil t))
			 'macro)))
	  (setq last-stmt-start beg
		beg (point)
		move tentative-move))
	(goto-char beg))

      (when c-recognize-knr-p
	(let ((fallback-pos (point)) knr-argdecl-start)
	  ;; Handle K&R argdecls.  Back up after the "statement" jumped
	  ;; over by `c-beginning-of-statement-1', unless it was the
	  ;; function body, in which case we're sitting on the opening
	  ;; brace now.  Then test if we're in a K&R argdecl region and
	  ;; that we started at the other side of the first argdecl in
	  ;; it.
	  (unless (eq (char-after) ?{)
	    (goto-char last-stmt-start))
	  (if (and (setq knr-argdecl-start (c-in-knr-argdecl lim))
		   (< knr-argdecl-start start)
		   (progn
		     (goto-char knr-argdecl-start)
		     (not (eq (c-beginning-of-statement-1 lim nil t) 'macro))))
	      (throw 'return
		     (cons (if (eq (char-after fallback-pos) ?{)
			       'previous
			     'same)
			   knr-argdecl-start))
	    (goto-char fallback-pos))))

      ;; `c-beginning-of-statement-1' counts each brace block as a separate
      ;; statement, so the result will be 'previous if we've moved over any.
      ;; So change our result back to 'same if necessary.
      ;;
      ;; If they were brace list initializers we might not have moved over a
      ;; declaration boundary though, so change it to 'same if we've moved
      ;; past a '=' before '{', but not ';'.  (This ought to be integrated
      ;; into `c-beginning-of-statement-1', so we avoid this extra pass which
      ;; potentially can search over a large amount of text.).  Take special
      ;; pains not to get mislead by C++'s "operator=", and the like.
      (if (and (eq move 'previous)
	       (save-excursion
		 (and
		  (progn
		    (while   ; keep going back to "[;={"s until we either find
			     ; no more, or get to one which isn't an "operator ="
			(and (c-syntactic-re-search-forward "[;={]" start t t t)
			     (eq (char-before) ?=)
			     c-overloadable-operators-regexp
			     c-opt-op-identifier-prefix
			     (save-excursion
			       (eq (c-backward-token-2) 0)
			       (looking-at c-overloadable-operators-regexp)
			       (eq (c-backward-token-2) 0)
			       (looking-at c-opt-op-identifier-prefix))))
		    (eq (char-before) ?=))
		  (c-syntactic-re-search-forward "[;{]" start t t)
		  (eq (char-before) ?{)
		  (c-safe (goto-char (c-up-list-forward (point))) t)
		  (not (c-syntactic-re-search-forward ";" start t t)))))
	  (cons 'same nil)
	(cons move nil)))))