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