;;; cc-mode.el --- major mode for editing C and similar languages
-;; Copyright (C) 1985, 1987, 1992-2015 Free Software Foundation, Inc.
+;; Copyright (C) 1985, 1987, 1992-2016 Free Software Foundation, Inc.
;; Authors: 2003- Alan Mackenzie
;; 1998- Martin Stjernholm
(cc-bytecomp-defvar adaptive-fill-first-line-regexp) ; Emacs
(cc-bytecomp-defun run-mode-hooks) ; Emacs 21.1
-;; We set these variables during mode init, yet we don't require
+;; We set this variable during mode init, yet we don't require
;; font-lock.
(cc-bytecomp-defvar font-lock-defaults)
-(cc-bytecomp-defvar font-lock-syntactic-keywords)
;; Menu support for both XEmacs and Emacs. If you don't have easymenu
;; with your version of Emacs, you are incompatible!
and the line breaking/filling code. Intended to be used by other
packages that embed CC Mode.
-MODE is the CC Mode flavor to set up, e.g. 'c-mode or 'java-mode.
+MODE is the CC Mode flavor to set up, e.g. `c-mode' or `java-mode'.
DEFAULT-STYLE tells which indentation style to install. It has the
same format as `c-default-style'.
(set (make-local-variable 'comment-line-break-function)
'c-indent-new-comment-line)
+ ;; Prevent time-wasting activity on C-y.
+ (when (boundp 'yank-handled-properties)
+ (make-local-variable 'yank-handled-properties)
+ (let ((yank-cat-handler (assq 'category yank-handled-properties)))
+ (when yank-cat-handler
+ (setq yank-handled-properties (remq yank-cat-handler
+ yank-handled-properties)))))
+
;; For the benefit of adaptive file, which otherwise mis-fills.
(setq fill-paragraph-handle-comment nil)
(font-lock-mode 1)))
;; Buffer local variables defining the region to be fontified by a font lock
-;; after-change function. They are set in c-after-change to
-;; after-change-functions' BEG and END, and may be modified by functions in
+;; after-change function. They are initialized in c-before-change to
+;; before-change-functions' BEG and END. `c-new-END' is amended in
+;; c-after-change with after-change-functions' BEG, END, and OLD-LEN. These
+;; variables may be modified by any before/after-change function, in
+;; particular by functions in `c-get-state-before-change-functions' and
;; `c-before-font-lock-functions'.
(defvar c-new-BEG 0)
(make-variable-buffer-local 'c-new-BEG)
customary in CC Mode modes but which aren't strictly necessary for CC
Mode to operate correctly.
-MODE is the symbol for the mode to initialize, like 'c-mode. See
+MODE is the symbol for the mode to initialize, like `c-mode'. See
`c-basic-common-init' for details. It's only optional to be
compatible with old code; callers should always specify it."
(setq c-new-BEG (point-min))
(setq c-new-END (point-max))
(save-excursion
- (mapc (lambda (fn)
- (funcall fn (point-min) (point-max)))
- c-get-state-before-change-functions)
- (mapc (lambda (fn)
- (funcall fn (point-min) (point-max)
- (- (point-max) (point-min))))
- c-before-font-lock-functions)))
+ (let (before-change-functions after-change-functions)
+ (mapc (lambda (fn)
+ (funcall fn (point-min) (point-max)))
+ c-get-state-before-change-functions)
+ (mapc (lambda (fn)
+ (if (not (eq fn 'c-restore-<>-properties))
+ (funcall fn (point-min) (point-max)
+ (- (point-max) (point-min)))))
+ c-before-font-lock-functions))))
(set (make-local-variable 'outline-regexp) "[^#\n\^M]")
(set (make-local-variable 'outline-level) 'c-outline-level)
(defvar c-old-EOM 0)
(make-variable-buffer-local 'c-old-EOM)
+(defun c-called-from-text-property-change-p ()
+ ;; Is the primitive which invoked `before-change-functions' or
+ ;; `after-change-functions' one which merely changes text properties? This
+ ;; function must be called directly from a member of one of the above hooks.
+ ;;
+ ;; In the following call, frame 0 is `backtrace-frame', frame 1 is
+ ;; `c-called-from-text-property-change-p', frame 2 is
+ ;; `c-before/after-change', frame 3 is the primitive invoking the change
+ ;; hook.
+ (memq (cadr (backtrace-frame 3))
+ '(put-text-property remove-list-of-text-properties)))
+
(defun c-extend-region-for-CPP (beg end)
;; Set c-old-BOM or c-old-EOM respectively to BEG, END, each extended to the
;; beginning/end of any preprocessor construct they may be in.
(unless
(or (save-excursion
(goto-char (match-beginning 0))
- (c-beginning-of-macro))
+ (let ((here (point)))
+ (and (save-match-data (c-beginning-of-macro))
+ (< (point) here))))
(progn
(setq pps-state
(parse-partial-sexp pps-position (point) nil nil pps-state)
;; 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-just-done-before-change ; Guard against a spurious second
- ; invocation of before-change-functions.
+ (unless (or (c-called-from-text-property-change-p)
+ c-just-done-before-change) ; guard against a spurious second
+ ; invocation of before-change-functions.
(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)
(save-restriction
(save-match-data
(buffer-substring-no-properties beg end)))))))
(if c-get-state-before-change-functions
- (let (open-paren-in-column-0-is-defun-start)
- (mapc (lambda (fn)
- (funcall fn beg end))
- c-get-state-before-change-functions)))
+ (mapc (lambda (fn)
+ (funcall fn beg end))
+ c-get-state-before-change-functions))
)))
;; The following must be done here rather than in `c-after-change' because
;; newly inserted parens would foul up the invalidation algorithm.
;; This calls the language variable c-before-font-lock-functions, if non nil.
;; This typically sets `syntax-table' properties.
- (setq c-just-done-before-change nil)
- (c-save-buffer-state (case-fold-search open-paren-in-column-0-is-defun-start)
- ;; When `combine-after-change-calls' is used we might get calls
- ;; with regions outside the current narrowing. This has been
- ;; observed in Emacs 20.7.
- (save-restriction
- (save-match-data ; c-recognize-<>-arglists changes match-data
- (widen)
-
- (when (> end (point-max))
- ;; Some emacsen might return positions past the end. This has been
- ;; observed in Emacs 20.7 when rereading a buffer changed on disk
- ;; (haven't been able to minimize it, but Emacs 21.3 appears to
- ;; work).
- (setq end (point-max))
- (when (> beg end)
- (setq beg end)))
-
- ;; C-y is capable of spuriously converting category properties
- ;; c-</>-as-paren-syntax and c-cpp-delimiter into hard syntax-table
- ;; properties. Remove these when it happens.
- (when (eval-when-compile (memq 'category-properties c-emacs-features))
- (c-clear-char-property-with-value beg end 'syntax-table
- c-<-as-paren-syntax)
- (c-clear-char-property-with-value beg end 'syntax-table
- c->-as-paren-syntax)
- (c-clear-char-property-with-value beg end 'syntax-table nil))
-
- (c-trim-found-types beg end old-len) ; maybe we don't need all of these.
- (c-invalidate-sws-region-after beg end)
- ;; (c-invalidate-state-cache beg) ; moved to `c-before-change'.
- (c-invalidate-find-decl-cache beg)
-
- (when c-recognize-<>-arglists
- (c-after-change-check-<>-operators beg end))
-
- ;; (c-new-BEG c-new-END) will be the region to fontify. It may become
- ;; larger than (beg end).
- (setq c-new-BEG beg
- c-new-END end)
- (setq c-in-after-change-fontification t)
- (save-excursion
- (mapc (lambda (fn)
- (funcall fn beg end old-len))
- c-before-font-lock-functions))))))
-
-(defun c-set-fl-decl-start (pos)
+ ;; (c-new-BEG c-new-END) will be the region to fontify. It may become
+ ;; larger than (beg end).
+ ;; (setq c-new-BEG beg c-new-END end)
+ (setq c-new-END (- (+ c-new-END (- end beg)) old-len))
+
+ (unless (c-called-from-text-property-change-p)
+ (setq c-just-done-before-change nil)
+ (c-save-buffer-state (case-fold-search)
+ ;; When `combine-after-change-calls' is used we might get calls
+ ;; with regions outside the current narrowing. This has been
+ ;; observed in Emacs 20.7.
+ (save-restriction
+ (save-match-data ; c-recognize-<>-arglists changes match-data
+ (widen)
+
+ (when (> end (point-max))
+ ;; Some emacsen might return positions past the end. This has been
+ ;; observed in Emacs 20.7 when rereading a buffer changed on disk
+ ;; (haven't been able to minimize it, but Emacs 21.3 appears to
+ ;; work).
+ (setq end (point-max))
+ (when (> beg end)
+ (setq beg end)))
+
+ ;; C-y is capable of spuriously converting category properties
+ ;; c-</>-as-paren-syntax and c-cpp-delimiter into hard syntax-table
+ ;; properties. Remove these when it happens.
+ (when (eval-when-compile (memq 'category-properties c-emacs-features))
+ (c-save-buffer-state ()
+ (c-clear-char-property-with-value beg end 'syntax-table
+ c-<-as-paren-syntax)
+ (c-clear-char-property-with-value beg end 'syntax-table
+ c->-as-paren-syntax)
+ (c-clear-char-property-with-value beg end 'syntax-table nil)))
+
+ (c-trim-found-types beg end old-len) ; maybe we don't need all of these.
+ (c-invalidate-sws-region-after beg end)
+ ;; (c-invalidate-state-cache beg) ; moved to `c-before-change'.
+ (c-invalidate-find-decl-cache beg)
+
+ (when c-recognize-<>-arglists
+ (c-after-change-check-<>-operators beg end))
+
+ (setq c-in-after-change-fontification t)
+ (save-excursion
+ (mapc (lambda (fn)
+ (funcall fn beg end old-len))
+ c-before-font-lock-functions)))))))
+
+(defun c-fl-decl-start (pos)
;; If the beginning of the line containing POS is in the middle of a "local"
;; declaration (i.e. one which does not start outside of braces enclosing
;; POS, such as a struct), return the beginning of that declaration.
- ;; Otherwise return POS. Note that declarations, in this sense, can be
+ ;; Otherwise return nil. Note that declarations, in this sense, can be
;; nested.
;;
;; This function is called indirectly from font locking stuff - either from
;; Go to a less nested declaration each time round this loop.
(and
(eq (car (c-beginning-of-decl-1 bod-lim)) 'same)
+ (> (point) bod-lim)
(progn (setq bo-decl (point))
;; Are we looking at a keyword such as "template" or
;; "typedef" which can decorate a type, or the type itself?
(1- (point)) 'syntax-table)
c-<-as-paren-syntax)))))
(not (bobp)))
- (backward-char))
- new-pos)) ; back over (, [, <.
-
-(defun c-change-set-fl-decl-start (_beg _end _old-len)
- ;; Set c-new-BEG to the beginning of a "local" declaration if it('s BOL) is
- ;; inside one. This is called from an after-change-function, but the
- ;; parameters BEG END and OLD-LEN are ignored. See `c-set-fl-decl-start'
- ;; for the detailed functionality.
- (if font-lock-mode
- (setq c-new-BEG (c-set-fl-decl-start c-new-BEG))))
-
-(defun c-context-set-fl-decl-start (beg end)
- ;; Return a cons (NEW-BEG . END), where NEW-BEG is the beginning of a
- ;; "local" declaration (BOL at) NEW is inside or BEG. See
- ;; `c-set-fl-decl-start' for the detailed functionality.
- (cons (c-set-fl-decl-start beg) end))
+ (backward-char)) ; back over (, [, <.
+ (and (/= new-pos pos) new-pos)))
+
+(defun c-change-expand-fl-region (beg end old-len)
+ ;; Expand the region (c-new-BEG c-new-END) to an after-change font-lock
+ ;; region. This will usually be the smallest sequence of whole lines
+ ;; containing `c-new-BEG' and `c-new-END', but if `c-new-BEG' is in a
+ ;; "local" declaration (see `c-fl-decl-start') the beginning of this is used
+ ;; as the lower bound.
+ ;;
+ ;; This is called from an after-change-function, but the parameters BEG END
+ ;; and OLD-LEN are not used.
+ (if font-lock-mode
+ (setq c-new-BEG
+ (or (c-fl-decl-start c-new-BEG) (c-point 'bol c-new-BEG))
+ c-new-END (c-point 'bonl c-new-END))))
+
+(defun c-context-expand-fl-region (beg end)
+ ;; Return a cons (NEW-BEG . NEW-END), where NEW-BEG is the beginning of a
+ ;; "local" declaration containing BEG (see `c-fl-decl-start') or BOL BEG is
+ ;; in. NEW-END is beginning of the line after the one END is in.
+ (cons (or (c-fl-decl-start beg) (c-point 'bol beg))
+ (c-point 'bonl end)))
+
+(defun c-before-context-fl-expand-region (beg end)
+ ;; Expand the region (BEG END) as specified by
+ ;; `c-before-context-fontification-functions'. Return a cons of the bounds
+ ;; of the new region.
+ (save-restriction
+ (widen)
+ (save-excursion
+ (let ((new-beg beg) (new-end end)
+ (new-region (cons beg end)))
+ (mapc (lambda (fn)
+ (setq new-region (funcall fn new-beg new-end))
+ (setq new-beg (car new-region) new-end (cdr new-region)))
+ c-before-context-fontification-functions)
+ new-region))))
(defun c-font-lock-fontify-region (beg end &optional verbose)
;; Effectively advice around `font-lock-fontify-region' which extends the
;; region (BEG END), for example, to avoid context fontification chopping
- ;; off the start of the context. Do not do anything if it's already been
- ;; done (i.e. from an after-change fontification. An example (C++) where
- ;; this used to happen is this:
+ ;; off the start of the context. Do not extend the region if it's already
+ ;; been done (i.e. from an after-change fontification. An example (C++)
+ ;; where the chopping off used to happen is this:
;;
;; template <typename T>
;;
;;
;; void myfunc(T* p) {}
- ;;
+ ;;
;; Type a space in the first blank line, and the fontification of the next
;; line was fouled up by context fontification.
- (let ((new-beg beg) (new-end end) new-region case-fold-search
- open-paren-in-column-0-is-defun-start)
- (if c-in-after-change-fontification
- (setq c-in-after-change-fontification nil)
- (save-restriction
- (widen)
- (save-excursion
- (mapc (lambda (fn)
- (setq new-region (funcall fn new-beg new-end))
- (setq new-beg (car new-region) new-end (cdr new-region)))
- c-before-context-fontification-functions))))
+ (let (new-beg new-end new-region case-fold-search)
+ (if (and c-in-after-change-fontification
+ (< beg c-new-END) (> end c-new-BEG))
+ ;; Region and the latest after-change fontification region overlap.
+ ;; Determine the upper and lower bounds of our adjusted region
+ ;; separately.
+ (progn
+ (if (<= beg c-new-BEG)
+ (setq c-in-after-change-fontification nil))
+ (setq new-beg
+ (if (and (>= beg (c-point 'bol c-new-BEG))
+ (<= beg c-new-BEG))
+ ;; Either jit-lock has accepted `c-new-BEG', or has
+ ;; (probably) extended the change region spuriously to
+ ;; BOL, which position likely has a syntactically
+ ;; different position. To ensure correct fontification,
+ ;; we start at `c-new-BEG', assuming any characters to the
+ ;; left of `c-new-BEG' on the line do not require
+ ;; fontification.
+ c-new-BEG
+ (setq new-region (c-before-context-fl-expand-region beg end)
+ new-end (cdr new-region))
+ (car new-region)))
+ (setq new-end
+ (if (and (>= end (c-point 'bol c-new-END))
+ (<= end c-new-END))
+ c-new-END
+ (or new-end
+ (cdr (c-before-context-fl-expand-region beg end))))))
+ ;; Context (etc.) fontification.
+ (setq new-region (c-before-context-fl-expand-region beg end)
+ new-beg (car new-region) new-end (cdr new-region)))
(funcall (default-value 'font-lock-fontify-region-function)
new-beg new-end verbose)))
(defun c-after-font-lock-init ()
;; Put on `font-lock-mode-hook'. This function ensures our after-change
;; function will get executed before the font-lock one.
- (remove-hook 'after-change-functions 'c-after-change t)
- (add-hook 'after-change-functions 'c-after-change nil t))
+ (when (memq #'c-after-change after-change-functions)
+ (remove-hook 'after-change-functions #'c-after-change t)
+ (add-hook 'after-change-functions #'c-after-change nil t)))
(defun c-font-lock-init ()
"Set up the font-lock variables for using the font-lock support in CC Mode.
. c-mark-function)))
;; Prevent `font-lock-default-fontify-region' extending the region it will
- ;; fontify to whole lines by removing `font-lock-extend-region-whole-lines'
- ;; (and, coincidentally, `font-lock-extend-region-multiline' (which we do
- ;; not need)) from `font-lock-extend-region-functions'. (Emacs only). This
- ;; fixes Emacs bug #19669.
+ ;; fontify to whole lines by removing `font-lock-extend-region-wholelines'
+ ;; from `font-lock-extend-region-functions'. (Emacs only). This fixes
+ ;; Emacs bug #19669.
(when (boundp 'font-lock-extend-region-functions)
- (setq font-lock-extend-region-functions nil))
+ (setq font-lock-extend-region-functions
+ (delq 'font-lock-extend-region-wholelines
+ font-lock-extend-region-functions)))
(make-local-variable 'font-lock-fontify-region-function)
(setq font-lock-fontify-region-function 'c-font-lock-fontify-region)
(add-hook 'font-lock-mode-hook 'c-after-font-lock-init nil t))
;; Emacs 22 and later.
-(defun c-extend-after-change-region (_beg _end _old-len)
+(defun c-extend-after-change-region (beg end _old-len)
"Extend the region to be fontified, if necessary."
- ;; Note: the parameters are ignored here. This somewhat indirect
+ ;; Note: the parameter OLD-LEN is ignored here. This somewhat indirect
;; implementation exists because it is minimally different from the
;; stand-alone CC Mode which, lacking
;; font-lock-extend-after-change-region-function, is forced to use advice
;; Of the seven CC Mode languages, currently (2009-05) only C, C++, Objc
;; (the languages with #define) and AWK Mode make non-null use of this
;; function.
+ (when (eq font-lock-support-mode 'jit-lock-mode)
+ (save-restriction
+ (widen)
+ (c-save-buffer-state () ; Protect the undo-list from put-text-property.
+ (if (< c-new-BEG beg)
+ (put-text-property c-new-BEG beg 'fontified nil))
+ (if (> c-new-END end)
+ (put-text-property end c-new-END 'fontified nil)))))
(cons c-new-BEG c-new-END))
;; Emacs < 22 and XEmacs
;;;###autoload
(define-derived-mode c-mode prog-mode "C"
- "Major mode for editing K&R and ANSI C code.
+ "Major mode for editing C code.
+
To submit a problem report, enter `\\[c-submit-bug-report]' from a
c-mode buffer. This automatically sets up a mail buffer with version
information already added. You just need to add a description of the
;; bug reporting
(defconst c-mode-help-address
- "bug-cc-mode@gnu.org"
+ "submit@debbugs.gnu.org"
"Address(es) for CC Mode bug reports.")
(defun c-version ()
(defvar reporter-prompt-for-summary-p)
(defvar reporter-dont-compact-list)
+;; This could be "emacs,cc-mode" in the version included in Emacs.
+(defconst c-mode-bug-package "cc-mode"
+ "The package to use in the bug submission.")
+
+;; reporter-submit-bug-report requires sendmail.
+(declare-function mail-position-on-field "sendmail" (field &optional soft))
+
(defun c-submit-bug-report ()
"Submit via mail a bug report on CC Mode."
(interactive)
vars)
(lambda ()
(run-hooks 'c-prepare-bug-report-hook)
+ (save-excursion
+ (or (mail-position-on-field "X-Debbugs-Package")
+ (insert c-mode-bug-package)))
(insert (format "Buffer Style: %s\nc-emacs-features: %s\n"
style c-features)))))))
\f
(cc-provide 'cc-mode)
-;;; Local Variables:
-;;; indent-tabs-mode: t
-;;; tab-width: 8
-;;; End:
+;; Local Variables:
+;; indent-tabs-mode: t
+;; tab-width: 8
+;; End:
;;; cc-mode.el ends here