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