Function: c-beginning-of-statement

c-beginning-of-statement is an interactive and byte-compiled function defined in cc-cmds.el.gz.

Signature

(c-beginning-of-statement &optional COUNT LIM SENTENCE-FLAG)

Documentation

Go to the beginning of the innermost C statement.

With prefix arg, go back N - 1 statements. If already at the beginning of a statement then go to the beginning of the closest preceding one, moving into nested blocks if necessary (use C-M-b (backward-sexp) to skip over a block). If within or next to a comment or multiline string, move by sentences instead of statements.

When called from a program, this function takes 3 optional args: the repetition count, a buffer position limit which is the farthest back to search for the syntactic context, and a flag saying whether to do sentence motion in or near comments and multiline strings.

Note that for use in programs, c-beginning-of-statement-1 is usually better. It has much better defined semantics than this one, which is intended for interactive use, and might therefore change to be more "DWIM:ey".

Probably introduced at or before Emacs version 19.20.

Key Bindings

Source Code

;; Defined in /usr/src/emacs/lisp/progmodes/cc-cmds.el.gz
(defun c-beginning-of-statement (&optional count lim sentence-flag)
  "Go to the beginning of the innermost C statement.
With prefix arg, go back N - 1 statements.  If already at the
beginning of a statement then go to the beginning of the closest
preceding one, moving into nested blocks if necessary (use
\\[backward-sexp] to skip over a block).  If within or next to a
comment or multiline string, move by sentences instead of statements.

When called from a program, this function takes 3 optional args: the
repetition count, a buffer position limit which is the farthest back
to search for the syntactic context, and a flag saying whether to do
sentence motion in or near comments and multiline strings.

Note that for use in programs, `c-beginning-of-statement-1' is
usually better.  It has much better defined semantics than this one,
which is intended for interactive use, and might therefore change to
be more \"DWIM:ey\"."
  (interactive (list (prefix-numeric-value current-prefix-arg)
		     nil t))
  (if (< count 0)
      (c-end-of-statement (- count) lim sentence-flag)
    (c-save-buffer-state
	((count (or count 1))
	 last ; start point for going back ONE chunk.  Updated each chunk movement.
	 (macro-fence
	  (save-excursion (and (not (bobp)) (c-beginning-of-macro) (point))))
	 res				; result from sub-function call
	 not-bos			; "not beginning-of-statement"
	 (range (c-collect-line-comments (c-literal-limits lim)))) ; (start.end) of current literal or NIL

      ;; Go back one statement at each iteration of the following loop.
      (while (and (/= count 0)
		  (or (not lim) (> (point) lim)))
	;; Go back one "chunk" each time round the following loop, stopping
	;; when we reach a statement boundary, etc.
	(setq last (point))
	(while
	    (cond ; Each arm of this cond returns NIL on reaching a desired
		  ; statement boundary, non-NIL otherwise.
	     ((bobp)
	      (setq count 0)
	      nil)

	     (range		   ; point is within or approaching a literal.
	      (cond
	       ;; Single line string or sentence-flag is null => skip the
	       ;; entire literal.
	       ((or (null sentence-flag)
		    (c-one-line-string-p range))
		(goto-char (car range))
		(setq range (c-ascertain-preceding-literal))
		;; N.B. The following is essentially testing for an AWK regexp
		;; at BOS:
		;; Was the previous non-ws thing an end of statement?
		(save-excursion
		  (if macro-fence
		      (c-backward-comments)
		    (c-backward-syntactic-ws))
		  (not (or (bobp) (c-after-statement-terminator-p)))))

	       ;; Comment inside a statement or a multi-line string.
	       (t (when (setq res ; returns non-nil when we go out of the literal
			      (if (eq (c-literal-type range) 'string)
				  (c-beginning-of-sentence-in-string range)
				(c-beginning-of-sentence-in-comment range)))
		    (setq range (c-ascertain-preceding-literal)))
		  res)))

	     ;; Non-literal code.
	     (t (setq res (c-back-over-illiterals macro-fence))
		(setq not-bos	       ; "not reached beginning-of-statement".
		      (or (= (point) last)
			  (memq (char-after) '(?\) ?\}))
			  (and
			   (car res)
			   ;; We're at a tentative BOS.  The next form goes
			   ;; back over WS looking for an end of previous
			   ;; statement.
			   (not (save-excursion
				  (if macro-fence
				      (c-backward-comments)
				    (c-backward-syntactic-ws))
				  (or (bobp) (c-after-statement-terminator-p)))))))
		;; Are we about to move backwards into or out of a
		;; preprocessor command?  If so, locate its beginning.
		(when (eq (cdr res) 'macro-boundary)
		  (save-excursion
		    (beginning-of-line)
		    (setq macro-fence
			  (and (not (bobp))
			       (progn (c-skip-ws-backward) (c-beginning-of-macro))
			       (point)))))
		;; Are we about to move backwards into a literal?
		(when (memq (cdr res) '(macro-boundary literal))
		  (setq range (c-ascertain-preceding-literal)))
		not-bos))
	  (setq last (point)))

	(if (/= count 0) (setq count (1- count))))
      (c-keep-region-active))))