Function: c-syntactic-skip-backward
c-syntactic-skip-backward is a byte-compiled function defined in
cc-engine.el.gz.
Signature
(c-syntactic-skip-backward SKIP-CHARS &optional LIMIT PAREN-LEVEL)
Documentation
Like skip-chars-backward but only look at syntactically relevant chars.
This means don't stop at positions inside syntactic whitespace or string literals. Preprocessor directives are also ignored, with the exception of the one that the point starts within, if any. If LIMIT is given, it's assumed to be at a syntactically relevant position.
If PAREN-LEVEL is non-nil, the function won't stop in nested paren sexps, and the search will also not go outside the current paren sexp. However, if LIMIT or the buffer limit is reached inside a nested paren then the point will be left at the limit.
Non-nil is returned if the point moved, nil otherwise.
Note that this function might do hidden buffer changes. See the comment at the start of cc-engine.el for more info.
Source Code
;; Defined in /usr/src/emacs/lisp/progmodes/cc-engine.el.gz
(defvar safe-pos-list) ; bound in c-syntactic-skip-backward
(defun c-syntactic-skip-backward (skip-chars &optional limit paren-level)
"Like `skip-chars-backward' but only look at syntactically relevant chars.
This means don't stop at positions inside syntactic whitespace or string
literals. Preprocessor directives are also ignored, with the exception
of the one that the point starts within, if any. If LIMIT is given,
it's assumed to be at a syntactically relevant position.
If PAREN-LEVEL is non-nil, the function won't stop in nested paren
sexps, and the search will also not go outside the current paren sexp.
However, if LIMIT or the buffer limit is reached inside a nested paren
then the point will be left at the limit.
Non-nil is returned if the point moved, nil otherwise.
Note that this function might do hidden buffer changes. See the
comment at the start of cc-engine.el for more info."
(let* ((start (point))
;; The result from `c-beginning-of-macro' at the start position or the
;; start position itself if it isn't within a macro.
(start-macro-beg
(save-excursion
(goto-char start)
(c-beginning-of-macro limit)
(point)))
lit-beg
;; The earliest position after the current one with the same paren
;; level. Used only when `paren-level' is set.
(paren-level-pos (point))
;; Whether we can optimize with an early `c-backward-syntactic-ws'.
(opt-ws (string-match "^\\^[^ \t\n\r]+$" skip-chars)))
;; In the next while form, we only loop when `skip-chars' is something
;; like "^/" and we've stopped at the end of a block comment.
(while
(progn
;; The next loop "tries" to find the end point each time round,
;; loops when it's ended up at the wrong level of nesting.
(while
(and
;; Optimize for, in particular, large blocks of comments from
;; `comment-region'.
(progn (when opt-ws
(let ((opt-pos (point)))
(c-backward-syntactic-ws limit)
(if (or (null limit)
(> (point) limit))
(setq paren-level-pos (point))
(goto-char opt-pos))))
t)
;; Move back to a candidate end point which isn't in a literal
;; or in a macro we didn't start in.
(let ((pos (point))
macro-start)
(while (and
(< (skip-chars-backward skip-chars limit) 0)
(or
(when (setq lit-beg (c-literal-start))
(goto-char lit-beg)
t)
;; Don't stop inside a macro we didn't start in.
(when
(save-excursion
(and (c-beginning-of-macro limit)
(< (point) start-macro-beg)
(setq macro-start (point))))
(goto-char macro-start))))
(when opt-ws
(let ((opt-pos (point)))
(c-backward-syntactic-ws limit)
(if (and limit
(<= (point) limit))
(goto-char opt-pos)))))
(< (point) pos))
;; Check whether we're at the wrong level of nesting (when
;; `paren-level' is non-nil).
(let ((pos (point)) state-2 pps-end-pos)
(when
(and paren-level
(save-excursion
(setq state-2 (parse-partial-sexp
pos paren-level-pos -1)
pps-end-pos (point))
(/= (car state-2) 0)))
;; Not at the right level.
(if (and (< (car state-2) 0)
;; We stop above if we go out of a paren.
;; Now check whether it precedes or is
;; nested in the starting sexp.
(save-excursion
(setq state-2
(parse-partial-sexp
pps-end-pos paren-level-pos
nil nil state-2))
(< (car state-2) 0)))
;; We've stopped short of the starting position
;; so the hit was inside a nested list. Go up
;; until we are at the right level.
(condition-case nil
(progn
(goto-char (scan-lists pos -1
(- (car state-2))))
(setq paren-level-pos (point))
(if (and limit (>= limit paren-level-pos))
(progn
(goto-char limit)
nil)
t))
(error
(goto-char (or limit (point-min)))
nil))
;; The hit was outside the list at the start
;; position. Go to the start of the list and exit.
(goto-char (1+ (elt state-2 1)))
nil)))))
(> (point)
(progn
;; Skip syntactic ws afterwards so that we don't stop at the
;; end of a comment if `skip-chars' is something like "^/".
(c-backward-syntactic-ws limit)
(point)))))
;; We might want to extend this with more useful return values in
;; the future.
(/= (point) start)))