summaryrefslogtreecommitdiff
path: root/lisp/progmodes/cc-mode.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/progmodes/cc-mode.el')
-rw-r--r--lisp/progmodes/cc-mode.el746
1 files changed, 623 insertions, 123 deletions
diff --git a/lisp/progmodes/cc-mode.el b/lisp/progmodes/cc-mode.el
index aa2a286dbe9..b45c2e5fd38 100644
--- a/lisp/progmodes/cc-mode.el
+++ b/lisp/progmodes/cc-mode.el
@@ -11,6 +11,8 @@
;; Maintainer: bug-cc-mode@gnu.org
;; Created: a long, long, time ago. adapted from the original c-mode.el
;; Keywords: c languages
+;; The version header below is used for ELPA packaging.
+;; Version: 5.33.1
;; This file is part of GNU Emacs.
@@ -126,6 +128,25 @@
; '
(require 'cc-fonts) ;)
+;; The following three really belong to cc-fonts.el, but they are required
+;; even when cc-fonts.el hasn't been loaded (this happens in XEmacs when
+;; font-lock-mode is nil).
+
+(defvar c-doc-line-join-re regexp-unmatchable)
+;; Matches a join of two lines in a doc comment.
+;; This should not be changed directly, but instead set by
+;; `c-setup-doc-comment-style'. This variable is used in `c-find-decl-spots'
+;; in (e.g.) autodoc style comments to bridge the gap between a "@\n" at an
+;; EOL and the token following "//!" on the next line.
+
+(defvar c-doc-bright-comment-start-re regexp-unmatchable)
+;; Matches the start of a "bright" comment, one whose contents may be
+;; fontified by, e.g., `c-font-lock-declarations'.
+
+(defvar c-doc-line-join-end-ch nil)
+;; A list of characters, each being a last character of a doc comment marker,
+;; e.g. the ! from pike autodoc's "//!".
+
;; Other modes and packages which depend on CC Mode should do the
;; following to make sure everything is loaded and available for their
@@ -499,9 +520,10 @@ preferably use the `c-mode-menu' language constant directly."
;; `basic-save-buffer' does (insert ?\n) when `require-final-newline' is
;; non-nil; (ii) to detect when Emacs fails to invoke
;; `before-change-functions'. This can happen when reverting a buffer - see
-;; bug #24094. It seems these failures happen only in GNU Emacs; XEmacs
-;; seems to maintain the strict alternation of calls to
-;; `before-change-functions' and `after-change-functions'.
+;; bug #24094. It seems these failures happen only in GNU Emacs; XEmacs seems
+;; to maintain the strict alternation of calls to `before-change-functions'
+;; and `after-change-functions'. Note that this variable is not set when
+;; `c-before-change' is invoked by a change to text properties.
(defun c-basic-common-init (mode default-style)
"Do the necessary initialization for the syntax handling routines
@@ -556,6 +578,8 @@ that requires a literal mode spec at compile time."
;; doesn't work with filladapt but it's better than nothing.
(set (make-local-variable 'fill-paragraph-function) 'c-fill-paragraph)
+ ;; Initialize the three literal sub-caches.
+ (c-truncate-lit-pos-cache 1)
;; Initialize the cache of brace pairs, and opening braces/brackets/parens.
(c-state-cache-init)
;; Initialize the "brace stack" cache.
@@ -563,7 +587,7 @@ that requires a literal mode spec at compile time."
(when (or c-recognize-<>-arglists
(c-major-mode-is 'awk-mode)
- (c-major-mode-is '(java-mode c-mode c++-mode objc-mode)))
+ (c-major-mode-is '(java-mode c-mode c++-mode objc-mode pike-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.
@@ -650,6 +674,9 @@ that requires a literal mode spec at compile time."
(make-local-hook 'after-change-functions))
(add-hook 'before-change-functions 'c-before-change nil t)
(setq c-just-done-before-change nil)
+ ;; FIXME: We should use the new `depth' arg in Emacs-27 (e.g. a depth of -10
+ ;; would do since font-lock uses a(n implicit) depth of 0) so we don't need
+ ;; c-after-font-lock-init.
(add-hook 'after-change-functions 'c-after-change nil t)
(when (boundp 'font-lock-extend-after-change-region-function)
(set (make-local-variable 'font-lock-extend-after-change-region-function)
@@ -675,14 +702,12 @@ that requires a literal mode spec at compile time."
(make-variable-buffer-local 'c-new-BEG)
(defvar c-new-END 0)
(make-variable-buffer-local 'c-new-END)
-;; The following two variables record the values of `c-new-BEG' and
-;; `c-new-END' just after `c-new-END' has been adjusted for the length of text
-;; inserted or removed. They may be read by any after-change function (but
-;; should not be altered by one).
-(defvar c-old-BEG 0)
-(make-variable-buffer-local 'c-old-BEG)
-(defvar c-old-END 0)
-(make-variable-buffer-local 'c-old-END)
+
+;; Buffer local variable which notes the value of calling `c-in-literal' just
+;; before a change. It is one of 'string, 'c, 'c++ (for the two sorts of
+;; comments), or nil.
+(defvar c-old-END-literality nil)
+(make-variable-buffer-local 'c-old-END-literality)
(defun c-common-init (&optional mode)
"Common initialization for all CC Mode modes.
@@ -882,7 +907,6 @@ Note that the style variables are always made local to the buffer."
;;; Change hooks, linking with Font Lock and electric-indent-mode.
-
(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
@@ -897,7 +921,8 @@ Note that the style variables are always made local to the buffer."
(defun c-depropertize-CPP (beg end)
;; Remove the punctuation syntax-table text property from the CPP parts of
- ;; (c-new-BEG c-new-END).
+ ;; (c-new-BEG c-new-END), and remove all syntax-table properties from any
+ ;; raw strings within these CPP parts.
;;
;; This function is in the C/C++/ObjC values of
;; `c-get-state-before-change-functions' and is called exclusively as a
@@ -909,6 +934,8 @@ Note that the style variables are always made local to the buffer."
(goto-char (match-beginning 1))
(setq m-beg (point))
(c-end-of-macro)
+ (when (c-major-mode-is 'c++-mode)
+ (save-excursion (c-depropertize-raw-strings-in-region m-beg (point))))
(c-clear-char-property-with-value m-beg (point) 'syntax-table '(1)))
(while (and (< (point) end)
@@ -917,14 +944,18 @@ Note that the style variables are always made local to the buffer."
(goto-char (match-beginning 1))
(setq m-beg (point))
(c-end-of-macro))
- (if (and ss-found (> (point) end))
- (c-clear-char-property-with-value m-beg (point) 'syntax-table '(1)))
+ (when (and ss-found (> (point) end))
+ (when (c-major-mode-is 'c++-mode)
+ (save-excursion (c-depropertize-raw-strings-in-region m-beg (point))))
+ (c-clear-char-property-with-value m-beg (point) 'syntax-table '(1)))
(while (and (< (point) c-new-END)
(search-forward-regexp c-anchored-cpp-prefix c-new-END 'bound))
(goto-char (match-beginning 1))
(setq m-beg (point))
(c-end-of-macro)
+ (when (c-major-mode-is 'c++-mode)
+ (save-excursion (c-depropertize-raw-strings-in-region m-beg (point))))
(c-clear-char-property-with-value
m-beg (point) 'syntax-table '(1)))))
@@ -996,9 +1027,9 @@ Note that the style variables are always made local to the buffer."
;; characters, ones which would interact syntactically with stuff outside
;; this region.
;;
- ;; These are unmatched string delimiters, or unmatched
- ;; parens/brackets/braces. An unclosed comment is regarded as valid, NOT
- ;; obtrusive.
+ ;; These are unmatched parens/brackets/braces. An unclosed comment is
+ ;; regarded as valid, NOT obtrusive. Unbalanced strings are handled
+ ;; elsewhere.
(save-excursion
(let (s)
(while
@@ -1008,9 +1039,11 @@ Note that the style variables are always made local to the buffer."
((< (nth 0 s) 0) ; found an unmated ),},]
(c-put-char-property (1- (point)) 'syntax-table '(1))
t)
- ((nth 3 s) ; In a string
- (c-put-char-property (nth 8 s) 'syntax-table '(1))
- t)
+ ;; Unbalanced strings are now handled by
+ ;; `c-before-change-check-unbalanced-strings', etc.
+ ;; ((nth 3 s) ; In a string
+ ;; (c-put-char-property (nth 8 s) 'syntax-table '(1))
+ ;; t)
((> (nth 0 s) 0) ; In a (,{,[
(c-put-char-property (nth 1 s) 'syntax-table '(1))
t)
@@ -1070,6 +1103,400 @@ Note that the style variables are always made local to the buffer."
(forward-line)) ; no infinite loop with, e.g., "#//"
)))))
+(defun c-unescaped-nls-in-string-p (&optional quote-pos)
+ ;; Return whether unescaped newlines can be inside strings.
+ ;;
+ ;; QUOTE-POS, if present, is the position of the opening quote of a string.
+ ;; Depending on the language, there might be a special character before it
+ ;; signifying the validity of such NLs.
+ (cond
+ ((null c-multiline-string-start-char) nil)
+ ((c-characterp c-multiline-string-start-char)
+ (and quote-pos
+ (eq (char-before quote-pos) c-multiline-string-start-char)))
+ (t t)))
+
+(defun c-multiline-string-start-is-being-detached (end)
+ ;; If (e.g.), the # character in Pike is being detached from the string
+ ;; opener it applies to, return t. Else return nil. END is the argument
+ ;; supplied to every before-change function.
+ (and (memq (char-after end) c-string-delims)
+ (c-characterp c-multiline-string-start-char)
+ (eq (char-before end) c-multiline-string-start-char)))
+
+(defun c-pps-to-string-delim (end)
+ ;; parse-partial-sexp forward to the next string quote, which is deemed to
+ ;; be a closing quote. Return nil.
+ ;;
+ ;; We remove string-fence syntax-table text properties from characters we
+ ;; pass over.
+ (let* ((start (point))
+ (no-st-s `(0 nil nil ?\" nil nil 0 nil ,start nil nil))
+ (st-s `(0 nil nil t nil nil 0 nil ,start nil nil))
+ no-st-pos st-pos
+ )
+ (parse-partial-sexp start end nil nil no-st-s 'syntax-table)
+ (setq no-st-pos (point))
+ (goto-char start)
+ (while (progn
+ (parse-partial-sexp (point) end nil nil st-s 'syntax-table)
+ (unless (bobp)
+ (c-clear-char-property (1- (point)) 'syntax-table))
+ (setq st-pos (point))
+ (and (< (point) end)
+ (not (eq (char-before) ?\")))))
+ (goto-char (min no-st-pos st-pos))
+ nil))
+
+(defun c-multiline-string-check-final-quote ()
+ ;; Check that the final quote in the buffer is correctly marked or not with
+ ;; a string-fence syntax-table text propery. The return value has no
+ ;; significance.
+ (let (pos-ll pos-lt)
+ (save-excursion
+ (goto-char (point-max))
+ (skip-chars-backward "^\"")
+ (while
+ (and
+ (not (bobp))
+ (cond
+ ((progn
+ (setq pos-ll (c-literal-limits)
+ pos-lt (c-literal-type pos-ll))
+ (memq pos-lt '(c c++)))
+ ;; In a comment.
+ (goto-char (car pos-ll)))
+ ((save-excursion
+ (backward-char) ; over "
+ (eq (logand (skip-chars-backward "\\\\") 1) 1))
+ ;; At an escaped string.
+ (backward-char)
+ t)
+ (t
+ ;; At a significant "
+ (c-clear-char-property (1- (point)) 'syntax-table)
+ (setq pos-ll (c-literal-limits)
+ pos-lt (c-literal-type pos-ll))
+ nil)))
+ (skip-chars-backward "^\""))
+ (cond
+ ((bobp))
+ ((eq pos-lt 'string)
+ (c-put-char-property (1- (point)) 'syntax-table '(15)))
+ (t nil)))))
+
+(defvar c-bc-changed-stringiness nil)
+;; Non-nil when, in a before-change function, the deletion of a range of text
+;; will change the "stringiness" of the subsequent text. Only used when
+;; `c-multiline-sting-start-char' is a non-nil value which isn't a character.
+
+(defun c-before-change-check-unbalanced-strings (beg end)
+ ;; If BEG or END is inside an unbalanced string, remove the syntax-table
+ ;; text property from respectively the start or end of the string. Also
+ ;; extend the region (c-new-BEG c-new-END) as necessary to cope with the
+ ;; coming change involving the insertion or deletion of an odd number of
+ ;; quotes.
+ ;;
+ ;; POINT is undefined both at entry to and exit from this function, the
+ ;; buffer will have been widened, and match data will have been saved.
+ ;;
+ ;; This function is called exclusively as a before-change function via
+ ;; `c-get-state-before-change-functions'.
+ (c-save-buffer-state
+ ((end-limits
+ (progn
+ (goto-char (if (c-multiline-string-start-is-being-detached end)
+ (1+ end)
+ end))
+ (c-literal-limits)))
+ (end-literal-type (and end-limits
+ (c-literal-type end-limits)))
+ (beg-limits
+ (progn
+ (goto-char beg)
+ (c-literal-limits)))
+ (beg-literal-type (and beg-limits
+ (c-literal-type beg-limits))))
+
+ ;; It is possible the buffer change will include inserting a string quote.
+ ;; This could have the effect of flipping the meaning of any following
+ ;; quotes up until the next unescaped EOL. Also guard against the change
+ ;; being the insertion of \ before an EOL, escaping it.
+ (cond
+ ((c-characterp c-multiline-string-start-char)
+ ;; The text about to be inserted might contain a multiline string
+ ;; opener. Set c-new-END after anything which might be affected.
+ ;; Go to the end of the putative multiline string.
+ (goto-char end)
+ (c-pps-to-string-delim (point-max))
+ (when (< (point) (point-max))
+ (while
+ (and
+ (progn
+ (while
+ (and
+ (c-syntactic-re-search-forward
+ (if c-single-quotes-quote-strings
+ "[\"']\\|\\s|"
+ "\"\\|\\s|")
+ (point-max) t t)
+ (progn
+ (c-clear-char-property (1- (point)) 'syntax-table)
+ (c-truncate-lit-pos-cache (1- (point)))
+ (not (memq (char-before) c-string-delims)))))
+ (memq (char-before) c-string-delims))
+ (progn
+ (c-pps-to-string-delim (point-max))
+ (< (point) (point-max))))))
+ (setq c-new-END (max (point) c-new-END)))
+
+ (c-multiline-string-start-char
+ (setq c-bc-changed-stringiness
+ (not (eq (eq end-literal-type 'string)
+ (eq beg-literal-type 'string))))
+ ;; Deal with deletion of backslashes before "s.
+ (goto-char end)
+ (if (and (looking-at (if c-single-quotes-quote-strings
+ "\\\\*[\"']"
+ "\\\\*\""))
+ (eq (logand (skip-chars-backward "\\\\" beg) 1) 1))
+ (setq c-bc-changed-stringiness (not c-bc-changed-stringiness)))
+ (if (eq beg-literal-type 'string)
+ (setq c-new-BEG (min (car beg-limits) c-new-BEG))))
+
+ ((< end (point-max))
+ ;; Have we just escaped a newline by deleting characters?
+ (if (and (eq end-literal-type 'string)
+ (memq (char-after end) '(?\n ?\r)))
+ (cond
+ ;; Are we escaping a newline by deleting stuff between \ and \n?
+ ((and (> end beg)
+ (progn
+ (goto-char end)
+ (eq (logand (skip-chars-backward "\\\\" beg) 1) 1)))
+ (c-clear-char-property end 'syntax-table)
+ (c-truncate-lit-pos-cache end)
+ (goto-char (1+ end)))
+ ;; Are we unescaping a newline by inserting stuff between \ and \n?
+ ((and (eq end beg)
+ (progn
+ (goto-char end)
+ (eq (logand (skip-chars-backward "\\\\") 1) 1)))
+ (goto-char (1+ end))) ; To after the NL which is being unescaped.
+ (t
+ (goto-char end)))
+ (goto-char end))
+
+ ;; Move to end of logical line (as it will be after the change, or as it
+ ;; was before unescaping a NL.)
+ (re-search-forward "\\(\\\\\\(.\\|\n\\|\r\\)\\|[^\\\n\r]\\)*" nil t)
+ ;; We're at an EOLL or point-max.
+ (if (equal (c-get-char-property (point) 'syntax-table) '(15))
+ (if (memq (char-after) '(?\n ?\r))
+ ;; Normally terminated invalid string.
+ (let ((eoll-1 (point)))
+ (forward-char)
+ (backward-sexp)
+ (c-clear-char-property eoll-1 'syntax-table)
+ (c-clear-char-property (point) 'syntax-table)
+ (c-truncate-lit-pos-cache (point)))
+ ;; Opening " at EOB.
+ (c-clear-char-property (1- (point)) 'syntax-table))
+ (when (and (c-search-backward-char-property 'syntax-table '(15) c-new-BEG)
+ (memq (char-after) c-string-delims)) ; Ignore an unterminated raw string's (.
+ ;; Opening " on last line of text (without EOL).
+ (c-clear-char-property (point) 'syntax-table)
+ (c-truncate-lit-pos-cache (point))
+ (setq c-new-BEG (min c-new-BEG (point))))))
+
+ (t (goto-char end) ; point-max
+ (when
+ (and
+ (c-search-backward-char-property 'syntax-table '(15) c-new-BEG)
+ (memq (char-after) c-string-delims))
+ (c-clear-char-property (point) 'syntax-table)
+ (c-truncate-lit-pos-cache (point)))))
+
+ (unless
+ (or (and
+ ;; Don't set c-new-BEG/END if we're in a raw string.
+ (eq beg-literal-type 'string)
+ (c-at-c++-raw-string-opener (car beg-limits)))
+ (and c-multiline-string-start-char
+ (not (c-characterp c-multiline-string-start-char))))
+ (when (and (eq end-literal-type 'string)
+ (not (eq (char-before (cdr end-limits)) ?\()))
+ (c-clear-char-property (1- (cdr end-limits)) 'syntax-table)
+ (c-truncate-lit-pos-cache (1- (cdr end-limits)))
+ (setq c-new-END (max c-new-END (cdr end-limits))))
+
+ (when (and (eq beg-literal-type 'string)
+ (memq (char-after (car beg-limits)) c-string-delims))
+ (c-clear-char-property (car beg-limits) 'syntax-table)
+ (c-truncate-lit-pos-cache (car beg-limits))
+ (setq c-new-BEG (min c-new-BEG (car beg-limits)))))))
+
+(defun c-after-change-mark-abnormal-strings (beg end _old-len)
+ ;; Mark any unbalanced strings in the region (c-new-BEG c-new-END) with
+ ;; string fence syntax-table text properties.
+ ;;
+ ;; POINT is undefined both at entry to and exit from this function, the
+ ;; buffer will have been widened, and match data will have been saved.
+ ;;
+ ;; This function is called exclusively as an after-change function via
+ ;; `c-before-font-lock-functions'.
+ (if (and c-multiline-string-start-char
+ (not (c-characterp c-multiline-string-start-char)))
+ ;; Only the last " might need to be marked.
+ (c-save-buffer-state
+ ((beg-literal-limits
+ (progn (goto-char beg) (c-literal-limits)))
+ (beg-literal-type (c-literal-type beg-literal-limits))
+ end-literal-limits end-literal-type)
+ (when (and (eq beg-literal-type 'string)
+ (c-get-char-property (car beg-literal-limits) 'syntax-table))
+ (c-clear-char-property (car beg-literal-limits) 'syntax-table)
+ (setq c-bc-changed-stringiness (not c-bc-changed-stringiness)))
+ (setq end-literal-limits (progn (goto-char end) (c-literal-limits))
+ end-literal-type (c-literal-type end-literal-limits))
+ ;; Deal with the insertion of backslashes before a ".
+ (goto-char end)
+ (if (and (looking-at "\\\\*\"")
+ (eq (logand (skip-chars-backward "\\\\" beg) 1) 1))
+ (setq c-bc-changed-stringiness (not c-bc-changed-stringiness)))
+ (when (eq (eq (eq beg-literal-type 'string)
+ (eq end-literal-type 'string))
+ c-bc-changed-stringiness)
+ (c-multiline-string-check-final-quote)))
+ ;; There could be several "s needing marking.
+ (c-save-buffer-state
+ ((cll (progn (goto-char c-new-BEG)
+ (c-literal-limits)))
+ (beg-literal-type (and cll (c-literal-type cll)))
+ (beg-limits
+ (cond
+ ((and (eq beg-literal-type 'string)
+ (c-unescaped-nls-in-string-p (car cll)))
+ (cons
+ (car cll)
+ (progn
+ (goto-char (1+ (car cll)))
+ (search-forward-regexp
+ (cdr (assq (char-after (car cll)) c-string-innards-re-alist))
+ nil t)
+ (min (1+ (point)) (point-max)))))
+ ((and (null beg-literal-type)
+ (goto-char beg)
+ (and (not (bobp))
+ (eq (char-before) c-multiline-string-start-char))
+ (memq (char-after) c-string-delims))
+ (cons (point)
+ (progn
+ (forward-char)
+ (search-forward-regexp
+ (cdr (assq (char-before) c-string-innards-re-alist)) nil t)
+ (1+ (point)))))
+ (cll)))
+ (end-hwm ; the highest position which could possibly be affected by
+ ; insertion/deletion of string delimiters.
+ (max
+ (progn
+ (goto-char (min (1+ end) ; 1+, in case a NL has become escaped.
+ (point-max)))
+ (re-search-forward "\\(\\\\\\(.\\|\n\\|\r\\)\\|[^\\\n\r]\\)*"
+ nil t)
+ (point))
+ c-new-END))
+ s)
+ (goto-char
+ (cond ((null beg-literal-type)
+ c-new-BEG)
+ ((eq beg-literal-type 'string)
+ (car beg-limits))
+ (t ; comment
+ (cdr beg-limits))))
+ ;; Handle one string each time around the next while loop.
+ (while
+ (and
+ (< (point) end-hwm)
+ (progn
+ ;; Skip over any comments before the next string.
+ (while (progn
+ (setq s (parse-partial-sexp (point) end-hwm nil
+ nil s 'syntax-table))
+ (and (< (point) end-hwm)
+ (or (not (nth 3 s))
+ (not (memq (char-before) c-string-delims))))))
+ ;; We're at the start of a string.
+ (memq (char-before) c-string-delims)))
+ (unless (and (c-major-mode-is 'c++-mode)
+ (c-maybe-re-mark-raw-string))
+ (if (c-unescaped-nls-in-string-p (1- (point)))
+ (looking-at "\\(\\\\\\(.\\|\n\\)\\|[^\"]\\)*")
+ (looking-at (cdr (assq (char-before) c-string-innards-re-alist))))
+ (cond
+ ((memq (char-after (match-end 0)) '(?\n ?\r))
+ (c-put-char-property (1- (point)) 'syntax-table '(15))
+ (c-put-char-property (match-end 0) 'syntax-table '(15))
+ (setq c-new-BEG (min c-new-BEG (point))
+ c-new-END (max c-new-END (match-end 0))))
+ ((or (eq (match-end 0) (point-max))
+ (eq (char-after (match-end 0)) ?\\)) ; \ at EOB
+ (c-put-char-property (1- (point)) 'syntax-table '(15))
+ (setq c-new-BEG (min c-new-BEG (point))
+ c-new-END (max c-new-END (match-end 0))) ; Do we need c-new-END?
+ ))
+ (goto-char (min (1+ (match-end 0)) (point-max))))
+ (setq s nil)))))
+
+(defun c-after-change-escape-NL-in-string (beg end _old_len)
+ ;; If a backslash has just been inserted into a string, and this quotes an
+ ;; existing newline, remove the string fence syntax-table text properties
+ ;; on what has become the tail of the string.
+ ;;
+ ;; POINT is undefined both at entry to and exit from this function, the
+ ;; buffer will have been widened, and match data will have been saved.
+ ;;
+ ;; This function is called exclusively as an after-change function via
+ ;; `c-before-font-lock-functions'. In C++ Mode, it should come before
+ ;; `c-after-change-unmark-raw-strings' in that lang variable.
+ (let (lit-start) ; Don't calculate this till we have to.
+ (when
+ (and (> end beg)
+ (memq (char-after end) '(?\n ?\r))
+ (progn (goto-char end)
+ (eq (logand (skip-chars-backward "\\\\") 1) 1))
+ (progn (goto-char end)
+ (setq lit-start (c-literal-start)))
+ (memq (char-after lit-start) c-string-delims)
+ (or (not (c-major-mode-is 'c++-mode))
+ (progn
+ (goto-char lit-start)
+ (and (not (and (eq (char-before) ?R)
+ (looking-at c-c++-raw-string-opener-1-re)))
+ (not (and (eq (char-after) ?\()
+ (equal (c-get-char-property
+ (point) 'syntax-table)
+ '(15))))))
+ (save-excursion
+ (c-beginning-of-macro))))
+ (goto-char (1+ end)) ; After the \
+ ;; Search forward for a closing ".
+ (when (and (re-search-forward "\\(\\\\\\(.\\|\n\\)\\|[^\"\\\n\r]\\)*"
+ nil t)
+ (eq (char-after) ?\")
+ (equal (c-get-char-property (point) 'syntax-table) '(15)))
+ (c-clear-char-property end 'syntax-table)
+ (c-truncate-lit-pos-cache end)
+ (c-clear-char-property (point) 'syntax-table)
+ (forward-char) ; to after the "
+ (when
+ (and
+ ;; Search forward for an end of logical line.
+ (re-search-forward "\\(\\\\\\(.\\|\n\\)\\|[^\\\n\r]\\)*" nil t)
+ (memq (char-after) '(?\n ?\r)))
+ (c-clear-char-property (point) 'syntax-table))))))
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Parsing of quotes.
;;
@@ -1086,7 +1513,7 @@ Note that the style variables are always made local to the buffer."
(defconst c-maybe-quoted-number-head
(concat
"\\(0\\("
- "\\([Xx]\\([0-9a-fA-F]\\('[0-9a-fA-F]\\|[0-9a-fA-F]\\)*'?\\)?\\)"
+ "\\([Xx]\\([[:xdigit:]]\\('[[:xdigit:]]\\|[[:xdigit:]]\\)*'?\\)?\\)"
"\\|"
"\\([Bb]\\([01]\\('[01]\\|[01]\\)*'?\\)?\\)"
"\\|"
@@ -1106,7 +1533,7 @@ Note that the style variables are always made local to the buffer."
(save-excursion
(let ((here (point))
found)
- (skip-chars-backward "0-9a-fA-F'")
+ (skip-chars-backward "[:xdigit:]'")
(if (and (memq (char-before) '(?x ?X))
(eq (char-before (1- (point))) ?0))
(backward-char 2))
@@ -1120,7 +1547,7 @@ Note that the style variables are always made local to the buffer."
(defconst c-maybe-quoted-number-tail
(concat
"\\("
- "\\([xX']?[0-9a-fA-F]\\('[0-9a-fA-F]\\|[0-9a-fA-F]\\)*\\)"
+ "\\([xX']?[[:xdigit:]]\\('[[:xdigit:]]\\|[[:xdigit:]]\\)*\\)"
"\\|"
"\\([bB']?[01]\\('[01]\\|[01]\\)*\\)"
"\\|"
@@ -1140,7 +1567,7 @@ Note that this is a strict tail, so won't match, e.g. \"0x....\".")
(defconst c-maybe-quoted-number
(concat
"\\(0\\("
- "\\([Xx][0-9a-fA-F]\\('[0-9a-fA-F]\\|[0-9a-fA-F]\\)*\\)"
+ "\\([Xx][[:xdigit:]]\\('[[:xdigit:]]\\|[[:xdigit:]]\\)*\\)"
"\\|"
"\\([Bb][01]\\('[01]\\|[01]\\)*\\)"
"\\|"
@@ -1158,9 +1585,9 @@ Note that this is a strict tail, so won't match, e.g. \"0x....\".")
(when c-has-quoted-numbers
(save-excursion
(let ((here (point))
- (bound (progn (skip-chars-forward "0-9a-fA-F'") (point))))
+ (bound (progn (skip-chars-forward "[:xdigit:]'") (point))))
(goto-char here)
- (when (< (skip-chars-backward "0-9a-fA-F'") 0)
+ (when (< (skip-chars-backward "[:xdigit:]'") 0)
(if (and (memq (char-before) '(?x ?X))
(eq (char-before (1- (point))) ?0))
(backward-char 2))
@@ -1172,7 +1599,7 @@ Note that this is a strict tail, so won't match, e.g. \"0x....\".")
(goto-char (match-beginning 0))
(save-excursion (search-forward "'" (match-end 0) t)))))))))
-(defun c-parse-quotes-before-change (beg end)
+(defun c-parse-quotes-before-change (_beg _end)
;; This function analyzes 's near the region (c-new-BEG c-new-END), amending
;; those two variables as needed to include 's into that region when they
;; might be syntactically relevant to the change in progress.
@@ -1184,7 +1611,7 @@ Note that this is a strict tail, so won't match, e.g. \"0x....\".")
;;
;; This function is called exclusively as a before-change function via the
;; variable `c-get-state-before-change-functions'.
- (c-save-buffer-state ()
+ (c-save-buffer-state (case-fold-search)
(goto-char c-new-BEG)
;; We need to scan for 's from the BO (logical) line.
(beginning-of-line)
@@ -1200,14 +1627,17 @@ Note that this is a strict tail, so won't match, e.g. \"0x....\".")
((c-quoted-number-head-before-point)
(if (>= (point) c-new-BEG)
(setq c-new-BEG (match-beginning 0))))
- ((looking-at "\\([^'\\]\\|\\\\.\\)'")
+ ((looking-at
+ "\\([^'\\]\\|\\\\\\([0-7]\\{1,3\\}\\|[xuU][[:xdigit:]]+\\|.\\)\\)'")
(goto-char (match-end 0))
(if (> (match-end 0) c-new-BEG)
(setq c-new-BEG (1- (match-beginning 0)))))
- ((or (>= (point) (1- c-new-BEG))
- (and (eq (point) (- c-new-BEG 2))
- (eq (char-after) ?\\)))
- (setq c-new-BEG (1- (point))))
+ ((looking-at "\\\\'")
+ (setq c-new-BEG (min c-new-BEG (1- (point))))
+ (goto-char (match-end 0)))
+ ((save-excursion
+ (not (search-forward "'" c-new-BEG t)))
+ (setq c-new-BEG (min c-new-BEG (1- (point)))))
(t nil)))
(goto-char c-new-END)
@@ -1226,19 +1656,29 @@ Note that this is a strict tail, so won't match, e.g. \"0x....\".")
(goto-char (match-end 0))
(if (> (match-end 0) c-new-END)
(setq c-new-END (match-end 0))))
- ((looking-at "\\([^'\\]\\|\\\\.\\)'")
+ ((looking-at
+ "\\([^'\\]\\|\\\\\\([0-7]\\{1,3\\}\\|[xuU][[:xdigit:]]+\\|.\\)\\)'")
(goto-char (match-end 0))
(if (> (match-end 0) c-new-END)
(setq c-new-END (match-end 0))))
+ ((looking-at "\\\\'")
+ (goto-char (match-end 0))
+ (setq c-new-END (max c-new-END (point))))
+ ((equal (c-get-char-property (1- (point)) 'syntax-table) '(1))
+ (when (c-search-forward-char-property-with-value-on-char
+ 'syntax-table '(1) ?\' (c-point 'eoll))
+ (setq c-new-END (max (point) c-new-END))))
(t nil)))
;; Having reached c-new-END, handle any 's after it whose context may be
- ;; changed by the current buffer change.
+ ;; changed by the current buffer change. The idea is to catch
+ ;; monstrosities like ',',',',',' changing "polarity".
(goto-char c-new-END)
(cond
((c-quoted-number-tail-after-point)
(setq c-new-END (match-end 0)))
((looking-at
- "\\(\\\\.\\|.\\)?\\('\\([^'\\]\\|\\\\.\\)\\)*'")
+ "\\(\\\\\\([0-7]\\{1,3\\}\\|[xuU][[:xdigit:]]+\\|.\\)\\|.\\)?\
+\\('\\([^'\\]\\|\\\\\\([0-7]\\{1,3\\}\\|[xuU][[:xdigit:]]+\\|.\\)\\)\\)*'")
(setq c-new-END (match-end 0))))
;; Remove the '(1) syntax-table property from any "'"s within (c-new-BEG
@@ -1247,7 +1687,7 @@ Note that this is a strict tail, so won't match, e.g. \"0x....\".")
(when (c-search-forward-char-property-with-value-on-char
'syntax-table '(1) ?\' c-new-END)
(c-invalidate-state-cache (1- (point)))
- (c-truncate-semi-nonlit-pos-cache (1- (point)))
+ (c-truncate-lit-pos-cache (1- (point)))
(c-clear-char-property-with-value-on-char
(1- (point)) c-new-END
'syntax-table '(1)
@@ -1259,7 +1699,7 @@ Note that this is a strict tail, so won't match, e.g. \"0x....\".")
'c-digit-separator t
?')))))
-(defun c-parse-quotes-after-change (beg end old-len)
+(defun c-parse-quotes-after-change (_beg _end _old-len)
;; This function applies syntax-table properties (value '(1)) and
;; c-digit-separator properties as needed to 's within the range (c-new-BEG
;; c-new-END). This operation is performed even within strings and
@@ -1267,7 +1707,7 @@ Note that this is a strict tail, so won't match, e.g. \"0x....\".")
;;
;; This function is called exclusively as an after-change function via the
;; variable `c-before-font-lock-functions'.
- (c-save-buffer-state (num-beg num-end)
+ (c-save-buffer-state (num-beg num-end case-fold-search)
;; Apply the needed syntax-table and c-digit-separator text properties to
;; quotes.
(save-restriction
@@ -1283,17 +1723,25 @@ Note that this is a strict tail, so won't match, e.g. \"0x....\".")
(setq num-beg (match-beginning 0)
num-end (match-end 0))
(c-invalidate-state-cache num-beg)
- (c-truncate-semi-nonlit-pos-cache num-beg)
+ (c-truncate-lit-pos-cache num-beg)
(c-put-char-properties-on-char num-beg num-end
'syntax-table '(1) ?')
(c-put-char-properties-on-char num-beg num-end
'c-digit-separator t ?')
(goto-char num-end))
- ((looking-at "\\([^\\']\\|\\\\.\\)'") ; balanced quoted expression.
+ ((looking-at
+ "\\([^\\']\\|\\\\\\([0-7]\\{1,3\\}\\|[xuU][[:xdigit:]]+\\|.\\)\
+\\)'") ; balanced quoted expression.
+ (goto-char (match-end 0)))
+ ((looking-at "\\\\'") ; Anomalous construct.
+ (c-invalidate-state-cache (1- (point)))
+ (c-truncate-lit-pos-cache (1- (point)))
+ (c-put-char-properties-on-char (1- (point)) (+ (point) 2)
+ 'syntax-table '(1) ?')
(goto-char (match-end 0)))
(t
(c-invalidate-state-cache (1- (point)))
- (c-truncate-semi-nonlit-pos-cache (1- (point)))
+ (c-truncate-lit-pos-cache (1- (point)))
(c-put-char-property (1- (point)) 'syntax-table '(1))))
;; Prevent the next `c-quoted-number-straddling-point' getting
;; confused by already processed single quotes.
@@ -1322,6 +1770,10 @@ Note that this is a strict tail, so won't match, e.g. \"0x....\".")
;; (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)
+ ;; 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-restriction
(save-match-data
(widen)
@@ -1332,7 +1784,7 @@ Note that this is a strict tail, so won't match, e.g. \"0x....\".")
;; 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 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;"?
@@ -1418,7 +1870,8 @@ Note that this is a strict tail, so won't match, e.g. \"0x....\".")
;; without an intervening call to `before-change-functions' when reverting
;; the buffer (see bug #24094). Whatever the cause, assume that the entire
;; buffer has changed.
- (when (not c-just-done-before-change)
+ (when (and (not c-just-done-before-change)
+ (not (c-called-from-text-property-change-p)))
(save-restriction
(widen)
(c-before-change (point-min) (point-max))
@@ -1429,7 +1882,6 @@ Note that this is a strict tail, so won't match, e.g. \"0x....\".")
;; (c-new-BEG c-new-END) will be the region to fontify. It may become
;; larger than (beg end).
(setq c-new-END (- (+ c-new-END (- end beg)) old-len))
- (setq c-old-BEG c-new-BEG c-old-END c-new-END)
(unless (c-called-from-text-property-change-p)
(setq c-just-done-before-change nil)
@@ -1473,7 +1925,41 @@ Note that this is a strict tail, so won't match, e.g. \"0x....\".")
(save-excursion
(mapc (lambda (fn)
(funcall fn beg end old-len))
- c-before-font-lock-functions)))))))
+ c-before-font-lock-functions))))))
+ ;; A workaround for syntax-ppss's failure to notice syntax-table text
+ ;; property changes.
+ (when (fboundp 'syntax-ppss)
+ (syntax-ppss-flush-cache c-syntax-table-hwm)))
+
+(defun c-doc-fl-decl-start (pos)
+ ;; If the line containing POS is in a doc comment continued line (as defined
+ ;; by `c-doc-line-join-re'), return the position of the first line of the
+ ;; sequence. Otherwise, return nil. Point has no significance at entry to
+ ;; and exit from this function.
+ (when (not (equal c-doc-line-join-re regexp-unmatchable))
+ (goto-char pos)
+ (back-to-indentation)
+ (and (or (looking-at c-comment-start-regexp)
+ (memq (c-literal-type (c-literal-limits)) '(c c++)))
+ (progn
+ (end-of-line)
+ (let ((here (point)))
+ (while (re-search-backward c-doc-line-join-re (c-point 'bopl) t))
+ (and (not (eq (point) here))
+ (c-point 'bol)))))))
+
+(defun c-doc-fl-decl-end (pos)
+ ;; If the line containing POS is continued by a doc comment continuation
+ ;; marker (as defined by `c-doc-line-join-re), return the position of
+ ;; the BOL at the end of the sequence. Otherwise, return nil. Point has no
+ ;; significance at entry to and exit from this function.
+ (when (not (equal c-doc-line-join-re regexp-unmatchable))
+ (goto-char pos)
+ (back-to-indentation)
+ (let ((here (point)))
+ (while (re-search-forward c-doc-line-join-re (c-point 'eonl) t))
+ (and (not (eq (point) here))
+ (c-point 'bonl)))))
(defun c-fl-decl-start (pos)
;; If the beginning of the line containing POS is in the middle of a "local"
@@ -1482,6 +1968,9 @@ Note that this is a strict tail, so won't match, e.g. \"0x....\".")
;; declaration is one which does not start outside of struct braces (and
;; similar) enclosing POS. Brace list braces here are not "similar".
;;
+ ;; POS being in a literal does not count as being in a declaration (on
+ ;; pragmatic grounds).
+ ;;
;; This function is called indirectly from font locking stuff - either from
;; c-after-change (to prepare for after-change font-locking) or from font
;; lock context (etc.) fontification.
@@ -1492,83 +1981,89 @@ Note that this is a strict tail, so won't match, e.g. \"0x....\".")
capture-opener
bod-lim bo-decl)
(goto-char (c-point 'bol new-pos))
- (when lit-start ; Comment or string.
- (goto-char lit-start))
- (setq bod-lim (c-determine-limit 500))
-
- ;; In C++ Mode, first check if we are within a (possibly nested) lambda
- ;; form capture list.
- (when (c-major-mode-is 'c++-mode)
- (let ((paren-state (c-parse-state))
- opener)
+ (unless lit-start
+ (setq bod-lim (c-determine-limit 500))
+
+ ;; In C++ Mode, first check if we are within a (possibly nested) lambda
+ ;; form capture list.
+ (when (c-major-mode-is 'c++-mode)
(save-excursion
- (while (setq opener (c-pull-open-brace paren-state))
- (goto-char opener)
- (if (c-looking-at-c++-lambda-capture-list)
- (setq capture-opener (point)))))))
-
- (while
- ;; Go to a less nested declaration each time round this loop.
- (and
- (setq old-pos (point))
- (c-syntactic-skip-backward "^;{}" bod-lim t)
- (> (point) bod-lim)
- (progn (c-forward-syntactic-ws)
- ;; Have we got stuck in a comment at EOB?
- (not (and (eobp)
- (c-literal-start))))
- (< (point) old-pos)
- (progn (setq bo-decl (point))
- (or (not (looking-at c-protection-key))
- (c-forward-keyword-clause 1)))
- (progn
- ;; Are we looking at a keyword such as "template" or
- ;; "typedef" which can decorate a type, or the type itself?
- (when (or (looking-at c-prefix-spec-kwds-re)
- (c-forward-type t))
- ;; We've found another candidate position.
- (setq new-pos (min new-pos bo-decl))
- (goto-char bo-decl))
- t)
- ;; Try and go out a level to search again.
- (progn
- (c-backward-syntactic-ws bod-lim)
- (and (> (point) bod-lim)
- (or (memq (char-before) '(?\( ?\[))
- (and (eq (char-before) ?\<)
- (eq (c-get-char-property
- (1- (point)) 'syntax-table)
- c-<-as-paren-syntax))
- (and (eq (char-before) ?{)
- (save-excursion
- (backward-char)
- (consp (c-looking-at-or-maybe-in-bracelist))))
- )))
- (not (bobp)))
- (backward-char)) ; back over (, [, <.
- (when (and capture-opener (< capture-opener new-pos))
- (setq new-pos capture-opener))
- (and (/= new-pos pos) new-pos)))
+ (while (and (c-go-up-list-backward nil bod-lim)
+ (c-looking-at-c++-lambda-capture-list))
+ (setq capture-opener (point)))))
+
+ (while
+ ;; Go to a less nested declaration each time round this loop.
+ (and
+ (setq old-pos (point))
+ (let (pseudo)
+ (while
+ (progn
+ (c-syntactic-skip-backward "^;{}" bod-lim t)
+ (and (eq (char-before) ?})
+ (save-excursion
+ (backward-char)
+ (setq pseudo (c-cheap-inside-bracelist-p (c-parse-state))))))
+ (goto-char pseudo))
+ t)
+ (> (point) bod-lim)
+ (progn (c-forward-syntactic-ws)
+ ;; Have we got stuck in a comment at EOB?
+ (not (and (eobp)
+ (c-literal-start))))
+ (< (point) old-pos)
+ (progn (setq bo-decl (point))
+ (or (not (looking-at c-protection-key))
+ (c-forward-keyword-clause 1)))
+ (progn
+ ;; Are we looking at a keyword such as "template" or
+ ;; "typedef" which can decorate a type, or the type itself?
+ (when (or (looking-at c-prefix-spec-kwds-re)
+ (c-forward-type t))
+ ;; We've found another candidate position.
+ (setq new-pos (min new-pos bo-decl))
+ (goto-char bo-decl))
+ t)
+ ;; Try and go out a level to search again.
+ (progn
+ (c-backward-syntactic-ws bod-lim)
+ (and (> (point) bod-lim)
+ (or (memq (char-before) '(?\( ?\[))
+ (and (eq (char-before) ?\<)
+ (eq (c-get-char-property
+ (1- (point)) 'syntax-table)
+ c-<-as-paren-syntax))
+ (and (eq (char-before) ?{)
+ (save-excursion
+ (backward-char)
+ (consp (c-looking-at-or-maybe-in-bracelist))))
+ )))
+ (not (bobp)))
+ (backward-char)) ; back over (, [, <.
+ (when (and capture-opener (< capture-opener new-pos))
+ (setq new-pos capture-opener))
+ (and (/= new-pos pos) new-pos))))
(defun c-fl-decl-end (pos)
;; If POS is inside a declarator, return the end of the token that follows
- ;; the declarator, otherwise return nil.
+ ;; the declarator, otherwise return nil. POS being in a literal does not
+ ;; count as being in a declarator (on pragmatic grounds).
(goto-char pos)
(let ((lit-start (c-literal-start))
pos1)
- (if lit-start (goto-char lit-start))
- (c-backward-syntactic-ws)
- (when (setq pos1 (c-on-identifier))
- (goto-char pos1)
- (let ((lim (save-excursion
- (and (c-beginning-of-macro)
- (progn (c-end-of-macro) (point))))))
- (when (and (c-forward-declarator lim)
- (or (not (eq (char-after) ?\())
- (c-go-list-forward nil lim))
- (eq (c-forward-token-2 1 nil lim) 0))
- (c-backward-syntactic-ws)
- (point))))))
+ (unless lit-start
+ (c-backward-syntactic-ws)
+ (when (setq pos1 (c-on-identifier))
+ (goto-char pos1)
+ (let ((lim (save-excursion
+ (and (c-beginning-of-macro)
+ (progn (c-end-of-macro) (point))))))
+ (when (and (c-forward-declarator lim)
+ (or (not (eq (char-after) ?\())
+ (c-go-list-forward nil lim))
+ (eq (c-forward-token-2 1 nil lim) 0))
+ (c-backward-syntactic-ws)
+ (point)))))))
(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
@@ -1581,9 +2076,10 @@ Note that this is a strict tail, so won't match, e.g. \"0x....\".")
;; 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))
+ (or (c-fl-decl-start c-new-BEG) (c-doc-fl-decl-start c-new-BEG)
+ (c-point 'bol c-new-BEG))
c-new-END
- (or (c-fl-decl-end c-new-END)
+ (or (c-fl-decl-end c-new-END) (c-doc-fl-decl-end c-new-END)
(c-point 'bonl c-new-END)))))
(defun c-context-expand-fl-region (beg end)
@@ -1591,8 +2087,10 @@ Note that this is a strict tail, so won't match, e.g. \"0x....\".")
;; "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.
(c-save-buffer-state ()
- (cons (or (c-fl-decl-start beg) (c-point 'bol beg))
- (or (c-fl-decl-end end) (c-point 'bonl (1- end))))))
+ (cons (or (c-fl-decl-start beg) (c-doc-fl-decl-start beg)
+ (c-point 'bol beg))
+ (or (c-fl-decl-end end) (c-doc-fl-decl-end end)
+ (c-point 'bonl (1- end))))))
(defun c-before-context-fl-expand-region (beg end)
;; Expand the region (BEG END) as specified by
@@ -1835,6 +2333,7 @@ Key bindings:
(c-common-init 'c-mode)
(easy-menu-add c-c-menu)
(cc-imenu-init cc-imenu-c-generic-expression)
+ (add-hook 'flymake-diagnostic-functions 'flymake-cc nil t)
(c-run-mode-hooks 'c-mode-common-hook))
(defconst c-or-c++-mode--regexp
@@ -1922,6 +2421,7 @@ Key bindings:
(c-common-init 'c++-mode)
(easy-menu-add c-c++-menu)
(cc-imenu-init cc-imenu-c++-generic-expression)
+ (add-hook 'flymake-diagnostic-functions 'flymake-cc nil t)
(c-run-mode-hooks 'c-mode-common-hook))
@@ -2000,7 +2500,7 @@ Key bindings:
;; since it's practically impossible to write a regexp that reliably
;; matches such a construct. Other tools are necessary.
(defconst c-Java-defun-prompt-regexp
- "^[ \t]*\\(\\(\\(public\\|protected\\|private\\|const\\|abstract\\|synchronized\\|final\\|static\\|threadsafe\\|transient\\|native\\|volatile\\)\\s-+\\)*\\(\\(\\([[a-zA-Z][][_$.a-zA-Z0-9]*[][_$.a-zA-Z0-9]+\\|[[a-zA-Z]\\)\\s-*\\)\\s-+\\)\\)?\\(\\([[a-zA-Z][][_$.a-zA-Z0-9]*\\s-+\\)\\s-*\\)?\\([_a-zA-Z][^][ \t:;.,{}()=]*\\|\\([_$a-zA-Z][_$.a-zA-Z0-9]*\\)\\)\\s-*\\(([^);{}]*)\\)?\\([] \t]*\\)\\(\\s-*\\<throws\\>\\s-*\\(\\([_$a-zA-Z][_$.a-zA-Z0-9]*\\)[, \t\n\r\f\v]*\\)+\\)?\\s-*")
+ "^[ \t]*\\(\\(\\(public\\|protected\\|private\\|const\\|abstract\\|synchronized\\|final\\|static\\|threadsafe\\|transient\\|native\\|volatile\\)\\s-+\\)*\\(\\(\\([[a-zA-Z][][_$.a-zA-Z0-9]*[][_$.a-zA-Z0-9]+\\|[[a-zA-Z]\\)\\s-*\\)\\s-+\\)\\)?\\(\\([[a-zA-Z][][_$.a-zA-Z0-9]*\\s-+\\)\\s-*\\)?\\([_a-zA-Z][^][ \t:;.,{}()\^?=]*\\|\\([_$a-zA-Z][_$.a-zA-Z0-9]*\\)\\)\\s-*\\(([^);{}]*)\\)?\\([] \t]*\\)\\(\\s-*\\<throws\\>\\s-*\\(\\([_$a-zA-Z][_$.a-zA-Z0-9]*\\)[, \t\n\r\f\v]*\\)+\\)?\\s-*")
(easy-menu-define c-java-menu java-mode-map "Java Mode Commands"
(cons "Java" (c-lang-const c-mode-menu java)))