Function: c-back-over-illiterals
c-back-over-illiterals is a byte-compiled function defined in
cc-cmds.el.gz.
Signature
(c-back-over-illiterals MACRO-START)
Source Code
;; Defined in /usr/src/emacs/lisp/progmodes/cc-cmds.el.gz
(defun c-back-over-illiterals (macro-start)
;; Move backwards over code which isn't a literal (i.e. comment or string),
;; stopping before reaching BOB or a literal or the boundary of a
;; preprocessor statement or the "beginning of a statement". MACRO-START is
;; the position of the '#' beginning the current preprocessor directive, or
;; NIL if we're not in such.
;;
;; Return a cons (A.B), where
;; A is NIL if we moved back to a BOS (and know it), T otherwise (we
;; didn't move, or we hit a literal, or we're not sure about BOS).
;; B is MACRO-BOUNDARY if we are about to cross the boundary out of or
;; into a macro, otherwise LITERAL if we've hit a literal, otherwise NIL
;;
;; The total collection of returned values is as follows:
;; (nil . nil): Found a BOS whilst remaining inside the illiterals.
;; (t . literal): No BOS found: only a comment/string. We _might_ be at
;; a BOS - the caller must check this.
;; (nil . macro-boundary): only happens with non-nil macro-start. We've
;; moved and reached the opening # of the macro.
;; (t . macro-boundary): Every other circumstance in which we're at a
;; macro-boundary. We might be at a BOS.
;;
;; Point is left either at the beginning-of-statement, or at the last non-ws
;; code before encountering the literal/BOB or macro-boundary.
;;
;; Note that this function moves within either preprocessor commands
;; (macros) or normal code, but will not cross a boundary between the two,
;; or between two distinct preprocessor commands.
;;
;; Stop before `{' and after `;', `{', `}' and `};' when not followed by `}'
;; or `)', but on the other side of the syntactic ws. Move by sexps and
;; move into parens. Also stop before `#' when it's at boi on a line.
;;
;; This function might do hidden buffer changes.
(save-match-data
(let ((here (point))
last) ; marks the position of non-ws code, what'll be BOS if, say, a
; semicolon precedes it.
(catch 'done
(while t ;; We go back one "token" each iteration of the loop.
(setq last (point))
(cond
;; Stop at the token after a comment.
((c-backward-single-comment) ; Also functions as backwards-ws.
(goto-char last)
(throw 'done '(t . literal)))
;; If we've gone back over a LF, we might have moved into or out of
;; a preprocessor line.
((and (save-excursion
(beginning-of-line)
(re-search-forward "\\(^\\|[^\\]\\)[\n\r]" last t))
(if macro-start
(< (point) macro-start)
(c-beginning-of-macro)))
(goto-char last)
;; Return a car of NIL ONLY if we've hit the opening # of a macro.
(throw 'done (cons (or (eq (point) here)
(not macro-start))
'macro-boundary)))
;; Have we found a virtual semicolon? If so, stop, unless the next
;; statement is where we started from.
((and (c-at-vsemi-p)
(< last here)
(not (memq (char-after last) '(?\) ?})))) ; we've moved back from ) or }
(goto-char last)
(throw 'done '(nil . nil)))
;; Hit the beginning of the buffer/region?
((bobp)
(if (/= here last)
(goto-char last))
(throw 'done '(nil . nil)))
;; Move back a character.
((progn (backward-char) nil))
;; Stop at "{" (unless it's a PIKE special brace list.)
((eq (char-after) ?\{)
(if (and c-special-brace-lists
(c-looking-at-special-brace-list))
(skip-syntax-backward "w_") ; Speedup only.
(if (/= here last)
(goto-char last))
(throw 'done '(nil . nil))))
;; Have we reached the start of a macro? This always counts as
;; BOS. (N.B. I don't think (eq (point) here) can ever be true
;; here. FIXME!!! ACM 2004/3/29)
((and macro-start (eq (point) macro-start))
(throw 'done (cons (eq (point) here) 'macro-boundary)))
;; Stop at token just after "}" or ";".
((looking-at "[;}]")
;; If we've gone back over ;, {, or }, we're done.
(if (or (= here last)
(memq (char-after last) '(?\) ?}))) ; we've moved back from ) or }
(if (and (eq (char-before) ?}) ; If };, treat them as a unit.
(eq (char-after) ?\;))
(backward-char))
(goto-char last) ; To the statement starting after the ; or }.
(throw 'done '(nil . nil))))
;; Stop at the token after a string.
((looking-at c-string-limit-regexp) ; Just gone back over a string terminator?
(goto-char last)
(throw 'done '(t . literal)))
;; Nothing special: go back word characters.
(t (skip-syntax-backward "w_")) ; Speedup only.
))))))