Function: c-add-stmt-syntax
c-add-stmt-syntax is a byte-compiled function defined in
cc-engine.el.gz.
Signature
(c-add-stmt-syntax SYNTAX-SYMBOL SYNTAX-EXTRA-ARGS STOP-AT-BOI-ONLY CONTAINING-SEXP PAREN-STATE &optional FIXED-ANCHOR)
Source Code
;; Defined in /usr/src/emacs/lisp/progmodes/cc-engine.el.gz
(defun c-add-stmt-syntax (syntax-symbol
syntax-extra-args
stop-at-boi-only
containing-sexp
paren-state
&optional fixed-anchor)
;; Add the indicated SYNTAX-SYMBOL to `c-syntactic-context', extending it as
;; needed with further syntax elements of the types `substatement',
;; `inexpr-statement', `arglist-cont-nonempty', `statement-block-intro',
;; `defun-block-intro', and `brace-list-intro'.
;;
;; Do the generic processing to anchor the given syntax symbol on the
;; preceding statement: First skip over any labels and containing statements
;; on the same line. If FIXED-ANCHOR is non-nil, use this as the
;; anchor-point for the given syntactic symbol, and don't make syntactic
;; entries for constructs beginning on lines before that containing
;; ANCHOR-POINT. Otherwise search backward until we find a statement or
;; block start that begins at boi without a label or comment.
;;
;; Point is assumed to be at the prospective anchor point for the
;; given SYNTAX-SYMBOL. More syntax entries are added if we need to
;; skip past open parens and containing statements. Most of the added
;; syntax elements will get the same anchor point - the exception is
;; for an anchor in a construct like "namespace"[*] - this is as early
;; as possible in the construct but on the same line as the {.
;;
;; [*] i.e. with a keyword matching c-other-block-decl-kwds.
;;
;; SYNTAX-EXTRA-ARGS are a list of the extra arguments for the
;; syntax symbol. They are appended after the anchor point.
;;
;; If STOP-AT-BOI-ONLY is nil, we can stop in the middle of the line
;; if the current statement starts there.
;;
;; Note: It's not a problem if PAREN-STATE "overshoots"
;; CONTAINING-SEXP, i.e. contains info about parens further down.
;;
;; This function might do hidden buffer changes.
(if (= (point) (c-point 'boi))
;; This is by far the most common case, so let's give it special
;; treatment.
(apply 'c-add-syntax syntax-symbol (point) syntax-extra-args)
(let ((syntax-last c-syntactic-context)
(boi (c-point 'boi))
(anchor-boi (c-point 'boi))
;; Set when we're on a label, so that we don't stop there.
;; FIXME: To be complete we should check if we're on a label
;; now at the start.
on-label)
;; Use point as the anchor point for "namespace", "extern", etc.
(apply 'c-add-syntax syntax-symbol
(if (rassq syntax-symbol c-other-decl-block-key-in-symbols-alist)
(point) nil)
syntax-extra-args)
;; Loop while we have to back out of containing blocks.
(while
(and
(catch 'back-up-block
;; Loop while we have to back up statements.
(while (or (/= (point) boi)
on-label
(looking-at c-comment-start-regexp))
;; Skip past any comments that stands between the
;; statement start and boi.
(let ((savepos (point)))
(while (and (/= savepos boi)
(c-backward-single-comment))
(setq savepos (point)
boi (c-point 'boi)))
(goto-char savepos))
;; Skip to the beginning of this statement or backward
;; another one.
(let ((old-pos (point))
(old-boi boi)
(step-type (c-beginning-of-statement-1 containing-sexp)))
(setq boi (c-point 'boi)
on-label (eq step-type 'label))
(cond ((= (point) old-pos)
;; If we didn't move we're at the start of a block and
;; have to continue outside it.
(throw 'back-up-block t))
((and (eq step-type 'up)
(>= (point) old-boi)
(looking-at "else\\>[^_]")
(save-excursion
(goto-char old-pos)
(looking-at "if\\>[^_]")))
;; Special case to avoid deeper and deeper indentation
;; of "else if" clauses.
)
((and (not stop-at-boi-only)
(/= old-pos old-boi)
(memq step-type '(up previous)))
;; If stop-at-boi-only is nil, we shouldn't back up
;; over previous or containing statements to try to
;; reach boi, so go back to the last position and
;; exit.
(goto-char old-pos)
(throw 'back-up-block nil))
(t
(if (and (not stop-at-boi-only)
(memq step-type '(up previous beginning)))
;; If we've moved into another statement then we
;; should no longer try to stop in the middle of a
;; line.
(setq stop-at-boi-only t))
;; Record this as a substatement if we skipped up one
;; level.
(when (eq step-type 'up)
(c-add-syntax 'substatement nil))))
)))
containing-sexp
(or (null fixed-anchor)
(> containing-sexp anchor-boi)))
;; Now we have to go out of this block.
(goto-char containing-sexp)
;; Don't stop in the middle of a special brace list opener
;; like "({".
(when c-special-brace-lists
(let ((special-list (c-looking-at-special-brace-list)))
(when (and special-list
(< (car (car special-list)) (point)))
(setq containing-sexp (car (car special-list)))
(goto-char containing-sexp))))
(setq paren-state (c-whack-state-after containing-sexp paren-state)
containing-sexp (c-most-enclosing-brace paren-state)
boi (c-point 'boi))
;; Analyze the construct in front of the block we've stepped out
;; from and add the right syntactic element for it.
(let ((paren-pos (point))
(paren-char (char-after))
step-type)
(if (eq paren-char ?\()
;; Stepped out of a parenthesis block, so we're in an
;; expression now.
(progn
(when (/= paren-pos boi)
(if (and c-recognize-paren-inexpr-blocks
(progn
(c-backward-syntactic-ws containing-sexp)
(or (not (looking-at "\\>"))
(not (c-on-identifier))))
(save-excursion
(goto-char (1+ paren-pos))
(c-forward-syntactic-ws)
(eq (char-after) ?{)))
;; Stepped out of an in-expression statement. This
;; syntactic element won't get an anchor pos.
(c-add-syntax 'inexpr-statement)
;; A parenthesis normally belongs to an arglist.
(c-add-syntax 'arglist-cont-nonempty nil paren-pos)))
(goto-char (max boi
(if containing-sexp
(1+ containing-sexp)
(point-min))))
(setq step-type 'same
on-label nil))
;; Stepped out of a brace block.
(setq step-type (c-beginning-of-statement-1 containing-sexp)
on-label (eq step-type 'label))
(if (and (eq step-type 'same)
(/= paren-pos (point)))
(let (inexpr bspec)
(cond
((save-excursion
(goto-char paren-pos)
(setq inexpr (c-looking-at-inexpr-block
(c-safe-position containing-sexp paren-state)
containing-sexp)))
(c-add-syntax (if (eq (car inexpr) 'inlambda)
'defun-block-intro
'statement-block-intro)
nil))
((looking-at c-other-decl-block-key)
(c-add-syntax
(cdr (assoc (match-string 1)
c-other-decl-block-key-in-symbols-alist))
(max (c-point 'boi paren-pos) (point))))
((c-inside-bracelist-p paren-pos paren-state nil)
(if (save-excursion
(goto-char paren-pos)
(c-looking-at-statement-block))
(c-add-syntax 'defun-block-intro nil)
(c-add-syntax 'brace-list-intro nil)))
((save-excursion
(goto-char paren-pos)
(setq bspec (c-looking-at-or-maybe-in-bracelist
containing-sexp containing-sexp))
(and (consp bspec)
(eq (cdr bspec) 'in-paren)))
(c-add-syntax 'brace-list-intro (car bspec)))
(t (c-add-syntax 'defun-block-intro nil))))
(c-add-syntax 'statement-block-intro nil)))
(if (= paren-pos boi)
;; Always done if the open brace was at boi. The
;; c-beginning-of-statement-1 call above is necessary
;; anyway, to decide the type of block-intro to add.
(goto-char paren-pos)
(setq boi (c-point 'boi)))
))
;; Fill in the current point as the anchor for all the symbols
;; added above.
(let ((p c-syntactic-context) q)
(while (not (eq p syntax-last))
(setq q (cdr (car p))) ; e.g. (nil 28) [from (arglist-cont-nonempty nil 28)]
(while q
(unless (car q)
(setcar q (if (or (cdr p)
(null fixed-anchor))
(point)
fixed-anchor)))
(setq q (cdr q)))
(setq p (cdr p))))
)))