Function: c-forward-sws

c-forward-sws is a byte-compiled function defined in cc-engine.el.gz.

Signature

(c-forward-sws)

Documentation

This function has :around advice: No documentation

Aliases

antlr-c-forward-sws

Source Code

;; Defined in /usr/src/emacs/lisp/progmodes/cc-engine.el.gz
(defun c-forward-sws ()
  ;; Used by `c-forward-syntactic-ws' to implement the unbounded search.
  ;;
  ;; This function might do hidden buffer changes.

  (let (;; `rung-pos' is set to a position as early as possible in the
	;; unmarked part of the simple ws region.
	(rung-pos (point)) next-rung-pos rung-end-pos last-put-in-sws-pos
	rung-is-marked next-rung-is-marked simple-ws-end macro-start macro-end
	;; `safe-start' is set when it's safe to cache the start position.
	;; This is the case except when we have an unterminated block comment
	;; within a macro.
	safe-start)

    ;; Skip simple ws and do a quick check on the following character to see
    ;; if it's anything that can't start syntactic ws, so we can bail out
    ;; early in the majority of cases when there just are a few ws chars.
    (skip-chars-forward " \t\n\r\f\v")
    (when (or (looking-at c-syntactic-ws-start)
	      (and c-opt-cpp-prefix
		   (looking-at c-noise-macro-name-re))
	      (and (c-major-mode-is 'c++-mode)
		   (looking-at "\\[\\["))
	      (looking-at c-doc-line-join-re))

      (setq rung-end-pos (min (1+ (point)) (point-max)))
      (if (setq rung-is-marked (text-property-any rung-pos rung-end-pos
						  'c-is-sws t))
	  ;; Find the last rung position to avoid setting properties in all
	  ;; the cases when the marked rung is complete.
	  ;; (`next-single-property-change' is certain to move at least one
	  ;; step forward.)
	  (setq rung-pos (1- (c-next-single-property-change
			      rung-is-marked 'c-is-sws nil rung-end-pos)))
	;; Got no marked rung here.  Since the simple ws might have started
	;; inside a line comment or cpp directive we must set `rung-pos' as
	;; high as possible.
	(setq rung-pos (point)))

      (with-silent-modifications
      (while
	  (progn
	    ;; In the following while form, we move over a "ladder" and
	    ;; following simple WS each time round the loop, appending the WS
	    ;; onto the ladder, joining adjacent ladders, and terminating when
	    ;; there is no more WS or we reach EOB.
	    (while
		(when (and rung-is-marked
			   (get-text-property (point) 'c-in-sws))

		  ;; The following search is the main reason that `c-in-sws'
		  ;; and `c-is-sws' aren't combined to one property.
		  (goto-char (c-next-single-property-change
			      (point) 'c-in-sws nil (point-max)))
		  (unless (get-text-property (point) 'c-is-sws)
		    ;; If the `c-in-sws' region extended past the last
		    ;; `c-is-sws' char we have to go back a bit.
		    (or (get-text-property (1- (point)) 'c-is-sws)
			(goto-char (previous-single-property-change
				    (point) 'c-is-sws)))
		    (backward-char))

		  (c-debug-sws-msg
		   "c-forward-sws cached move %s -> %s (max %s)"
		   rung-pos (point) (point-max))

		  (setq rung-pos (point))
		  (and (> (skip-chars-forward " \t\n\r\f\v") 0)
		       (not (eobp))))

	      ;; We'll loop here if there is simple ws after the last rung.
	      ;; That means that there's been some change in it and it's
	      ;; possible that we've stepped into another ladder, so extend
	      ;; the previous one to join with it if there is one, and try to
	      ;; use the cache again.
	      (c-debug-sws-msg
	       "c-forward-sws extending rung with [%s..%s] (max %s)"
	       (1+ rung-pos) (1+ (point)) (point-max))
	      (unless (get-text-property (point) 'c-is-sws)
		;; Remove any `c-in-sws' property from the last char of
		;; the rung before we mark it with `c-is-sws', so that we
		;; won't connect with the remains of a broken "ladder".
		(c-remove-in-sws (point) (1+ (point))))
	      (c-put-is-sws (1+ rung-pos)
			    (1+ (point)))
	      (c-put-in-sws rung-pos
			    (setq rung-pos (point)
				  last-put-in-sws-pos rung-pos)))

	    ;; Now move over any comments (x)or a CPP construct.
	    (setq simple-ws-end (point))
	    (setq safe-start t)
	    ;; Take elaborate precautions to detect an open block comment at
	    ;; the end of a macro.  If we find one, we set `safe-start' to nil
	    ;; and break off any further scanning of comments.
	    ;;
	    ;; (2019-05-02): `c-end-of-macro' now moves completely over block
	    ;; comments, even multiline ones lacking \s at their EOLs.  So a
	    ;; lot of the following is probably redundant now.
	    (let ((com-begin (point)) com-end in-macro)
	      (when (and (c-forward-single-comment)
			 (setq com-end (point))
			 (save-excursion
			   (goto-char com-begin)
			   (c-beginning-of-macro)))
		(setq in-macro t)
		(goto-char com-begin)
		(if (progn (c-end-of-macro com-end)
			   (< (point) com-end))
		    (setq safe-start nil)))
	      (if in-macro
		  (while (and safe-start
			      com-end (> com-end com-begin)
			      (setq com-begin (point))
			      (when (and (c-forward-single-comment)
					 (setq com-end (point)))
				(goto-char com-begin)
				(if (progn (c-end-of-macro com-end)
					   (< (point) com-end))
				    (setq safe-start nil))
				safe-start)))
		(c-forward-comments)))

	    (cond
	     ((/= (point) simple-ws-end)
	      ;; Skipped over comments.  Don't cache at eob in case the buffer
	      ;; is narrowed.
	      (not (eobp)))

	     ((save-excursion
		(and c-opt-cpp-prefix
		     (looking-at c-opt-cpp-start)
		     (setq macro-start (point))
		     (progn (skip-chars-backward " \t")
			    (bolp))
		     (or (bobp)
			 (progn (backward-char)
				(not (eq (char-before) ?\\))))))
	      ;; Skip a preprocessor directive.
	      (end-of-line)
	      (while (and (eq (char-before) ?\\)
			  (= (forward-line 1) 0))
		(end-of-line))
	      (setq macro-end (point))
	      ;; Check for an open block comment at the end of the macro.
	      (let ((s (parse-partial-sexp macro-start macro-end)))
		(if (and (elt s 4)		    ; in a comment
			 (null (elt s 7)))	    ; a block comment
		    (setq safe-start nil)))
	      (forward-line 1)
	      ;; Don't cache at eob in case the buffer is narrowed.
	      (not (eobp)))

	     ((and c-opt-cpp-prefix
		   (looking-at c-noise-macro-name-re))
	      ;; Skip over a noise macro without parens.
	      (goto-char (match-end 1))
	      (not (eobp)))

	     ((setq next-rung-pos (c-looking-at-c++-attribute))
	      (goto-char next-rung-pos)
	      (not (eobp)))

	     ((looking-at c-doc-line-join-re)
	      ;; Skip over a line join in (e.g.) Pike autodoc.
	      (goto-char (match-end 0))
	      (setq safe-start nil) ; Never cache this; the doc style could be
					; changed at any time.
	      (not (eobp)))))

	;; We've searched over a piece of non-white syntactic ws.  See if this
	;; can be cached.
	(setq next-rung-pos (point))
	(skip-chars-forward " \t\n\r\f\v")
	(setq rung-end-pos (min (1+ (point)) (point-max)))

	(if (or
	     ;; Cache if we haven't skipped comments only, and if we started
	     ;; either from a marked rung or from a completely uncached
	     ;; position.
	     (and safe-start
		  (or rung-is-marked
		      (not (get-text-property simple-ws-end 'c-in-sws))))

	     ;; See if there's a marked rung in the encountered simple ws.  If
	     ;; so then we can cache, unless `safe-start' is nil.  Even then
	     ;; we need to do this to check if the cache can be used for the
	     ;; next step.
	     (and (setq next-rung-is-marked
			(text-property-any next-rung-pos rung-end-pos
					   'c-is-sws t))
		  safe-start))

	    (progn
	      (c-debug-sws-msg
	       "c-forward-sws caching [%s..%s] - [%s..%s] (max %s)"
	       rung-pos (1+ simple-ws-end) next-rung-pos rung-end-pos
	       (point-max))

	      ;; Remove the properties for any nested ws that might be cached.
	      ;; Only necessary for `c-is-sws' since `c-in-sws' will be set
	      ;; anyway.
	      (c-remove-is-sws (1+ simple-ws-end) next-rung-pos)
	      (unless (and rung-is-marked (= rung-pos simple-ws-end))
		(c-put-is-sws rung-pos
			      (1+ simple-ws-end))
		(setq rung-is-marked t))
	      (c-put-in-sws rung-pos
			    (setq rung-pos (point)
				  last-put-in-sws-pos rung-pos))
	      (unless (get-text-property (1- rung-end-pos) 'c-is-sws)
		;; Remove any `c-in-sws' property from the last char of
		;; the rung before we mark it with `c-is-sws', so that we
		;; won't connect with the remains of a broken "ladder".
		(c-remove-in-sws (1- rung-end-pos) rung-end-pos))
	      (c-put-is-sws next-rung-pos
			    rung-end-pos))

	  (c-debug-sws-msg
	   "c-forward-sws not caching [%s..%s] - [%s..%s] (max %s)"
	   rung-pos (1+ simple-ws-end) next-rung-pos rung-end-pos
	   (point-max))

	  ;; Set `rung-pos' for the next rung.  It's the same thing here as
	  ;; initially, except that the rung position is set as early as
	  ;; possible since we can't be in the ending ws of a line comment or
	  ;; cpp directive now.
	  (if (setq rung-is-marked next-rung-is-marked)
	      (setq rung-pos (1- (c-next-single-property-change
				  rung-is-marked 'c-is-sws nil rung-end-pos)))
	    (setq rung-pos next-rung-pos))))

      ;; Make sure that the newly marked `c-in-sws' region doesn't connect to
      ;; another one after the point (which might occur when editing inside a
      ;; comment or macro).
      (when (eq last-put-in-sws-pos (point))
	(cond ((< last-put-in-sws-pos (point-max))
	       (c-debug-sws-msg
		"c-forward-sws clearing at %s for cache separation"
		last-put-in-sws-pos)
	       (c-remove-in-sws last-put-in-sws-pos
				(1+ last-put-in-sws-pos)))
	      (t
	       ;; If at eob we have to clear the last character before the end
	       ;; instead since the buffer might be narrowed and there might
	       ;; be a `c-in-sws' after (point-max).  In this case it's
	       ;; necessary to clear both properties.
	       (c-debug-sws-msg
		"c-forward-sws clearing thoroughly at %s for cache separation"
		(1- last-put-in-sws-pos))
	       (c-remove-is-and-in-sws (1- last-put-in-sws-pos)
				       last-put-in-sws-pos))))))))