Function: c-scan-conditionals

c-scan-conditionals is a byte-compiled function defined in cc-cmds.el.gz.

Signature

(c-scan-conditionals COUNT &optional TARGET-DEPTH WITH-ELSE)

Documentation

Scan forward across COUNT preprocessor conditionals.

With a negative argument, scan backward across preprocessor conditionals. Return the end position. Point is not moved.

If there aren't enough preprocessor conditionals, throw an error.

"#elif" is treated like "#else" followed by "#if", except that
the nesting level isn't changed when tracking subconditionals.

The optional argument TARGET-DEPTH specifies the wanted nesting depth after each scan. E.g. if TARGET-DEPTH is -1, the end position will be outside the enclosing conditional. A non-integer non-nil TARGET-DEPTH counts as -1.

If the optional argument WITH-ELSE is non-nil, "#else" directives are treated as conditional clause limits. Normally they are ignored.

Source Code

;; Defined in /usr/src/emacs/lisp/progmodes/cc-cmds.el.gz
(defun c-scan-conditionals (count &optional target-depth with-else)
  "Scan forward across COUNT preprocessor conditionals.
With a negative argument, scan backward across preprocessor
conditionals.  Return the end position.  Point is not moved.

If there aren't enough preprocessor conditionals, throw an error.

\"#elif\" is treated like \"#else\" followed by \"#if\", except that
the nesting level isn't changed when tracking subconditionals.

The optional argument TARGET-DEPTH specifies the wanted nesting depth
after each scan.  E.g. if TARGET-DEPTH is -1, the end position will be
outside the enclosing conditional.  A non-integer non-nil TARGET-DEPTH
counts as -1.

If the optional argument WITH-ELSE is non-nil, \"#else\" directives
are treated as conditional clause limits.  Normally they are ignored."
  (let* ((forward (> count 0))
	 (increment (if forward -1 1))
	 (search-function (if forward 're-search-forward 're-search-backward))
	 new case-fold-search)
    (unless (integerp target-depth)
      (setq target-depth (if target-depth -1 0)))
    (save-excursion
      (while (/= count 0)
	(let ((depth 0)
	      ;; subdepth is the depth in "uninteresting" subtrees,
	      ;; i.e. those that takes us farther from the target
	      ;; depth instead of closer.
	      (subdepth 0)
	      found)
	  (save-excursion
	    ;; Find the "next" significant line in the proper direction.
	    (while (and (not found)
			;; Rather than searching for a # sign that
			;; comes at the beginning of a line aside from
			;; whitespace, search first for a string
			;; starting with # sign.  Then verify what
			;; precedes it.  This is faster on account of
			;; the fastmap feature of the regexp matcher.
			(funcall search-function
				 "#[ \t]*\\(if\\|elif\\|endif\\|else\\)"
				 nil t))
	      (beginning-of-line)
	      ;; Now verify it is really a preproc line.
	      (if (looking-at "^[ \t]*#[ \t]*\\(if\\|elif\\|endif\\|else\\)")
		  (let (dchange (directive (match-string 1)))
		    (cond ((string= directive "if")
			   (setq dchange (- increment)))
			  ((string= directive "endif")
			   (setq dchange increment))
			  ((= subdepth 0)
			   ;; When we're not in an "uninteresting"
			   ;; subtree, we might want to act on "elif"
			   ;; and "else" too.
			   (if (cond (with-else
				      ;; Always move toward the target depth.
				      (setq dchange
					    (if (> target-depth 0) 1 -1)))
				     ((string= directive "elif")
				      (setq dchange (- increment))))
			       ;; Ignore the change if it'd take us
			       ;; into an "uninteresting" subtree.
			       (if (eq (> dchange 0) (<= target-depth 0))
				   (setq dchange nil)))))
		    (when dchange
		      (when (or (/= subdepth 0)
				(eq (> dchange 0) (<= target-depth 0)))
			(setq subdepth (+ subdepth dchange)))
		      (setq depth (+ depth dchange))
		      ;; If we are trying to move across, and we find an
		      ;; end before we find a beginning, get an error.
		      (if (and (< depth target-depth) (< dchange 0))
			  (error (if forward
				     "No following conditional at this level"
				   "No previous conditional at this level"))))
		    ;; When searching forward, start from next line so
		    ;; that we don't find the same line again.
		    (if forward (forward-line 1))
		    ;; We found something if we've arrived at the
		    ;; target depth.
		    (if (and dchange (= depth target-depth))
			(setq found (point))))
		;; else
		(if forward (forward-line 1)))))
	  (or found
	      (error "No containing preprocessor conditional"))
	  (goto-char (setq new found)))
	(setq count (+ count increment))))
    (c-keep-region-active)
    new))