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