Function: c-before-change

c-before-change is a byte-compiled function defined in cc-mode.el.gz.

Signature

(c-before-change BEG END)

Source Code

;; Defined in /usr/src/emacs/lisp/progmodes/cc-mode.el.gz
(defun c-before-change (beg end)
  ;; Function to be put on `before-change-functions'.  Primarily, this calls
  ;; the language dependent `c-get-state-before-change-functions'.  It is
  ;; otherwise used only to remove stale entries from the `c-found-types'
  ;; cache, and to record entries which a `c-after-change' function might
  ;; confirm as stale.
  ;;
  ;; Note that this function must be FAST rather than accurate.  Note
  ;; also that it only has any effect when font locking is enabled.
  ;; We exploit this by checking for font-lock-*-face instead of doing
  ;; rigorous syntactic analysis.

  ;; If either change boundary is wholly inside an identifier, delete
  ;; it/them from the cache.  Don't worry about being inside a string
  ;; or a comment - "wrongly" removing a symbol from `c-found-types'
  ;; isn't critical.
  (unless (c-called-from-text-property-change-p)
    (c-with-string-fences
     (save-restriction
       (widen)
       ;; Clear the list of found types if we make a change at the start of the
       ;; buffer, to make it easier to get rid of misspelled types and
       ;; variables that have gotten recognized as types in malformed code.
       (when (eq beg (point-min))
	 (c-clear-found-types))
       (if c-just-done-before-change
	   ;; We have two consecutive calls to `before-change-functions'
	   ;; without an intervening `after-change-functions'.  An example of
	   ;; this is bug #38691.  To protect CC Mode, assume that the entire
	   ;; buffer has changed.
	   (setq beg (point-min)
		 end (point-max)
		 c-just-done-before-change 'whole-buffer)
	 (setq c-just-done-before-change t))
       ;; (c-new-BEG c-new-END) will be the region to fontify.
       (setq c-new-BEG beg  c-new-END end)
       (setq c-maybe-stale-found-type nil)
       (setq c-open-string-opener nil)
       ;; A workaround for syntax-ppss's failure to notice syntax-table text
       ;; property changes.
       (when (fboundp 'syntax-ppss)
	 (setq c-syntax-table-hwm most-positive-fixnum))
       (save-match-data
	 (save-excursion
	   ;; Are we inserting/deleting stuff in the middle of an
	   ;; identifier?
	   (c-unfind-enclosing-token beg)
	   (c-unfind-enclosing-token end)
	   ;; Are we coalescing two tokens together, e.g. "fo o"
	   ;; -> "foo"?
	   (when (< beg end)
	     (c-unfind-coalesced-tokens beg end))
	   (c-invalidate-sws-region-before beg end)
	   ;; Are we (potentially) disrupting the syntactic
	   ;; context which makes a type a type?  E.g. by
	   ;; inserting stuff after "foo" in "foo bar;", or
	   ;; before "foo" in "typedef foo *bar;"?
	   ;;
	   ;; We search for appropriate c-type properties "near"
	   ;; the change.  First, find an appropriate boundary
	   ;; for this property search.
	   (let (lim lim-2
		     type type-pos
		     marked-id term-pos
		     (end1
		      (or (and (eq (get-text-property end 'face)
				   'font-lock-comment-face)
			       (c-previous-single-property-change end 'face))
			  end)))
	     (when (>= end1 beg) ; Don't hassle about changes entirely in
					; comments.
	       ;; Find a limit for the search for a `c-type' property
	       ;; Point is currently undefined.  A `goto-char' somewhere is needed.  (2020-12-06).
	       (setq lim-2 (c-determine-limit 1000 (point) ; that is wrong.  FIXME!!!  (2020-12-06)
					      ))
	       (while
		   (and (/= (skip-chars-backward "^;{}" lim-2) 0)
			(> (point) (point-min))
			(memq (c-get-char-property (1- (point)) 'face)
			      '(font-lock-comment-face font-lock-string-face))))
	       (setq lim (max (point-min) (1- (point))))

	       ;; Look for the latest `c-type' property before end1
	       (when (and (> end1 (point-min))
			  (setq type-pos
				(if (get-text-property (1- end1) 'c-type)
				    end1
				  (c-previous-single-property-change end1 'c-type
								     nil lim))))
		 (setq type (get-text-property (max (1- type-pos) lim) 'c-type))

		 (when (memq type '(c-decl-id-start c-decl-type-start))
		   ;; Get the identifier, if any, that the property is on.
		   (goto-char (1- type-pos))
		   (setq marked-id
			 (when (looking-at "\\(\\sw\\|\\s_\\)")
			   (c-beginning-of-current-token)
			   (buffer-substring-no-properties (point) type-pos)))

		   (goto-char end1)
		   (setq lim-2 (c-determine-+ve-limit 1000))
		   (skip-chars-forward "^;{}" lim-2) ; FIXME!!!  loop for
					; comment, maybe
		   (setq lim (point))
		   (setq term-pos
			 (or (c-next-single-property-change end 'c-type nil lim) lim))
		   (setq c-maybe-stale-found-type
			 (list type marked-id
			       type-pos term-pos
			       (buffer-substring-no-properties type-pos
							       term-pos)
			       (buffer-substring-no-properties beg end)))))))

	   ;; If we're about to delete "typedef"s, clear the identifiers from
	   ;; `c-found-types'.
	   (c-before-change-de-typedef beg end)

	   (if c-get-state-before-change-functions
	       (mapc (lambda (fn)
		       (funcall fn beg end))
		     c-get-state-before-change-functions))

	   (c-laomib-invalidate-cache beg end))))
     (c-truncate-lit-pos/state-cache beg)
     ;; The following must be done here rather than in `c-after-change'
     ;; because newly inserted parens would foul up the invalidation
     ;; algorithm.
     (c-invalidate-state-cache)
     ;; The following must happen after the previous, which likely alters
     ;; the macro cache.
     (when c-opt-cpp-symbol
       (c-invalidate-macro-cache beg end))
     (setq c-no-bracelist-cache
	   (c-whack-state-after beg c-no-bracelist-cache)))))