;;; cc-mode.el --- major mode for editing C and similar languages
;; Copyright (C) 1985, 1987, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-;; 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
-;; Free Software Foundation, Inc.
+;; 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
+;; 2010 Free Software Foundation, Inc.
;; Authors: 2003- Alan Mackenzie
;; 1998- Martin Stjernholm
;; 1985 Richard M. Stallman
;; Maintainer: bug-cc-mode@gnu.org
;; Created: a long, long, time ago. adapted from the original c-mode.el
-;; Keywords: c languages oop
+;; Keywords: c languages
;; This file is part of GNU Emacs.
(cc-bytecomp-defvar adaptive-fill-first-line-regexp) ; Emacs
(cc-bytecomp-defun set-keymap-parents) ; XEmacs
(cc-bytecomp-defun run-mode-hooks) ; Emacs 21.1
-(cc-bytecomp-obsolete-fun make-local-hook) ; Marked obsolete in Emacs 21.1.
;; We set these variables during mode init, yet we don't require
;; font-lock.
;; Autoload directive for emacsen that doesn't have an older CC Mode
;; version in the dist.
-(autoload 'c-subword-mode "cc-subword"
+(autoload 'subword-mode "subword"
"Mode enabling subword movement and editing keys." t)
;; Load cc-fonts first after font-lock is loaded, since it isn't
;; conflicts with OOBR
;;(define-key c-mode-base-map "\C-c\C-v" 'c-version)
;; (define-key c-mode-base-map "\C-c\C-y" 'c-toggle-hungry-state) Commented out by ACM, 2005-11-22.
- (define-key c-mode-base-map "\C-c\C-w" 'c-subword-mode)
+ (define-key c-mode-base-map "\C-c\C-w" 'subword-mode)
)
;; We don't require the outline package, but we configure it a bit anyway.
;; temporary changes in some font lock support modes, causing extra
;; unnecessary work and font lock glitches due to interactions between
;; various text properties.
-;;
+;;
;; (2007-02-12): The macro `combine-after-change-calls' ISN'T used any
;; more.
end (point))))))))
;; c-maybe-stale-found-type records a place near the region being
-;; changed where an element of `found-types' might become stale. It
+;; changed where an element of `found-types' might become stale. It
;; is set in c-before-change and is either nil, or has the form:
;;
;; (c-decl-id-start "foo" 97 107 " (* ooka) " "o"), where
-;;
+;;
;; o - `c-decl-id-start' is the c-type text property value at buffer
;; pos 96.
-;;
+;;
;; o - 97 107 is the region potentially containing the stale type -
;; this is delimited by a non-nil c-type text property at 96 and
;; either another one or a ";", "{", or "}" at 107.
-;;
+;;
;; o - " (* ooka) " is the (before change) buffer portion containing
;; the suspect type (here "ooka").
;;
(make-local-variable 'fill-paragraph-function)
(setq fill-paragraph-function 'c-fill-paragraph)
+ ;; Initialise the cache of brace pairs, and opening braces/brackets/parens.
+ (c-state-cache-init)
+
(when (or c-recognize-<>-arglists
(c-major-mode-is 'awk-mode)
- (c-major-mode-is '(c-mode c++-mode objc-mode)))
+ (c-major-mode-is '(java-mode c-mode c++-mode objc-mode)))
;; We'll use the syntax-table text property to change the syntax
;; of some chars for this language, so do the necessary setup for
;; that.
(make-local-variable 'lookup-syntax-properties)
(setq lookup-syntax-properties t)))
- ;; Use this in Emacs 21 to avoid meddling with the rear-nonsticky
+ ;; Use this in Emacs 21+ to avoid meddling with the rear-nonsticky
;; property on each character.
(when (boundp 'text-property-default-nonsticky)
(make-local-variable 'text-property-default-nonsticky)
- (let ((elem (assq 'syntax-table text-property-default-nonsticky)))
- (if elem
- (setcdr elem t)
- (setq text-property-default-nonsticky
- (cons '(syntax-table . t)
- text-property-default-nonsticky))))
- (setq text-property-default-nonsticky
- (cons '(c-type . t)
- text-property-default-nonsticky)))
+ (mapc (lambda (tprop)
+ (unless (assq tprop text-property-default-nonsticky)
+ (setq text-property-default-nonsticky
+ (cons `(,tprop . t) text-property-default-nonsticky))))
+ '(syntax-table category c-type)))
;; In Emacs 21 and later it's possible to turn off the ad-hoc
;; heuristic that open parens in column 0 are defun starters. Since
;; Install the functions that ensure that various internal caches
;; don't become invalid due to buffer changes.
- (make-local-hook 'before-change-functions)
+ (when (featurep 'xemacs)
+ (make-local-hook 'before-change-functions)
+ (make-local-hook 'after-change-functions))
(add-hook 'before-change-functions 'c-before-change nil t)
- (make-local-hook 'after-change-functions)
(add-hook 'after-change-functions 'c-after-change nil t)
(set (make-local-variable 'font-lock-extend-after-change-region-function)
'c-extend-after-change-region)) ; Currently (2009-05) used by all
(font-lock-mode 0)
(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-function's BEG and END, and may be modified by a
+;; `c-before-font-lock-function'.
+(defvar c-new-BEG 0)
+(make-variable-buffer-local 'c-new-BEG)
+(defvar c-new-END 0)
+(make-variable-buffer-local 'c-new-END)
+
(defun c-common-init (&optional mode)
"Common initialization for all CC Mode modes.
In addition to the work done by `c-basic-common-init' and
;; Starting a mode is a sort of "change". So call the change functions...
(save-restriction
(widen)
+ (setq c-new-BEG (point-min))
+ (setq c-new-END (point-max))
(save-excursion
- (if c-get-state-before-change-function
- (funcall c-get-state-before-change-function (point-min) (point-max)))
+ (if c-get-state-before-change-functions
+ (mapc (lambda (fn)
+ (funcall fn (point-min) (point-max)))
+ c-get-state-before-change-functions))
(if c-before-font-lock-function
(funcall c-before-font-lock-function (point-min) (point-max)
(- (point-max) (point-min))))))
(and (cdr rfn)
(setq require-final-newline mode-require-final-newline)))))
+(defun c-count-cfss (lv-alist)
+ ;; LV-ALIST is an alist like `file-local-variables-alist'. Count how many
+ ;; elements with the key `c-file-style' there are in it.
+ (let ((elt-ptr lv-alist) elt (cownt 0))
+ (while elt-ptr
+ (setq elt (car elt-ptr)
+ elt-ptr (cdr elt-ptr))
+ (when (eq (car elt) 'c-file-style)
+ (setq cownt (1+ cownt))))
+ cownt))
+
(defun c-before-hack-hook ()
"Set the CC Mode style and \"offsets\" when in the buffer's local variables.
They are set only when, respectively, the pseudo variables
This function is called from the hook `before-hack-local-variables-hook'."
(when c-buffer-is-cc-mode
- (let ((stile (cdr (assq 'c-file-style file-local-variables-alist)))
+ (let ((mode-cons (assq 'mode file-local-variables-alist))
+ (stile (cdr (assq 'c-file-style file-local-variables-alist)))
(offsets (cdr (assq 'c-file-offsets file-local-variables-alist))))
+ (when mode-cons
+ (hack-one-local-variable (car mode-cons) (cdr mode-cons))
+ (setq file-local-variables-alist
+ (delq mode-cons file-local-variables-alist)))
(when stile
(or (stringp stile) (error "c-file-style is not a string"))
- (c-set-style stile))
+ (if (boundp 'dir-local-variables-alist)
+ ;; Determine whether `c-file-style' was set in the file's local
+ ;; variables or in a .dir-locals.el (a directory setting).
+ (let ((cfs-in-file-and-dir-count
+ (c-count-cfss file-local-variables-alist))
+ (cfs-in-dir-count (c-count-cfss dir-local-variables-alist)))
+ (c-set-style stile
+ (= cfs-in-file-and-dir-count cfs-in-dir-count)))
+ (c-set-style stile)))
(when offsets
(mapc
(lambda (langentry)
(defmacro c-run-mode-hooks (&rest hooks)
;; Emacs 21.1 has introduced a system with delayed mode hooks that
- ;; require the use of the new function `run-mode-hooks'.
+ ;; requires the use of the new function `run-mode-hooks'.
(if (cc-bytecomp-fboundp 'run-mode-hooks)
`(run-mode-hooks ,@hooks)
`(progn ,@(mapcar (lambda (hook) `(run-hooks ,hook)) hooks))))
\f
;;; Change hooks, linking with Font Lock.
-;; 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-function's BEG and END, and may be modified by a
-;; `c-before-font-lock-function'.
-(defvar c-new-BEG 0)
-(make-variable-buffer-local 'c-new-BEG)
-(defvar c-new-END 0)
-(make-variable-buffer-local 'c-new-END)
-
;; Buffer local variables recording Beginning/End-of-Macro position before a
;; change, when a macro straddles, respectively, the BEG or END (or both) of
;; the change region. Otherwise these have the values BEG/END.
;; has already been widened, and match-data saved. The return value is
;; meaningless.
;;
- ;; This function is the C/C++/ObjC value of
- ;; `c-get-state-before-change-function' and is called exclusively as a
+ ;; This function is in the C/C++/ObjC values of
+ ;; `c-get-state-before-change-functions' and is called exclusively as a
;; before change function.
(goto-char beg)
(c-beginning-of-macro)
(setq c-old-BOM (point))
(goto-char end)
- (if (c-beginning-of-macro)
- (c-end-of-macro))
+ (when (c-beginning-of-macro)
+ (c-end-of-macro)
+ (or (eobp) (forward-char))) ; Over the terminating NL which may be marked
+ ; with a c-cpp-delimiter category property
(setq c-old-EOM (point)))
(defun c-neutralize-CPP-line (beg end)
t)
(t nil)))))))
-(defun c-extend-and-neutralize-syntax-in-CPP (begg endd old-len)
+(defun c-neutralize-syntax-in-and-mark-CPP (begg endd old-len)
;; (i) Extend the font lock region to cover all changed preprocessor
;; regions; it does this by setting the variables `c-new-BEG' and
;; `c-new-END' to the new boundaries.
;; extended changed region. "Restore" lines which were CPP lines before the
;; change and are no longer so; these can be located from the Buffer local
;; variables `c-old-BOM' and `c-old-EOM'.
- ;;
+ ;;
+ ;; (iii) Mark every CPP construct by placing a `category' property value
+ ;; `c-cpp-delimiter' at its start and end. The marked characters are the
+ ;; opening # and usually the terminating EOL, but sometimes the character
+ ;; before a comment/string delimiter.
+ ;;
;; That is, set syntax-table properties on characters that would otherwise
;; interact syntactically with those outside the CPP line(s).
- ;;
+ ;;
;; This function is called from an after-change function, BEGG ENDD and
;; OLD-LEN being the standard parameters. It prepares the buffer for font
;; locking, hence must get called before `font-lock-after-change-function'.
;; This function is the C/C++/ObjC value of `c-before-font-lock-function'.
;;
;; Note: SPEED _MATTERS_ IN THIS FUNCTION!!!
- ;;
+ ;;
;; This function might make hidden buffer changes.
- (c-save-buffer-state (limits mbeg+1)
+ (c-save-buffer-state (limits)
;; First determine the region, (c-new-BEG c-new-END), which will get font
;; locked. It might need "neutralizing". This region may not start
;; inside a string, comment, or macro.
(goto-char c-old-BOM) ; already set to old start of macro or begg.
(setq c-new-BEG
- (if (setq limits (c-literal-limits))
- (cdr limits) ; go forward out of any string or comment.
- (point)))
+ (min c-new-BEG
+ (if (setq limits (c-state-literal-at (point)))
+ (cdr limits) ; go forward out of any string or comment.
+ (point))))
(goto-char endd)
- (if (setq limits (c-literal-limits))
+ (if (setq limits (c-state-literal-at (point)))
(goto-char (car limits))) ; go backward out of any string or comment.
(if (c-beginning-of-macro)
(c-end-of-macro))
- (setq c-new-END (max (+ (- c-old-EOM old-len) (- endd begg))
- (point)))
+ (setq c-new-END (max c-new-END
+ (+ (- c-old-EOM old-len) (- endd begg))
+ (point)))
- ;; Clear any existing punctuation properties.
+ ;; Clear all old relevant properties.
(c-clear-char-property-with-value c-new-BEG c-new-END 'syntax-table '(1))
+ (c-clear-char-property-with-value c-new-BEG c-new-END 'category 'c-cpp-delimiter)
+ ;; FIXME!!! What about the "<" and ">" category properties? 2009-11-16
;; Add needed properties to each CPP construct in the region.
(goto-char c-new-BEG)
- (let ((pps-position c-new-BEG) pps-state)
+ (let ((pps-position c-new-BEG) pps-state mbeg)
(while (and (< (point) c-new-END)
(search-forward-regexp c-anchored-cpp-prefix c-new-END t))
;; If we've found a "#" inside a string/comment, ignore it.
pps-position (point))
(unless (or (nth 3 pps-state) ; in a string?
(nth 4 pps-state)) ; in a comment?
- (setq mbeg+1 (point))
- (c-end-of-macro) ; Do we need to go forward 1 char here? No!
- (c-neutralize-CPP-line mbeg+1 (point))
- (setq pps-position (point))))))) ; no need to update pps-state.
+ (goto-char (match-beginning 0))
+ (setq mbeg (point))
+ (if (> (c-syntactic-end-of-macro) mbeg)
+ (progn
+ (c-neutralize-CPP-line mbeg (point))
+ (c-set-cpp-delimiters mbeg (point))
+ ;(setq pps-position (point))
+ )
+ (forward-line)) ; no infinite loop with, e.g., "#//"
+ )))))
(defun c-before-change (beg end)
- ;; Function to be put on `before-change-function'. Primarily, this calls
- ;; the language dependent `c-get-state-before-change-function'. It is
+ ;; 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
;; larger than (beg end).
(setq c-new-BEG beg
c-new-END end)
- (if c-get-state-before-change-function
- (funcall c-get-state-before-change-function beg end))
+ (if c-get-state-before-change-functions
+ (mapc (lambda (fn)
+ (funcall fn beg end))
+ c-get-state-before-change-functions))
))))
(defun c-after-change (beg end old-len)
(when (> beg end)
(setq beg end)))
+ ;; C-y is capable of spuriously converting category properties
+ ;; c-</>-as-paren-syntax into hard syntax-table properties. Remove
+ ;; these when it happens.
+ (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-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)
c-beginning-of-syntax
(font-lock-mark-block-function
. c-mark-function)))
-
- (make-local-hook 'font-lock-mode-hook)
+ (if (featurep 'xemacs)
+ (make-local-hook 'font-lock-mode-hook))
(add-hook 'font-lock-mode-hook 'c-after-font-lock-init nil t))
(defun c-extend-after-change-region (beg end old-len)