Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:ymarkovitch
emacs
emacs-cc-mode-master.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File emacs-cc-mode-master.patch of Package emacs
diff --git a/lisp/progmodes/cc-align.el b/lisp/progmodes/cc-align.el index 3f39374008..51d51deef7 100644 --- a/lisp/progmodes/cc-align.el +++ b/lisp/progmodes/cc-align.el @@ -274,8 +274,10 @@ statement-block-intro, statement-case-intro, arglist-intro." (save-excursion (beginning-of-line) (backward-up-list 1) + (forward-char) (skip-chars-forward " \t" (c-point 'eol)) - (vector (1+ (current-column))))) + (if (eolp) (skip-chars-backward " \t")) + (vector (current-column)))) (defun c-lineup-arglist-close-under-paren (langelem) "Line up a line under the enclosing open paren. @@ -790,6 +792,38 @@ arglist-cont-nonempty." (or (c-lineup-assignments langelem) c-basic-offset)) +(defun c-lineup-ternary-bodies (langelem) + "Line up true and false branches of a ternary operator (i.e. `?:'). +More precisely, if the line starts with a colon which is a part of +a said operator, align it with corresponding question mark; otherwise +return nil. For example: + + return arg % 2 == 0 ? arg / 2 + : (3 * arg + 1); <- c-lineup-ternary-bodies + +Works with: arglist-cont, arglist-cont-nonempty and statement-cont." + (save-excursion + (back-to-indentation) + (when (and (eq ?: (char-after)) + (not (eq ?: (char-after (1+ (point)))))) + (let ((limit (c-langelem-pos langelem)) (depth 1)) + (catch 'done + (while (and (c-syntactic-skip-backward "^?:" limit t) + (not (bobp))) + (backward-char) + (cond ((eq (char-after) ??) + ;; If we've found a question mark, decrease depth. If we've + ;; reached zero, we've found the one we were looking for. + (when (zerop (setq depth (1- depth))) + (throw 'done (vector (current-column))))) + ((or (eq ?: (char-before)) (eq ?? (char-before))) + ;; Step over `::' and `?:' operators. We don't have to + ;; handle `?:' here but doing so saves an iteration. + (if (eq (point) limit) + (throw 'done nil) + (goto-char (1- (point))))) + ((setq depth (1+ depth)))))))))) ; Otherwise increase depth. + (defun c-lineup-cascaded-calls (langelem) "Line up \"cascaded calls\" under each other. If the line begins with \"->\" or \".\" and the preceding line ends @@ -1083,7 +1117,7 @@ arglist-cont." (vector (+ (current-column) c-basic-offset)))) (vector 0))))) -(defun c-lineup-2nd-brace-entry-in-arglist (langelem) +(defun c-lineup-2nd-brace-entry-in-arglist (_langelem) "Lineup the second entry of a brace block under the first, when the first line is also contained in an arglist or an enclosing brace ON THAT LINE. @@ -1113,7 +1147,8 @@ Works with brace-list-intro." ; the line. (save-excursion ; "{" earlier on the line (goto-char (c-langelem-pos - (assq 'brace-list-intro c-syntactic-context))) + (assq 'brace-list-entry + c-syntactic-context))) (and (eq (c-backward-token-2 1 nil @@ -1124,7 +1159,7 @@ Works with brace-list-intro." (eq (char-after) ?{)))) 'c-lineup-arglist-intro-after-paren)) -(defun c-lineup-class-decl-init-+ (langelem) +(defun c-lineup-class-decl-init-+ (_langelem) "Line up the second entry of a class (etc.) initializer c-basic-offset characters in from the identifier when: \(i) The type is a class, struct, union, etc. (but not an enum); @@ -1165,7 +1200,7 @@ Works with: brace-list-intro." (eq (point) init-pos) (vector (+ (current-column) c-basic-offset))))))) -(defun c-lineup-class-decl-init-after-brace (langelem) +(defun c-lineup-class-decl-init-after-brace (_langelem) "Line up the second entry of a class (etc.) initializer after its opening brace when: \(i) The type is a class, struct, union, etc. (but not an enum); diff --git a/lisp/progmodes/cc-awk.el b/lisp/progmodes/cc-awk.el index 802e75765b..3228944372 100644 --- a/lisp/progmodes/cc-awk.el +++ b/lisp/progmodes/cc-awk.el @@ -49,9 +49,11 @@ (load "cc-bytecomp" nil t))) (cc-require 'cc-defs) +(cc-require-when-compile 'cc-langs) +(cc-require-when-compile 'cc-fonts) +(cc-require 'cc-engine) ;; Silence the byte compiler. -(cc-bytecomp-defvar font-lock-mode) ; Checked with boundp before use. (cc-bytecomp-defvar c-new-BEG) (cc-bytecomp-defvar c-new-END) @@ -649,6 +651,46 @@ ;; several lines back. The elisp "advice" feature is used on these functions ;; to allow this. +(defun c-awk-font-lock-invalid-namespace-separators (limit) + ;; This function will be called from font-lock for a region bounded by POINT + ;; and LIMIT, as though it were to identify a keyword for + ;; font-lock-keyword-face. It always returns NIL to inhibit this and + ;; prevent a repeat invocation. See elisp/lispref page "Search-based + ;; Fontification". + ;; + ;; This function gives invalid GAWK namepace separators (::) + ;; font-lock-warning-face. "Invalid" here means there are spaces, etc., + ;; around a separator, or there are more than one of them in an identifier. + ;; Invalid separators inside function declaration parentheses are handled + ;; elsewhere. + (while (and + (< (point) limit) + (c-syntactic-re-search-forward + (eval-when-compile + (concat "\\([^" (c-lang-const c-symbol-chars awk) "]::\\)" + "\\|" + ;; "\\(::[^" (c-lang-const c-symbol-start awk) "]\\)" + "\\(::[^" c-alpha "_" "]\\)" + "\\|" + "\\(::[" (c-lang-const c-symbol-chars awk) "]*::\\)")) + limit 'bound)) + (cond + ((match-beginning 1) ; " ::" + (c-put-font-lock-face (1+ (match-beginning 1)) (match-end 1) + 'font-lock-warning-face) + (goto-char (- (match-end 1) 2))) + ((match-beginning 2) ; ":: " + (c-put-font-lock-face (match-beginning 2) (1- (match-end 2)) + 'font-lock-warning-face) + (goto-char (1- (match-end 2)))) + (t ; "::foo::" + (c-put-font-lock-face (match-beginning 3) (+ 2 (match-beginning 3)) + 'font-lock-warning-face) + (c-put-font-lock-face (- (match-end 3) 2) (match-end 3) + 'font-lock-warning-face) + (goto-char (- (match-end 3) 2))))) + nil) + (defun c-awk-beginning-of-logical-line (&optional pos) ;; Go back to the start of the (apparent) current line (or the start of the ;; line containing POS), returning the buffer position of that point. I.e., @@ -900,6 +942,13 @@ (goto-char c-new-BEG) (c-awk-set-syntax-table-properties c-new-END))) +(defun c-awk-context-expand-fl-region (beg end) + ;; Return a cons (NEW-BEG . NEW-END), where NEW-BEG is the beginning of the + ;; logical line BEG is on, and NEW-END is the beginning of the line after + ;; the end of the logical line that END is on. + (cons (save-excursion (c-awk-beginning-of-logical-line beg)) + (c-awk-beyond-logical-line end))) + ;; Awk regexps written with help from Peter Galbraith ;; <galbraith@mixing.qc.dfo.ca>. ;; Take GNU Emacs's 'words out of the following regexp-opts. They don't work @@ -907,18 +956,34 @@ (defconst awk-font-lock-keywords (eval-when-compile (list - ;; Function names. - '("^\\s *\\(func\\(tion\\)?\\)\\>\\s *\\(\\sw+\\)?" - (1 font-lock-keyword-face) (3 font-lock-function-name-face nil t)) - ;; + ;; Function declarations. + `(,(c-make-font-lock-search-function + "^\\s *\\(func\\(tion\\)?\\)\\s +\\(\\(\\sw+\\(::\\sw+\\)?\\)\\s *\\)?\\(([^()]*)\\)?" + '(1 font-lock-keyword-face t) + ;; We can't use LAXMATCH in `c-make-font-lock-search-function', so.... + '((when (match-beginning 4) + (c-put-font-lock-face + (match-beginning 4) (match-end 4) font-lock-function-name-face) + nil)) + ;; Put warning face on any use of :: inside the parens. + '((when (match-beginning 6) + (goto-char (1+ (match-beginning 6))) + (let ((end (1- (match-end 6)))) + (while (and (< (point) end) + (c-syntactic-re-search-forward "::" end t)) + (c-put-font-lock-face (- (point) 2) (point) + 'font-lock-warning-face))) + nil)))) + ;; Variable names. (cons (concat "\\<" (regexp-opt '("ARGC" "ARGIND" "ARGV" "BINMODE" "CONVFMT" "ENVIRON" - "ERRNO" "FIELDWIDTHS" "FILENAME" "FNR" "FS" "IGNORECASE" - "LINT" "NF" "NR" "OFMT" "OFS" "ORS" "PROCINFO" "RLENGTH" - "RS" "RSTART" "RT" "SUBSEP" "TEXTDOMAIN") t) "\\>") + "ERRNO" "FIELDWIDTHS" "FILENAME" "FNR" "FPAT" "FS" "FUNCTAB" + "IGNORECASE" "LINT" "NF" "NR" "OFMT" "OFS" "ORS" "PREC" + "PROCINFO" "RLENGTH" "ROUNDMODE" "RS" "RSTART" "RT" "SUBSEP" + "SYNTAB" "TEXTDOMAIN") t) "\\>") 'font-lock-variable-name-face) ;; Special file names. (acm, 2002/7/22) @@ -949,7 +1014,8 @@ std\\(err\\|in\\|out\\)\\|user\\)\\)\\>\ ;; Keywords. (concat "\\<" (regexp-opt - '("BEGIN" "END" "break" "case" "continue" "default" "delete" + '("BEGIN" "BEGINFILE" "END" "ENDFILE" + "break" "case" "continue" "default" "delete" "do" "else" "exit" "for" "getline" "if" "in" "next" "nextfile" "return" "switch" "while") t) "\\>") @@ -959,16 +1025,20 @@ std\\(err\\|in\\|out\\)\\|user\\)\\)\\>\ ,(concat "\\<" (regexp-opt - '("adump" "and" "asort" "atan2" "bindtextdomain" "close" - "compl" "cos" "dcgettext" "exp" "extension" "fflush" - "gensub" "gsub" "index" "int" "length" "log" "lshift" - "match" "mktime" "or" "print" "printf" "rand" "rshift" + '("adump" "and" "asort" "asorti" "atan2" "bindtextdomain" "close" + "compl" "cos" "dcgettext" "dcngettext" "exp" "extension" "fflush" + "gensub" "gsub" "index" "int" "isarray" "length" "log" "lshift" + "match" "mktime" "or" "patsplit" "print" "printf" "rand" "rshift" "sin" "split" "sprintf" "sqrt" "srand" "stopme" "strftime" "strtonum" "sub" "substr" "system" - "systime" "tolower" "toupper" "xor") t) + "systime" "tolower" "toupper" "typeof" "xor") + t) "\\>") 0 c-preprocessor-face-name)) + ;; Directives + `(eval . '("@\\(include\\|load\\|namespace\\)\\>" 0 ,c-preprocessor-face-name)) + ;; gawk debugging keywords. (acm, 2002/7/21) ;; (Removed, 2003/6/6. These functions are now fontified as built-ins) ;; (list (concat "\\<" (regexp-opt '("adump" "stopme") t) "\\>") @@ -980,6 +1050,9 @@ std\\(err\\|in\\|out\\)\\|user\\)\\)\\>\ c-awk-escaped-nls*-with-space* "(") (0 'font-lock-warning-face)) + ;; Double :: tokens, or the same with space(s) around them. + #'c-awk-font-lock-invalid-namespace-separators + ;; Space after \ in what looks like an escaped newline. 2002/5/31 '("\\\\\\s +$" 0 font-lock-warning-face t) @@ -1003,7 +1076,7 @@ std\\(err\\|in\\|out\\)\\|user\\)\\)\\>\ ;; Matches an unterminated string/regexp, NOT including the eol at the end. (defconst c-awk-harmless-pattern-characters* - (concat "\\([^{;#/\"\\\\\n\r]\\|" c-awk-esc-pair-re "\\)*")) + (concat "\\([^{;#/\"\\\n\r]\\|" c-awk-esc-pair-re "\\)*")) ;; Matches any "harmless" character in a pattern or an escaped character pair. (defun c-awk-at-statement-end-p () diff --git a/lisp/progmodes/cc-cmds.el b/lisp/progmodes/cc-cmds.el index a80fb12af3..1754436d13 100644 --- a/lisp/progmodes/cc-cmds.el +++ b/lisp/progmodes/cc-cmds.el @@ -48,6 +48,7 @@ (cc-bytecomp-defvar filladapt-mode) ; c-fill-paragraph contains a kludge ; which looks at this. (cc-bytecomp-defun electric-pair-post-self-insert-function) +(cc-bytecomp-defvar c-indent-to-body-directives) ;; Indentation / Display syntax functions (defvar c-fix-backslashes t) @@ -512,11 +513,11 @@ function to control that." (let ((src (default-value 'post-self-insert-hook))) (while src (unless (memq (car src) c--unsafe-post-self-insert-hook-functions) - (add-hook 'dest (car src) t)) ; Preserve the order of the functions. + (push (car src) dest)) (setq src (cdr src))))) - (t (add-hook 'dest (car src) t))) ; Preserve the order of the functions. + (t (push (car src) dest))) (setq src (cdr src))) - (run-hooks 'dest))) + (mapc #'funcall (nreverse dest)))) ; Preserve the order of the functions. (defmacro c--call-post-self-insert-hook-more-safely () ;; Call post-self-insert-hook, if such exists. See comment for @@ -906,7 +907,6 @@ settings of `c-cleanup-list' are done." (when (and (boundp 'electric-pair-mode) electric-pair-mode) (let ((size (buffer-size)) - (c-in-electric-pair-functionality t) post-self-insert-hook) (electric-pair-post-self-insert-function) (setq got-pair-} (and at-eol @@ -1441,6 +1441,98 @@ keyword on the line, the keyword is not inserted inside a literal, and (indent-according-to-mode) (delete-char -2))))) +(defun c-align-cpp-indent-to-body () + "Align a \"#pragma\" line under the previous line. +This function is intented for use as a member of `c-special-indent-hook'." + (when (assq 'cpp-macro c-syntactic-context) + (when + (save-excursion + (save-match-data + (back-to-indentation) + (and + (looking-at (concat c-opt-cpp-symbol "[ \t]*\\([a-zA-Z0-9_]+\\)")) + (member (match-string-no-properties 1) + c-cpp-indent-to-body-directives)))) + (c-indent-line (delete '(cpp-macro) c-syntactic-context))))) + +(defvar c-cpp-indent-to-body-flag nil) +;; Non-nil when CPP directives such as "#pragma" should be indented to under +;; the preceding statement. +(make-variable-buffer-local 'c-cpp-indent-to-body-flag) + +(defun c-electric-pragma () + "Reindent the current line if appropriate. + +This function is used to reindent a preprocessor line when the +symbol for the directive, typically \"pragma\", triggers this +function as a hook function of an abbreviation. + +The \"#\" of the preprocessor construct is aligned under the +first anchor point of the line's syntactic context. + +The line is reindented if the construct is not in a string or +comment, there is exactly one \"#\" contained in optional +whitespace before it on the current line, and `c-electric-flag' +and `c-syntactic-indentation' are both non-nil." + (save-excursion + (save-match-data + (when + (and + c-cpp-indent-to-body-flag + c-electric-flag + c-syntactic-indentation + last-abbrev-location + c-opt-cpp-symbol ; "#" or nil. + (progn (back-to-indentation) + (looking-at (concat c-opt-cpp-symbol "[ \t]*"))) + (>= (match-end 0) last-abbrev-location) + (not (c-literal-limits))) + (c-indent-line (delete '(cpp-macro) (c-guess-basic-syntax))))))) + +(defun c-add-indent-to-body-to-abbrev-table (d) + ;; Create an abbreviation table entry for the directive D, and add it to the + ;; current abbreviation table. Existing abbreviation (e.g. for "else") do + ;; not get overwritten. + (when (and c-buffer-is-cc-mode + local-abbrev-table + (not (abbrev-symbol d local-abbrev-table))) + (condition-case nil + (define-abbrev local-abbrev-table d d 'c-electric-pragma 0 t) + (wrong-number-of-arguments + (define-abbrev local-abbrev-table d d 'c-electric-pragma))))) + +(defun c-clear-stale-indent-to-body-abbrevs () + ;; Fill in this comment. FIXME!!! + (when (fboundp 'abbrev-get) + (mapatoms (lambda (a) + (when (and (abbrev-get a ':system) ; Preserve a user's abbrev! + (not (member (symbol-name a) c-std-abbrev-keywords)) + (not (member (symbol-name a) + c-cpp-indent-to-body-directives))) + (unintern a local-abbrev-table))) + local-abbrev-table))) + +(defun c-toggle-cpp-indent-to-body (&optional arg) + "Toggle the C preprocessor indent-to-body feature. +When enabled, preprocessor directives which are words in +`c-indent-to-body-directives' are indented as if they were statements. + +Optional numeric ARG, if supplied, turns on the feature when positive, +turns it off when negative, and just toggles it when zero or +left out." + (interactive "P") + (setq c-cpp-indent-to-body-flag + (c-calculate-state arg c-cpp-indent-to-body-flag)) + (if c-cpp-indent-to-body-flag + (progn + (c-clear-stale-indent-to-body-abbrevs) + (mapc 'c-add-indent-to-body-to-abbrev-table + c-cpp-indent-to-body-directives) + (add-hook 'c-special-indent-hook 'c-align-cpp-indent-to-body nil t)) + (remove-hook 'c-special-indent-hook 'c-align-cpp-indent-to-body t)) + (message "c-cpp-indent-to-body %sabled" + (if c-cpp-indent-to-body-flag "en" "dis"))) + (declare-function subword-forward "subword" (&optional arg)) @@ -1461,19 +1553,6 @@ keyword on the line, the keyword is not inserted inside a literal, and (declare-function c-backward-subword "ext:cc-subword" (&optional arg)) ;; "nomenclature" functions + c-scope-operator. -(defun c-forward-into-nomenclature (&optional arg) - "Compatibility alias for `c-forward-subword'." - (interactive "p") - (if (fboundp 'subword-mode) - (progn - (require 'subword) - (subword-forward arg)) - (require 'cc-subword) - (c-forward-subword arg))) -(make-obsolete 'c-forward-into-nomenclature - (if (fboundp 'subword-mode) 'subword-forward 'c-forward-subword) - "23.2") - (defun c-backward-into-nomenclature (&optional arg) "Compatibility alias for `c-backward-subword'." (interactive "p") @@ -1560,7 +1639,7 @@ No indentation or other \"electric\" behavior is performed." ;; ;; This function might do hidden buffer changes. (save-excursion - (let* (kluge-start + (let* (knr-start knr-res decl-result brace-decl-p (start (point)) (paren-state (c-parse-state)) @@ -1591,63 +1670,39 @@ No indentation or other \"electric\" behavior is performed." (not (looking-at c-defun-type-name-decl-key)))))) 'at-function-end) (t - ;; Find the start of the current declaration. NOTE: If we're in the - ;; variables after a "struct/eval" type block, we don't get to the - ;; real declaration here - we detect and correct for this later. - - ;;If we're in the parameters' parens, move back out of them. - (if least-enclosing (goto-char least-enclosing)) - ;; Kluge so that c-beginning-of-decl-1 won't go back if we're already - ;; at a declaration. - (if (or (and (eolp) (not (eobp))) ; EOL is matched by "\\s>" - (not (looking-at -"\\([;#]\\|\\'\\|\\s(\\|\\s)\\|\\s\"\\|\\s\\\\|\\s$\\|\\s<\\|\\s>\\|\\s!\\)"))) - (forward-char)) - (setq kluge-start (point)) - ;; First approximation as to whether the current "header" we're in is - ;; one followed by braces. - (setq brace-decl-p - (save-excursion - (and (c-syntactic-re-search-forward "[;{]" nil t t) - (or (eq (char-before) ?\{) - (and c-recognize-knr-p - ;; Might have stopped on the - ;; ';' in a K&R argdecl. In - ;; that case the declaration - ;; should contain a block. - (c-in-knr-argdecl)))))) - (setq decl-result - (car (c-beginning-of-decl-1 - ;; NOTE: If we're in a K&R region, this might be the start - ;; of a parameter declaration, not the actual function. - ;; It might also leave us at a label or "label" like - ;; "private:". - (and least-enclosing ; LIMIT for c-b-of-decl-1 - (c-safe-position least-enclosing paren-state))))) - - ;; Has the declaration we've gone back to got braces? - (if (or (eq decl-result 'label) - (looking-at c-protection-key)) - (setq brace-decl-p nil)) - - (cond - ((or (eq decl-result 'label) ; e.g. "private:" or invalid syntax. - (= (point) kluge-start)) ; might be BOB or unbalanced parens. - 'outwith-function) - ((eq decl-result 'same) - (if brace-decl-p - (if (eq (point) start) - 'at-header + (if (and least-enclosing + (eq (char-after least-enclosing) ?\()) + (c-go-list-forward least-enclosing)) + (c-forward-syntactic-ws) + (setq knr-start (point)) + (if (c-syntactic-re-search-forward "{" nil t t) + (progn + (backward-char) + (cond + ((or (progn + (c-backward-syntactic-ws) + (<= (point) start)) + (and c-recognize-knr-p + (and (setq knr-res (c-in-knr-argdecl)) + (<= knr-res knr-start)))) 'in-header) - 'outwith-function)) - ((eq decl-result 'previous) - (if (and (not brace-decl-p) - (c-in-function-trailer-p)) - 'at-function-end - 'outwith-function)) - (t (error - "c-where-wrt-brace-construct: c-beginning-of-decl-1 returned %s" - decl-result)))))))) + ((and knr-res + (goto-char knr-res) + (c-backward-syntactic-ws))) ; Always returns nil. + ((and (eq (char-before) ?\)) + (c-go-list-backward)) + (c-syntactic-skip-backward "^;" start t) + (if (eq (point) start) + (if (progn (c-backward-syntactic-ws) + (memq (char-before) '(?\; ?} nil))) + (if (progn (c-forward-syntactic-ws) + (eq (point) start)) + 'at-header + 'outwith-function) + 'in-header) + 'outwith-function)) + (t 'outwith-function))) + 'outwith-function)))))) (defun c-backward-to-nth-BOF-{ (n where) ;; Skip to the opening brace of the Nth function before point. If @@ -1670,9 +1725,11 @@ No indentation or other \"electric\" behavior is performed." (goto-char (c-least-enclosing-brace (c-parse-state))) (setq n (1- n))) ((eq where 'in-header) - (c-syntactic-re-search-forward "{") - (backward-char) - (setq n (1- n))) + (let ((encl-paren (c-least-enclosing-brace (c-parse-state)))) + (if encl-paren (goto-char encl-paren)) + (c-syntactic-re-search-forward "{" nil t t) + (backward-char) + (setq n (1- n)))) ((memq where '(at-header outwith-function at-function-end in-trailer)) (c-syntactic-skip-backward "^}") (when (eq (char-before) ?\}) @@ -1886,21 +1943,24 @@ defun." ;; The actual movement is done below. (setq n (1- n))) ((memq where '(at-function-end outwith-function at-header in-header)) - (when (c-syntactic-re-search-forward "{" nil 'eob) + (if (eq where 'in-header) + (let ((pos (c-least-enclosing-brace (c-parse-state)))) + (if pos (c-go-list-forward pos)))) + (when (c-syntactic-re-search-forward "{" nil 'eob t) (backward-char) (forward-sexp) (setq n (1- n)))) (t (error "c-forward-to-nth-EOF-\\;-or-}: `where' is %s" where))) - (when (c-in-function-trailer-p) - (c-syntactic-re-search-forward ";" nil 'eob t)) - ;; Each time round the loop, go forward to a "}" at the outermost level. (while (and (> n 0) (not (eobp))) (when (c-syntactic-re-search-forward "{" nil 'eob) (backward-char) (forward-sexp) (setq n (1- n)))) + + (when (c-in-function-trailer-p) + (c-syntactic-re-search-forward ";" nil 'eob t)) n) (defun c-end-of-defun (&optional arg) @@ -2024,6 +2084,23 @@ other top level construct with a brace block." (c-backward-syntactic-ws) (point)))) + ((and (c-major-mode-is 'objc-mode) (looking-at "[-+]\\s-*(")) ; Objective-C method + ;; Move to the beginning of the method name. + (c-forward-token-2 2 t) + (let* ((class + (save-excursion + (when (re-search-backward + "^\\s-*@\\(implementation\\|class\\|interface\\)\\s-+\\(\\sw+\\)" nil t) + (match-string-no-properties 2)))) + (limit (save-excursion (re-search-forward "[;{]" nil t))) + (method (when (re-search-forward "\\(\\sw+:?\\)" limit t) + (match-string-no-properties 1)))) + (when (and class method) + ;; Add the parameter labels onto name. They always end in ':'. + (while (re-search-forward "\\(\\sw+:\\)" limit 1) + (setq method (concat method (match-string-no-properties 1)))) + (concat "[" class " " method "]")))) + (t ; Normal function or initializer. (when (looking-at c-defun-type-name-decl-key) ; struct, etc. (goto-char (match-end 0)) @@ -2230,7 +2307,7 @@ with a brace block, at the outermost level of nesting." (c-save-buffer-state ((paren-state (c-parse-state)) (orig-point-min (point-min)) (orig-point-max (point-max)) - lim name where limits fdoc) + lim name limits where) (setq lim (c-widen-to-enclosing-decl-scope paren-state orig-point-min orig-point-max)) (and lim (setq lim (1- lim))) @@ -2261,7 +2338,7 @@ With a prefix arg, push the name onto the kill ring too." (put 'c-display-defun-name 'isearch-scroll t) (defun c-mark-function () - "Put mark at end of the current top-level declaration or macro, point at beginning. + "Put mark at end of current top-level declaration or macro, point at beginning. If point is not inside any then the closest following one is chosen. Each successive call of this command extends the marked region by one function. diff --git a/lisp/progmodes/cc-defs.el b/lisp/progmodes/cc-defs.el index 02415943e4..536e676626 100644 --- a/lisp/progmodes/cc-defs.el +++ b/lisp/progmodes/cc-defs.el @@ -87,7 +87,7 @@ ;;; Variables also used at compile time. -(defconst c-version "5.34.1" +(defconst c-version "5.35.1" "CC Mode version number.") (defconst c-version-sym (intern c-version)) @@ -434,6 +434,14 @@ to it is returned. This function does not modify the point or the mark." (setq count (+ count (skip-chars-backward "\\\\")))) (not (zerop (logand count 1)))))) +(defmacro c-will-be-unescaped (beg) + ;; Would the character after BEG be unescaped? + `(save-excursion + (let (count) + (goto-char ,beg) + (setq count (skip-chars-backward "\\\\")) + (zerop (logand count 1))))) + (defvar c-use-extents) (defmacro c-next-single-property-change (position prop &optional object limit) @@ -445,6 +453,15 @@ to it is returned. This function does not modify the point or the mark." ;; Emacs and earlier XEmacs `(next-single-property-change ,position ,prop ,object ,limit))) +(defmacro c-previous-single-property-change (position prop &optional object limit) + ;; See the doc string for either of the defuns expanded to. + (if (and c-use-extents + (fboundp 'previous-single-char-property-change)) + ;; XEmacs >= 2005-01-25 + `(previous-single-char-property-change ,position ,prop ,object ,limit) + ;; Emacs and earlier XEmacs + `(previous-single-property-change ,position ,prop ,object ,limit))) + (defmacro c-region-is-active-p () ;; Return t when the region is active. The determination of region ;; activeness is different in both Emacs and XEmacs. @@ -674,14 +691,16 @@ whitespace. LIMIT sets an upper limit of the forward movement, if specified. If LIMIT or the end of the buffer is reached inside a comment or -preprocessor directive, the point will be left there. +preprocessor directive, the point will be left there. If point starts +on the wrong side of LIMIT, it stays unchanged. Note that this function might do hidden buffer changes. See the comment at the start of cc-engine.el for more info." (if limit - `(save-restriction - (narrow-to-region (point-min) (or ,limit (point-max))) - (c-forward-sws)) + `(when (< (point) (or ,limit (point-max))) + (save-restriction + (narrow-to-region (point-min) (or ,limit (point-max))) + (c-forward-sws))) '(c-forward-sws))) (defmacro c-backward-syntactic-ws (&optional limit) @@ -693,14 +712,16 @@ whitespace. LIMIT sets a lower limit of the backward movement, if specified. If LIMIT is reached inside a line comment or preprocessor directive then -the point is moved into it past the whitespace at the end. +the point is moved into it past the whitespace at the end. If point +starts on the wrong side of LIMIT, it stays unchanged. Note that this function might do hidden buffer changes. See the comment at the start of cc-engine.el for more info." (if limit - `(save-restriction - (narrow-to-region (or ,limit (point-min)) (point-max)) - (c-backward-sws)) + `(when (> (point) (or ,limit (point-min))) + (save-restriction + (narrow-to-region (or ,limit (point-min)) (point-max)) + (c-backward-sws))) '(c-backward-sws))) (defmacro c-forward-sexp (&optional count) @@ -1047,15 +1068,6 @@ MODE is either a mode symbol or a list of mode symbols." ;; properties set on a single character and that never spread to any ;; other characters. -(defmacro c-put-syn-tab (pos value) - ;; Set both the syntax-table and the c-fl-syn-tab text properties at POS to - ;; VALUE (which should not be nil). - `(let ((-pos- ,pos) - (-value- ,value)) - (c-put-char-property -pos- 'syntax-table -value-) - (c-put-char-property -pos- 'c-fl-syn-tab -value-) - (c-truncate-lit-pos-cache -pos-))) - (eval-and-compile ;; Constant used at compile time to decide whether or not to use ;; XEmacs extents. Check all the extent functions we'll use since @@ -1183,13 +1195,6 @@ MODE is either a mode symbol or a list of mode symbols." ;; Emacs < 21. `(c-clear-char-property-fun ,pos ',property)))) -(defmacro c-clear-syn-tab (pos) - ;; Remove both the 'syntax-table and `c-fl-syn-tab properties at POS. - `(let ((-pos- ,pos)) - (c-clear-char-property -pos- 'syntax-table) - (c-clear-char-property -pos- 'c-fl-syn-tab) - (c-truncate-lit-pos-cache -pos-))) - (defmacro c-min-property-position (from to property) ;; Return the first position in the range [FROM to) where the text property ;; PROPERTY is set, or `most-positive-fixnum' if there is no such position. @@ -1235,8 +1240,18 @@ MODE is either a mode symbol or a list of mode symbols." ;; Remove all occurrences of the `syntax-table' and `c-fl-syn-tab' text ;; properties between FROM and TO. `(let ((-from- ,from) (-to- ,to)) - (c-clear-char-properties -from- -to- 'syntax-table) - (c-clear-char-properties -from- -to- 'c-fl-syn-tab))) + (when (and + c-min-syn-tab-mkr c-max-syn-tab-mkr + (< -from- c-max-syn-tab-mkr) + (> -to- c-min-syn-tab-mkr)) + (let ((pos -from-)) + (while (and + (< pos -to-) + (setq pos (c-min-property-position pos -to- 'c-fl-syn-tab)) + (< pos -to-)) + (c-clear-syn-tab pos) + (setq pos (1+ pos))))) + (c-clear-char-properties -from- -to- 'syntax-table))) (defmacro c-search-forward-char-property (property value &optional limit) "Search forward for a text-property PROPERTY having value VALUE. @@ -1456,28 +1471,6 @@ with value CHAR in the region [FROM to)." (c-put-char-property (point) ,property ,value) (forward-char))))) -(defmacro c-with-extended-string-fences (beg end &rest body) - ;; If needed, extend the region with "mirrored" c-fl-syn-tab properties to - ;; contain the region (BEG END), then evaluate BODY. If this mirrored - ;; region was initially empty, restore it afterwards. - `(let ((-beg- ,beg) - (-end- ,end) - ) - (cond - ((null c-fl-syn-tab-region) - (unwind-protect - (progn - (c-restore-string-fences -beg- -end-) - ,@body) - (c-clear-string-fences))) - ((and (>= -beg- (car c-fl-syn-tab-region)) - (<= -end- (cdr c-fl-syn-tab-region))) - ,@body) - (t ; Crudely extend the mirrored region. - (setq -beg- (min -beg- (car c-fl-syn-tab-region)) - -end- (max -end- (cdr c-fl-syn-tab-region))) - (c-restore-string-fences -beg- -end-) - ,@body)))) ;; Macros to put overlays (Emacs) or extents (XEmacs) on buffer text. ;; For our purposes, these are characterized by being possible to diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el index 5a0f935075..cc9833a434 100644 --- a/lisp/progmodes/cc-engine.el +++ b/lisp/progmodes/cc-engine.el @@ -163,7 +163,9 @@ (defvar c-doc-line-join-re) (defvar c-doc-bright-comment-start-re) (defvar c-doc-line-join-end-ch) -(defvar c-fl-syn-tab-region) +(cc-bytecomp-defvar c-min-syn-tab-mkr) +(cc-bytecomp-defvar c-max-syn-tab-mkr) +(cc-bytecomp-defun c-clear-syn-tab) (cc-bytecomp-defun c-clear-string-fences) (cc-bytecomp-defun c-restore-string-fences) @@ -405,7 +407,7 @@ comment at the start of cc-engine.el for more info." (when (and (car c-macro-cache) (> (point) (car c-macro-cache)) ; in case we have a ; zero-sized region. - (not (eq (char-before (1- (point))) ?\\))) + (not lim)) (setcdr c-macro-cache (point)) (setq c-macro-cache-syntactic nil))))))) @@ -970,7 +972,7 @@ comment at the start of cc-engine.el for more info." ;; that we've moved. (while (progn (setq pos (point)) - (c-backward-syntactic-ws) + (c-backward-syntactic-ws lim) ;; Protect post-++/-- operators just before a virtual semicolon. (and (not (c-at-vsemi-p)) (/= (skip-chars-backward "-+!*&~@`#") 0)))) @@ -982,7 +984,7 @@ comment at the start of cc-engine.el for more info." (if (and (memq (char-before) delims) (progn (forward-char -1) (setq saved (point)) - (c-backward-syntactic-ws) + (c-backward-syntactic-ws lim) (or (memq (char-before) delims) (memq (char-before) '(?: nil)) (eq (char-syntax (char-before)) ?\() @@ -1162,7 +1164,7 @@ comment at the start of cc-engine.el for more info." ;; HERE IS THE SINGLE PLACE INSIDE THE PDA LOOP WHERE WE MOVE ;; BACKWARDS THROUGH THE SOURCE. - (c-backward-syntactic-ws) + (c-backward-syntactic-ws lim) (let ((before-sws-pos (point)) ;; The end position of the area to search for statement ;; barriers in this round. @@ -1172,33 +1174,44 @@ comment at the start of cc-engine.el for more info." ;; Go back over exactly one logical sexp, taking proper ;; account of macros and escaped EOLs. (while - (progn - (setq comma-delimited (and (not comma-delim) - (eq (char-before) ?\,))) - (unless (c-safe (c-backward-sexp) t) - ;; Give up if we hit an unbalanced block. Since the - ;; stack won't be empty the code below will report a - ;; suitable error. - (setq pre-stmt-found t) - (throw 'loop nil)) - (cond - ;; Have we moved into a macro? - ((and (not macro-start) - (c-beginning-of-macro)) - (save-excursion - (c-backward-syntactic-ws) - (setq before-sws-pos (point))) - ;; Have we crossed a statement boundary? If not, - ;; keep going back until we find one or a "real" sexp. - (and + (and + (progn + (setq comma-delimited (and (not comma-delim) + (eq (char-before) ?\,))) + (unless (c-safe (c-backward-sexp) t) + ;; Give up if we hit an unbalanced block. Since the + ;; stack won't be empty the code below will report a + ;; suitable error. + (setq pre-stmt-found t) + (throw 'loop nil)) + ;; Handle C++'s `constexpr', etc. + (if (save-excursion + (and (looking-at c-block-stmt-hangon-key) + (progn + (c-backward-syntactic-ws lim) + (c-safe (c-backward-sexp) t)) + (looking-at c-block-stmt-2-key) + (setq pos (point)))) + (goto-char pos)) + (cond + ;; Have we moved into a macro? + ((and (not macro-start) + (c-beginning-of-macro)) (save-excursion - (c-end-of-macro) - (not (c-crosses-statement-barrier-p - (point) maybe-after-boundary-pos))) - (setq maybe-after-boundary-pos (point)))) - ;; Have we just gone back over an escaped NL? This - ;; doesn't count as a sexp. - ((looking-at "\\\\$"))))) + (c-backward-syntactic-ws lim) + (setq before-sws-pos (point))) + ;; Have we crossed a statement boundary? If not, + ;; keep going back until we find one or a "real" sexp. + (and + (save-excursion + (c-end-of-macro) + (not (c-crosses-statement-barrier-p + (point) maybe-after-boundary-pos))) + (setq maybe-after-boundary-pos (point)))) + ;; Have we just gone back over an escaped NL? This + ;; doesn't count as a sexp. + ((looking-at "\\\\$")))) + (>= (point) lim))) ;; Have we crossed a statement boundary? (setq boundary-pos @@ -1410,12 +1423,14 @@ comment at the start of cc-engine.el for more info." (setq ret 'label))) ;; Skip over the unary operators that can start the statement. - (while (progn - (c-backward-syntactic-ws) - ;; protect AWK post-inc/decrement operators, etc. - (and (not (c-at-vsemi-p (point))) - (/= (skip-chars-backward "-.+!*&~@`#") 0))) + (while (and (> (point) lim) + (progn + (c-backward-syntactic-ws lim) + ;; protect AWK post-inc/decrement operators, etc. + (and (not (c-at-vsemi-p (point))) + (/= (skip-chars-backward "-.+!*&~@`#") 0)))) (setq pos (point))) + (goto-char pos) ret))) @@ -1580,6 +1595,7 @@ comment at the start of cc-engine.el for more info." (save-excursion (backward-char) (looking-at "\\s(")) (c-crosses-statement-barrier-p (point) end))))) +(make-obsolete 'c-at-expression-start-p nil "CC mode 5.35") ;; A set of functions that covers various idiosyncrasies in @@ -1642,6 +1658,21 @@ comment at the start of cc-engine.el for more info." (forward-char 2) t)))) +(defmacro c-forward-comment-minus-1 () + "Call (forward-comment -1), taking care of escaped newlines. +Return the result of `forward-comment' if it gets called, nil otherwise." + `(if (not comment-end-can-be-escaped) + (forward-comment -1) + (when (and (< (skip-syntax-backward " >") 0) + (eq (char-after) ?\n)) + (forward-char)) + (cond + ((and (eq (char-before) ?\n) + (eq (char-before (1- (point))) ?\\)) + (backward-char) + nil) + (t (forward-comment -1))))) + (defun c-backward-single-comment () "Move backward past whitespace and the closest preceding comment, if any. Return t if a comment was found, nil otherwise. In either case, the @@ -1675,12 +1706,12 @@ This function does not do any hidden buffer changes." ;; same line. (re-search-forward "\\=\\s *[\n\r]" start t) - (if (if (forward-comment -1) + (if (if (c-forward-comment-minus-1) (if (eolp) ;; If forward-comment above succeeded and we're at eol ;; then the newline we moved over above didn't end a ;; line comment, so we give it another go. - (forward-comment -1) + (c-forward-comment-minus-1) t)) ;; Emacs <= 20 and XEmacs move back over the closer of a @@ -1709,7 +1740,7 @@ comment at the start of cc-engine.el for more info." (if (let (moved-comment) (while - (and (not (setq moved-comment (forward-comment -1))) + (and (not (setq moved-comment (c-forward-comment-minus-1))) ;; Cope specifically with ^M^J here - ;; forward-comment sometimes gets stuck after ^Ms, ;; sometimes after ^M^J. @@ -1895,52 +1926,29 @@ comment at the start of cc-engine.el for more info." (defun c-enclosing-c++-attribute () ;; If we're in C++ Mode, and point is within a correctly balanced [[ ... ]] ;; attribute structure, return a cons of its starting and ending positions. - ;; Otherwise, return nil. We use the c-{in,is}-sws-face text properties for - ;; this determination, this macro being intended only for use in the *-sws-* - ;; functions and macros. The match data are NOT preserved over this macro. - (let (attr-end pos-is-sws) - (and - (c-major-mode-is 'c++-mode) - (> (point) (point-min)) - (setq pos-is-sws - (if (get-text-property (1- (point)) 'c-is-sws) - (1- (point)) - (1- (previous-single-property-change - (point) 'c-is-sws nil (point-min))))) - (save-excursion - (goto-char pos-is-sws) - (setq attr-end (c-looking-at-c++-attribute))) - (> attr-end (point)) - (cons pos-is-sws attr-end)))) - -(defun c-slow-enclosing-c++-attribute () - ;; Like `c-enclosing-c++-attribute', but does not depend on the c-i[ns]-sws - ;; properties being set. + ;; Otherwise, return nil. (and (c-major-mode-is 'c++-mode) (save-excursion - (let ((paren-state (c-parse-state)) + (let ((lim (max (- (point) 200) (point-min))) cand) (while - (progn - (setq cand - (catch 'found-cand - (while (cdr paren-state) - (when (and (numberp (car paren-state)) - (numberp (cadr paren-state)) - (eq (car paren-state) - (1+ (cadr paren-state))) - (eq (char-after (car paren-state)) ?\[) - (eq (char-after (cadr paren-state)) ?\[)) - (throw 'found-cand (cadr paren-state))) - (setq paren-state (cdr paren-state))))) - (and cand - (not - (and (c-go-list-forward cand) - (eq (char-before) ?\]) - (eq (char-before (1- (point))) ?\]))))) - (setq paren-state (cdr paren-state))) - (and cand (cons cand (point))))))) + (and + (progn + (skip-chars-backward "^[;{}" lim) + (eq (char-before) ?\[)) + (not (eq (char-before (1- (point))) ?\[)) + (> (point) lim)) + (backward-char)) + (and (eq (char-before) ?\[) + (eq (char-before (1- (point))) ?\[) + (progn (backward-char 2) t) + (setq cand (point)) + (c-go-list-forward nil (min (+ (point) 200) (point-max))) + (eq (char-before) ?\]) + (eq (char-before (1- (point))) ?\]) + (not (c-literal-limits)) + (cons cand (point))))))) (defun c-invalidate-sws-region-before (beg end) ;; Called from c-before-change. BEG and END are the bounds of the change @@ -2243,7 +2251,7 @@ comment at the start of cc-engine.el for more info." ((and c-opt-cpp-prefix (looking-at c-noise-macro-name-re)) - ;; Skip over a noise macro. + ;; Skip over a noise macro without parens. (goto-char (match-end 1)) (not (eobp))) @@ -2666,7 +2674,7 @@ comment at the start of cc-engine.el for more info." ;; One of the above "near" caches is associated with each of these functions. ;; ;; When searching this cache, these functions first seek an exact match, then -;; a "close" match from the assiciated near cache. If neither of these +;; a "close" match from the associated near cache. If neither of these ;; succeed, the nearest preceding entry in the far cache is used. ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -2702,7 +2710,7 @@ comment at the start of cc-engine.el for more info." ;; or the car of the list is the "position element" of ELT, the position ;; where ELT is valid. ;; - ;; POINT is left at the postition for which the returned state is valid. It + ;; POINT is left at the position for which the returned state is valid. It ;; will be either the position element of ELT, or one character before ;; that. (The latter happens in Emacs <= 25 and XEmacs, when ELT indicates ;; its position element directly follows a potential first character of a @@ -2710,7 +2718,7 @@ comment at the start of cc-engine.el for more info." (if (and (consp elt) (>= (length elt) 3)) ;; Inside a string or comment (let ((depth 0) (containing nil) (last nil) - in-string in-comment (after-quote nil) + in-string in-comment (min-depth 0) com-style com-str-start (intermediate nil) (char-1 (nth 3 elt)) ; first char of poss. 2-char construct (pos (car elt)) @@ -2772,7 +2780,7 @@ comment at the start of cc-engine.el for more info." ((nth 3 state) ; A string (list (point) (nth 3 state) (nth 8 state))) ((and (nth 4 state) ; A comment - (not (eq (nth 7 state) 'syntax-table))) ; but not a psuedo comment. + (not (eq (nth 7 state) 'syntax-table))) ; but not a pseudo comment. (list (point) (if (eq (nth 7 state) 1) 'c++ 'c) (nth 8 state))) @@ -2899,7 +2907,7 @@ comment at the start of cc-engine.el for more info." (setq nc-list (cdr nc-list)))))) (defun c-semi-get-near-cache-entry (here) - ;; Return the near cache entry at the highest postion before HERE, if any, + ;; Return the near cache entry at the highest position before HERE, if any, ;; or nil. The near cache entry is of the form (POSITION . STATE), where ;; STATE has the form of a result of `parse-partial-sexp'. (let ((nc-pos-state @@ -2988,9 +2996,7 @@ comment at the start of cc-engine.el for more info." c-block-comment-awkward-chars))) (and (nth 4 s) (nth 7 s) ; Line comment (not (memq (char-before here) '(?\\ ?\n))))))) - (c-with-extended-string-fences - pos here - (setq s (parse-partial-sexp pos here nil nil s)))) + (setq s (parse-partial-sexp pos here nil nil s))) (when (not (eq near-pos here)) (c-semi-put-near-cache-entry here s)) (cond @@ -3031,7 +3037,7 @@ comment at the start of cc-engine.el for more info." (defun c-full-trim-near-cache () ;; Remove stale entries in `c-full-lit-near-cache', i.e. those whose END ;; entries, or positions, are above `c-full-near-cache-limit'. - (let ((nc-list c-full-lit-near-cache) elt) + (let ((nc-list c-full-lit-near-cache)) (while nc-list (let ((elt (car nc-list))) (if (if (car (cddr elt)) @@ -3194,6 +3200,24 @@ comment at the start of cc-engine.el for more info." c-semi-near-cache-limit (min c-semi-near-cache-limit pos) c-full-near-cache-limit (min c-full-near-cache-limit pos))) +(defun c-foreign-truncate-lit-pos-cache (beg _end) + "Truncate CC Mode's literal cache. + +This function should be added to the `before-change-functions' +hook by major modes that use CC Mode's filling functionality +without initializing CC Mode. Currently (2020-06) these are +js-mode and mhtml-mode." + (c-truncate-lit-pos-cache beg)) + +(defun c-foreign-init-lit-pos-cache () + "Initialize CC Mode's literal cache. + +This function should be called from the mode functions of major +modes which use CC Mode's filling functionality without +initializing CC Mode. Currently (2020-06) these are js-mode and +mhtml-mode." + (c-truncate-lit-pos-cache 1)) + ;; A system for finding noteworthy parens before the point. @@ -3554,18 +3578,23 @@ comment at the start of cc-engine.el for more info." ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Defuns which analyze the buffer, yet don't change `c-state-cache'. (defun c-get-fallback-scan-pos (here) - ;; Return a start position for building `c-state-cache' from - ;; scratch. This will be at the top level, 2 defuns back. + ;; Return a start position for building `c-state-cache' from scratch. This + ;; will be at the top level, 2 defuns back. Return nil if we don't find + ;; these defun starts a reasonable way back. (save-excursion - ;; Go back 2 bods, but ignore any bogus positions returned by - ;; beginning-of-defun (i.e. open paren in column zero). - (goto-char here) - (let ((cnt 2)) - (while (not (or (bobp) (zerop cnt))) - (c-beginning-of-defun-1) ; Pure elisp BOD. - (if (eq (char-after) ?\{) - (setq cnt (1- cnt))))) - (point))) + (save-restriction + (when (> here (* 10 c-state-cache-too-far)) + (narrow-to-region (- here (* 10 c-state-cache-too-far)) here)) + ;; Go back 2 bods, but ignore any bogus positions returned by + ;; beginning-of-defun (i.e. open paren in column zero). + (goto-char here) + (let ((cnt 2)) + (while (not (or (bobp) (zerop cnt))) + (c-beginning-of-defun-1) ; Pure elisp BOD. + (if (eq (char-after) ?\{) + (setq cnt (1- cnt))))) + (and (not (bobp)) + (point))))) (defun c-state-balance-parens-backwards (here- here+ top) ;; Return the position of the opening paren/brace/bracket before HERE- which @@ -3656,9 +3685,7 @@ comment at the start of cc-engine.el for more info." how-far 0)) ((<= good-pos here) (setq strategy 'forward - start-point (if changed-macro-start - cache-pos - (max good-pos cache-pos)) + start-point (max good-pos cache-pos) how-far (- here start-point))) ((< (- good-pos here) (- here cache-pos)) ; FIXME!!! ; apply some sort of weighting. (setq strategy 'backward @@ -3677,7 +3704,8 @@ comment at the start of cc-engine.el for more info." ;; (not (c-major-mode-is 'c++-mode)) (> how-far c-state-cache-too-far)) (setq BOD-pos (c-get-fallback-scan-pos here)) ; somewhat EXPENSIVE!!! - (if (< (- here BOD-pos) how-far) + (if (and BOD-pos + (< (- here BOD-pos) how-far)) (setq strategy 'BOD start-point BOD-pos))) @@ -3765,12 +3793,14 @@ comment at the start of cc-engine.el for more info." (point))) (bra ; Position of "{". ;; Don't start scanning in the middle of a CPP construct unless - ;; it contains HERE - these constructs, in Emacs, are "commented - ;; out" with category properties. - (if (eq (c-get-char-property macro-start-or-from 'category) - 'c-cpp-delimiter) - macro-start-or-from - from)) + ;; it contains HERE. + (if (and (not (eq macro-start-or-from from)) + (< macro-start-or-from here) ; Might not be needed. + (progn (goto-char macro-start-or-from) + (c-end-of-macro) + (>= (point) here))) + from + macro-start-or-from)) ce) ; Position of "}" (or upper-lim (setq upper-lim from)) @@ -4300,34 +4330,29 @@ comment at the start of cc-engine.el for more info." (setq c-state-nonlit-pos-cache-limit (1- here))) (c-truncate-lit-pos-cache here) - ;; `c-state-cache': - ;; Case 1: if `here' is in a literal containing point-min, everything - ;; becomes (or is already) nil. - (if (or (null c-state-cache-good-pos) - (< here (c-state-get-min-scan-pos))) - (setq c-state-cache nil - c-state-cache-good-pos nil - c-state-min-scan-pos nil) - - ;; Truncate `c-state-cache' and set `c-state-cache-good-pos' to a value - ;; below `here'. To maintain its consistency, we may need to insert a new - ;; brace pair. - (let ((here-bol (c-point 'bol here)) - too-high-pa ; recorded {/(/[ next above or just below here, or nil. - dropped-cons) ; was the last removed element a brace pair? - ;; The easy bit - knock over-the-top bits off `c-state-cache'. - (while (and c-state-cache - (>= (c-state-cache-top-paren) here)) - (setq dropped-cons (consp (car c-state-cache)) - too-high-pa (c-state-cache-top-lparen) - c-state-cache (cdr c-state-cache))) - - ;; Do we need to add in an earlier brace pair, having lopped one off? - (if (and dropped-cons - (<= too-high-pa here)) - (c-append-lower-brace-pair-to-state-cache too-high-pa here here-bol)) - (setq c-state-cache-good-pos (or (c-state-cache-after-top-paren) - (c-state-get-min-scan-pos))))) + (cond + ;; `c-state-cache': + ;; Case 1: if `here' is in a literal containing point-min, everything + ;; becomes (or is already) nil. + ((or (null c-state-cache-good-pos) + (< here (c-state-get-min-scan-pos))) + (setq c-state-cache nil + c-state-cache-good-pos nil + c-state-min-scan-pos nil)) + + ;; Case 2: `here' is below `c-state-cache-good-pos', so we need to amend + ;; the entire `c-state-cache' data. + ((< here c-state-cache-good-pos) + (let* ((res (c-remove-stale-state-cache-backwards here)) + (good-pos (car res)) + (scan-backward-pos (cadr res)) + (scan-forward-p (car (cddr res)))) + (if scan-backward-pos + (c-append-lower-brace-pair-to-state-cache scan-backward-pos here)) + (setq c-state-cache-good-pos + (if scan-forward-p + (c-append-to-state-cache good-pos here) + good-pos))))) ;; The brace-pair desert marker: (when (car c-state-brace-pair-desert) @@ -4785,7 +4810,7 @@ comment at the start of cc-engine.el for more info." ;; Handle the "operator +" syntax in C++. (when (and c-overloadable-operators-regexp - (= (c-backward-token-2 0) 0)) + (= (c-backward-token-2 0 nil (c-determine-limit 500)) 0)) (cond ((and (looking-at c-overloadable-operators-regexp) (or (not c-opt-op-identifier-prefix) @@ -5054,7 +5079,8 @@ See `c-forward-token-2' for details." (while (and (> count 0) (progn - (c-backward-syntactic-ws) + (c-backward-syntactic-ws + limit) (backward-char) (if (looking-at jump-syntax) (goto-char (scan-sexps (1+ (point)) -1)) @@ -5391,8 +5417,12 @@ comment at the start of cc-engine.el for more info." ;; Optimize for, in particular, large blocks of comments from ;; `comment-region'. (progn (when opt-ws - (c-backward-syntactic-ws) - (setq paren-level-pos (point))) + (let ((opt-pos (point))) + (c-backward-syntactic-ws limit) + (if (or (null limit) + (> (point) limit)) + (setq paren-level-pos (point)) + (goto-char opt-pos)))) t) ;; Move back to a candidate end point which isn't in a literal ;; or in a macro we didn't start in. @@ -5412,7 +5442,11 @@ comment at the start of cc-engine.el for more info." (setq macro-start (point)))) (goto-char macro-start)))) (when opt-ws - (c-backward-syntactic-ws))) + (let ((opt-pos (point))) + (c-backward-syntactic-ws limit) + (if (and limit + (<= (point) limit)) + (goto-char opt-pos))))) (< (point) pos)) ;; Check whether we're at the wrong level of nesting (when @@ -5463,7 +5497,7 @@ comment at the start of cc-engine.el for more info." (progn ;; Skip syntactic ws afterwards so that we don't stop at the ;; end of a comment if `skip-chars' is something like "^/". - (c-backward-syntactic-ws) + (c-backward-syntactic-ws limit) (point))))) ;; We might want to extend this with more useful return values in @@ -5751,12 +5785,23 @@ comment at the start of cc-engine.el for more info." (t 'c))) ; Assuming the range is valid. range)) +(defun c-determine-limit-no-macro (here org-start) + ;; If HERE is inside a macro, and ORG-START is not also in the same macro, + ;; return the beginning of the macro. Otherwise return HERE. Point is not + ;; preserved by this function. + (goto-char here) + (let ((here-BOM (and (c-beginning-of-macro) (point)))) + (if (and here-BOM + (not (eq (progn (goto-char org-start) + (and (c-beginning-of-macro) (point))) + here-BOM))) + here-BOM + here))) + (defsubst c-determine-limit-get-base (start try-size) ;; Get a "safe place" approximately TRY-SIZE characters before START. ;; This defsubst doesn't preserve point. (goto-char start) - (c-backward-syntactic-ws) - (setq start (point)) (let* ((pos (max (- start try-size) (point-min))) (s (c-semi-pp-to-literal pos)) (cand (or (car (cddr s)) pos))) @@ -5765,20 +5810,23 @@ comment at the start of cc-engine.el for more info." (parse-partial-sexp pos start nil nil (car s) 'syntax-table) (point)))) -(defun c-determine-limit (how-far-back &optional start try-size) +(defun c-determine-limit (how-far-back &optional start try-size org-start) ;; Return a buffer position approximately HOW-FAR-BACK non-literal ;; characters from START (default point). The starting position, either ;; point or START may not be in a comment or string. ;; ;; The position found will not be before POINT-MIN and won't be in a - ;; literal. + ;; literal. It will also not be inside a macro, unless START/point is also + ;; in the same macro. ;; ;; We start searching for the sought position TRY-SIZE (default ;; twice HOW-FAR-BACK) bytes back from START. ;; ;; This function must be fast. :-) + (save-excursion (let* ((start (or start (point))) + (org-start (or org-start start)) (try-size (or try-size (* 2 how-far-back))) (base (c-determine-limit-get-base start try-size)) (pos base) @@ -5831,21 +5879,27 @@ comment at the start of cc-engine.el for more info." (setq elt (car stack) stack (cdr stack)) (setq count (+ count (cdr elt)))) - - ;; Have we found enough yet? (cond ((null elt) ; No non-literal characters found. - (if (> base (point-min)) - (c-determine-limit how-far-back base (* 2 try-size)) - (point-min))) + (cond + ((> pos start) ; Nothing but literals + base) + ((> base (point-min)) + (c-determine-limit how-far-back base (* 2 try-size) org-start)) + (t base))) ((>= count how-far-back) - (+ (car elt) (- count how-far-back))) + (c-determine-limit-no-macro + (+ (car elt) (- count how-far-back)) + org-start)) ((eq base (point-min)) (point-min)) ((> base (- start try-size)) ; Can only happen if we hit point-min. - (car elt)) + (c-determine-limit-no-macro + (car elt) + org-start)) (t - (c-determine-limit (- how-far-back count) base (* 2 try-size))))))) + (c-determine-limit (- how-far-back count) base (* 2 try-size) + org-start)))))) (defun c-determine-+ve-limit (how-far &optional start-pos) ;; Return a buffer position about HOW-FAR non-literal characters forward @@ -6237,8 +6291,14 @@ comment at the start of cc-engine.el for more info." ;; preceding syntactic ws to set `cfd-match-pos' and to catch ;; any decl spots in the syntactic ws. (unless cfd-re-match - (c-backward-syntactic-ws) - (setq cfd-re-match (point)))) + (let ((cfd-cbsw-lim + (max (- (point) 1000) (point-min)))) + (c-backward-syntactic-ws cfd-cbsw-lim) + (setq cfd-re-match + (if (or (bobp) (> (point) cfd-cbsw-lim)) + (point) + (point-min)))) ; Set BOB case if the token's too far back. + )) ;; Choose whichever match is closer to the start. (if (< cfd-re-match cfd-prop-match) @@ -6399,7 +6459,7 @@ comment at the start of cc-engine.el for more info." (while (and (not (bobp)) (c-got-face-at (1- (point)) c-literal-faces)) (goto-char (previous-single-property-change - (point) 'face nil (point-min)))) + (point) 'face nil (point-min)))) ; No limit. FIXME, perhaps? 2020-12-07. ;; XEmacs doesn't fontify the quotes surrounding string ;; literals. @@ -6471,12 +6531,15 @@ comment at the start of cc-engine.el for more info." (c-invalidate-find-decl-cache cfd-start-pos) (setq syntactic-pos (point)) - (unless (eq syntactic-pos c-find-decl-syntactic-pos) + (unless + (eq syntactic-pos c-find-decl-syntactic-pos) ;; Don't have to do this if the cache is relevant here, ;; typically if the same line is refontified again. If ;; we're just some syntactic whitespace further down we can ;; still use the cache to limit the skipping. - (c-backward-syntactic-ws c-find-decl-syntactic-pos)) + (c-backward-syntactic-ws + (max (or c-find-decl-syntactic-pos (point-min)) + (- (point) 10000) (point-min)))) ;; If we hit `c-find-decl-syntactic-pos' and ;; `c-find-decl-match-pos' is set then we install the cached @@ -6602,7 +6665,8 @@ comment at the start of cc-engine.el for more info." ;; syntactic ws. (when (and cfd-match-pos (< cfd-match-pos syntactic-pos)) (goto-char syntactic-pos) - (c-forward-syntactic-ws) + (c-forward-syntactic-ws + (min (+ (point) 2000) (point-max))) (and cfd-continue-pos (< cfd-continue-pos (point)) (setq cfd-token-pos (point)))) @@ -6643,7 +6707,8 @@ comment at the start of cc-engine.el for more info." ;; can't be nested, and that's already been done in ;; `c-find-decl-prefix-search'. (when (> cfd-continue-pos cfd-token-pos) - (c-forward-syntactic-ws) + (c-forward-syntactic-ws + (min (+ (point) 2000) (point-max))) (setq cfd-token-pos (point))) ;; Continue if the following token fails the @@ -7159,7 +7224,7 @@ comment at the start of cc-engine.el for more info." ;; characters.) If the raw string is not terminated, E\) and E\" are set to ;; nil. ;; - ;; Note: this function is dependant upon the correct syntax-table text + ;; Note: this function is dependent upon the correct syntax-table text ;; properties being set. (let ((state (c-semi-pp-to-literal (point))) open-quote-pos open-paren-pos close-paren-pos close-quote-pos id) @@ -7614,8 +7679,7 @@ comment at the start of cc-engine.el for more info." ;; entire raw string (when properly terminated) or just the delimiter ;; (otherwise). In either of these cases, return t, otherwise return nil. ;; - (let ((here (point)) - in-macro macro-end id Rquote found) + (let (in-macro macro-end) (when (and (eq (char-before (1- (point))) ?R) @@ -8236,7 +8300,7 @@ comment at the start of cc-engine.el for more info." ;; o - nil if no name is found; ;; o - 'template if it's an identifier ending with an angle bracket ;; arglist; - ;; o - 'operator of it's an operator identifier; + ;; o - 'operator if it's an operator identifier; ;; o - t if it's some other kind of name. ;; ;; This function records identifier ranges on @@ -8252,9 +8316,11 @@ comment at the start of cc-engine.el for more info." ;; typically called from `c-forward-type' in this case, and ;; the caller only wants the top level type that it finds to ;; be promoted. - c-promote-possible-types) + c-promote-possible-types + (lim+ (c-determine-+ve-limit 500))) (while (and + (< (point) lim+) (looking-at c-identifier-key) (progn @@ -8282,7 +8348,7 @@ comment at the start of cc-engine.el for more info." ;; Handle a C++ operator or template identifier. (goto-char id-end) - (c-forward-syntactic-ws) + (c-forward-syntactic-ws lim+) (cond ((eq (char-before id-end) ?e) ;; Got "... ::template". (let ((subres (c-forward-name))) @@ -8304,23 +8370,28 @@ comment at the start of cc-engine.el for more info." ;; '*', '&' or a name followed by ":: *", ;; where each can be followed by a sequence ;; of `c-opt-type-modifier-key'. - (while (cond ((looking-at "[*&]") - (goto-char (match-end 0)) - t) - ((looking-at c-identifier-start) - (and (c-forward-name) - (looking-at "::") - (progn - (goto-char (match-end 0)) - (c-forward-syntactic-ws) - (eq (char-after) ?*)) - (progn - (forward-char) - t)))) + (while + (and + (< (point) lim+) + (cond ((looking-at "[*&]") + (goto-char (match-end 0)) + t) + ((looking-at c-identifier-start) + (and (c-forward-name) + (looking-at "::") + (progn + (goto-char (match-end 0)) + (c-forward-syntactic-ws lim+) + (eq (char-after) ?*)) + (progn + (forward-char) + t))))) (while (progn - (c-forward-syntactic-ws) + (c-forward-syntactic-ws lim+) (setq pos (point)) - (looking-at c-opt-type-modifier-key)) + (and + (<= (point) lim+) + (looking-at c-opt-type-modifier-key))) (goto-char (match-end 1)))))) ((looking-at c-overloadable-operators-regexp) @@ -8328,7 +8399,7 @@ comment at the start of cc-engine.el for more info." (setq c-last-identifier-range (cons (point) (match-end 0))) (goto-char (match-end 0)) - (c-forward-syntactic-ws) + (c-forward-syntactic-ws lim+) (setq pos (point) res 'operator))) @@ -8342,7 +8413,7 @@ comment at the start of cc-engine.el for more info." (setq c-last-identifier-range (cons id-start id-end))) (goto-char id-end) - (c-forward-syntactic-ws) + (c-forward-syntactic-ws lim+) (setq pos (point) res t))) @@ -8358,7 +8429,7 @@ comment at the start of cc-engine.el for more info." ;; cases with tricky syntactic whitespace that aren't ;; covered in `c-identifier-key'. (goto-char (match-end 0)) - (c-forward-syntactic-ws) + (c-forward-syntactic-ws lim+) t) ((and c-recognize-<>-arglists @@ -8366,8 +8437,11 @@ comment at the start of cc-engine.el for more info." ;; Maybe an angle bracket arglist. (when (let (c-last-identifier-range) (c-forward-<>-arglist nil)) + ;; <> arglists can legitimately be very long, so recalculate + ;; `lim+'. + (setq lim+ (c-determine-+ve-limit 500)) - (c-forward-syntactic-ws) + (c-forward-syntactic-ws lim+) (unless (eq (char-after) ?\() (setq c-last-identifier-range nil) (c-add-type start (1+ pos))) @@ -8382,7 +8456,7 @@ comment at the start of cc-engine.el for more info." (when (and c-record-type-identifiers id-start) (c-record-ref-id (cons id-start id-end))) (forward-char 2) - (c-forward-syntactic-ws) + (c-forward-syntactic-ws lim+) t) (when (and c-record-type-identifiers id-start @@ -8415,6 +8489,7 @@ comment at the start of cc-engine.el for more info." ;; o - 'found if it's a type that matches one in `c-found-types'; ;; o - 'maybe if it's an identifier that might be a type; ;; o - 'decltype if it's a decltype(variable) declaration; - or + ;; o - 'no-id if "auto" precluded parsing a type identifier. ;; o - nil if it can't be a type (the point isn't moved then). ;; ;; The point is assumed to be at the beginning of a token. @@ -8439,9 +8514,12 @@ comment at the start of cc-engine.el for more info." ;; prefix of a type. (when c-opt-type-modifier-prefix-key ; e.g. "const" "volatile", but NOT "typedef" (while (looking-at c-opt-type-modifier-prefix-key) + (when (looking-at c-no-type-key) + (setq res 'no-id)) (goto-char (match-end 1)) (c-forward-syntactic-ws) - (setq res 'prefix))) + (or (eq res 'no-id) + (setq res 'prefix)))) (cond ((looking-at c-typeof-key) ; e.g. C++'s "decltype". @@ -8492,28 +8570,30 @@ comment at the start of cc-engine.el for more info." (setq res t)) (unless res (goto-char start))) ; invalid syntax - ((progn - (setq pos nil) - (if (looking-at c-identifier-start) - (save-excursion - (setq id-start (point) - name-res (c-forward-name)) - (when name-res - (setq id-end (point) - id-range c-last-identifier-range)))) - (and (cond ((looking-at c-primitive-type-key) - (setq res t)) - ((c-with-syntax-table c-identifier-syntax-table - (looking-at c-known-type-key)) - (setq res 'known))) - (or (not id-end) - (>= (save-excursion - (save-match-data - (goto-char (match-end 1)) - (c-forward-syntactic-ws) - (setq pos (point)))) - id-end) - (setq res nil)))) + ((and + (not (eq res 'no-id)) + (progn + (setq pos nil) + (if (looking-at c-identifier-start) + (save-excursion + (setq id-start (point) + name-res (c-forward-name)) + (when name-res + (setq id-end (point) + id-range c-last-identifier-range)))) + (and (cond ((looking-at c-primitive-type-key) + (setq res t)) + ((c-with-syntax-table c-identifier-syntax-table + (looking-at c-known-type-key)) + (setq res 'known))) + (or (not id-end) + (>= (save-excursion + (save-match-data + (goto-char (match-end 1)) + (c-forward-syntactic-ws) + (setq pos (point)))) + id-end) + (setq res nil))))) ;; Looking at a primitive or known type identifier. We've ;; checked for a name first so that we don't go here if the ;; known type match only is a prefix of another name. @@ -8588,7 +8668,7 @@ comment at the start of cc-engine.el for more info." (goto-char start) (setq res nil))))) - (when res + (when (not (memq res '(nil no-id))) ;; Skip trailing type modifiers. If any are found we know it's ;; a type. (when c-opt-type-modifier-key @@ -8801,7 +8881,7 @@ comment at the start of cc-engine.el for more info." (or res (goto-char here)) res)) -(defmacro c-back-over-list-of-member-inits () +(defmacro c-back-over-list-of-member-inits (limit) ;; Go back over a list of elements, each looking like: ;; <symbol> (<expression>) , ;; or <symbol> {<expression>} , (with possibly a <....> expressions @@ -8810,21 +8890,21 @@ comment at the start of cc-engine.el for more info." ;; a comma. If either of <symbol> or bracketed <expression> is missing, ;; throw nil to 'level. If the terminating } or ) is unmatched, throw nil ;; to 'done. This is not a general purpose macro! - '(while (eq (char-before) ?,) + `(while (eq (char-before) ?,) (backward-char) - (c-backward-syntactic-ws) + (c-backward-syntactic-ws ,limit) (when (not (memq (char-before) '(?\) ?}))) (throw 'level nil)) (when (not (c-go-list-backward)) (throw 'done nil)) - (c-backward-syntactic-ws) + (c-backward-syntactic-ws ,limit) (while (eq (char-before) ?>) (when (not (c-backward-<>-arglist nil)) (throw 'done nil)) - (c-backward-syntactic-ws)) + (c-backward-syntactic-ws ,limit)) (when (not (c-back-over-compound-identifier)) (throw 'level nil)) - (c-backward-syntactic-ws))) + (c-backward-syntactic-ws ,limit))) (defun c-back-over-member-initializers (&optional limit) ;; Test whether we are in a C++ member initializer list, and if so, go back @@ -8843,14 +8923,14 @@ comment at the start of cc-engine.el for more info." (catch 'done (setq level-plausible (catch 'level - (c-backward-syntactic-ws) + (c-backward-syntactic-ws limit) (when (memq (char-before) '(?\) ?})) (when (not (c-go-list-backward)) (throw 'done nil)) - (c-backward-syntactic-ws)) + (c-backward-syntactic-ws limit)) (when (c-back-over-compound-identifier) - (c-backward-syntactic-ws)) - (c-back-over-list-of-member-inits) + (c-backward-syntactic-ws limit)) + (c-back-over-list-of-member-inits limit) (and (eq (char-before) ?:) (save-excursion (c-backward-token-2) @@ -8864,14 +8944,14 @@ comment at the start of cc-engine.el for more info." (setq level-plausible (catch 'level (goto-char pos) - (c-backward-syntactic-ws) + (c-backward-syntactic-ws limit) (when (not (c-back-over-compound-identifier)) (throw 'level nil)) - (c-backward-syntactic-ws) - (c-back-over-list-of-member-inits) + (c-backward-syntactic-ws limit) + (c-back-over-list-of-member-inits limit) (and (eq (char-before) ?:) (save-excursion - (c-backward-token-2) + (c-backward-token-2 nil nil limit) (not (looking-at c-:$-multichar-token-regexp))) (c-just-after-func-arglist-p))))) @@ -8952,14 +9032,15 @@ point unchanged and return nil." (c-forward-noise-clause)) ((and (looking-at c-type-decl-prefix-key) (if (and (c-major-mode-is 'c++-mode) - (match-beginning 3)) + (match-beginning 4)) ; Was 3 - 2021-01-01 ;; If the third submatch matches in C++ then ;; we're looking at an identifier that's a ;; prefix only if it specifies a member pointer. (progn (setq id-start (point)) (c-forward-name) - (if (looking-at "\\(::\\)") + (if (save-match-data + (looking-at "\\(::\\)")) ;; We only check for a trailing "::" and ;; let the "*" that should follow be ;; matched in the next round. @@ -8969,13 +9050,15 @@ point unchanged and return nil." (setq got-identifier t) nil)) t)) - (if (looking-at c-type-decl-operator-prefix-key) + (if (save-match-data + (looking-at c-type-decl-operator-prefix-key)) (setq decorated t)) (if (eq (char-after) ?\() (progn (setq paren-depth (1+ paren-depth)) (forward-char)) - (goto-char (match-end 1))) + (goto-char (or (match-end 1) + (match-end 2)))) (c-forward-syntactic-ws) t))) @@ -9119,6 +9202,12 @@ This function might do hidden buffer changes." (catch 'is-function (while (progn + (while + (cond + ((looking-at c-decl-hangon-key) + (c-forward-keyword-clause 1)) + ((looking-at c-noise-macro-with-parens-name-re) + (c-forward-noise-clause)))) (if (eq (char-after) ?\)) (throw 'is-function t)) (setq cdd-got-type (c-forward-type)) @@ -9354,8 +9443,8 @@ This function might do hidden buffer changes." maybe-typeless ;; Save the value of kwd-sym between loops of the "Check for a ;; type" loop. Needed to distinguish a C++11 "auto" from a pre - ;; C++11 one. - prev-kwd-sym + ;; C++11 one. (Commented out, 2020-11-01). + ;; prev-kwd-sym ;; If a specifier is found that also can be a type prefix, ;; these flags are set instead of those above. If we need to ;; back up an identifier, they are copied to the real flag @@ -9435,12 +9524,11 @@ This function might do hidden buffer changes." (when (setq found-type (c-forward-type t)) ; brace-block-too ;; Found a known or possible type or a prefix of a known type. - (when (and (c-major-mode-is 'c++-mode) ; C++11 style "auto"? - (eq prev-kwd-sym (c-keyword-sym "auto")) - (looking-at "[=(]")) ; FIXME!!! proper regexp. - (setq new-style-auto t) - (setq found-type nil) - (goto-char start)) ; position of foo in "auto foo" + (when (and (eq found-type 'no-id) + (save-excursion + (and (c-forward-name) ; over the identifier + (looking-at "[=(]")))) ; FIXME!!! proper regexp. + (setq new-style-auto t)) ; position of foo in "auto foo" (when at-type ;; Got two identifiers with nothing but whitespace @@ -9515,7 +9603,7 @@ This function might do hidden buffer changes." ;; specifier keyword and we know we're in a ;; declaration. (setq at-decl-or-cast t) - (setq prev-kwd-sym kwd-sym) + ;; (setq prev-kwd-sym kwd-sym) (goto-char kwd-clause-end)))) @@ -9523,7 +9611,7 @@ This function might do hidden buffer changes." ;; over all specifiers and type identifiers. The reason ;; to do this for a known type prefix is to make things ;; like "unsigned INT16" work. - (and found-type (not (eq found-type t)))))) + (and found-type (not (memq found-type '(t no-id))))))) (cond ((eq at-type t) @@ -9543,6 +9631,10 @@ This function might do hidden buffer changes." ;; followed by another type. (setq at-type t)) + ((eq at-type 'no-id) + ;; For an auto type, we assume we definitely have a type construct. + (setq at-type t)) + ((not at-type) ;; Got no type but set things up to continue anyway to handle ;; the various cases when a declaration doesn't start with a @@ -9643,14 +9735,15 @@ This function might do hidden buffer changes." (setq after-paren-pos (point)))) (while (and (looking-at c-type-decl-prefix-key) (if (and (c-major-mode-is 'c++-mode) - (match-beginning 3)) - ;; If the third submatch matches in C++ then + (match-beginning 4)) + ;; If the fourth submatch matches in C++ then ;; we're looking at an identifier that's a ;; prefix only if it specifies a member pointer. (when (progn (setq pos (point)) (setq got-identifier (c-forward-name))) (setq name-start pos) - (if (looking-at "\\(::\\)") + (if (save-match-data + (looking-at "\\(::\\)")) ;; We only check for a trailing "::" and ;; let the "*" that should follow be ;; matched in the next round. @@ -9671,7 +9764,8 @@ This function might do hidden buffer changes." (when (save-match-data (looking-at c-type-decl-operator-prefix-key)) (setq got-function-name-prefix t)) - (goto-char (match-end 1))) + (goto-char (or (match-end 1) + (match-end 2)))) (c-forward-syntactic-ws))) (setq got-parens (> paren-depth 0)) @@ -9771,6 +9865,16 @@ This function might do hidden buffer changes." (save-excursion (goto-char after-paren-pos) (c-forward-syntactic-ws) + (progn + (while + (cond + ((and + c-opt-cpp-prefix + (looking-at c-noise-macro-with-parens-name-re)) + (c-forward-noise-clause)) + ((looking-at c-decl-hangon-key) + (c-forward-keyword-clause 1)))) + t) (or (c-forward-type) ;; Recognize a top-level typeless ;; function declaration in C. @@ -10802,11 +10906,11 @@ comment at the start of cc-engine.el for more info." (low-lim (max (or lim (point-min)) (or macro-start (point-min)))) before-lparen after-rparen (here (point)) - (pp-count-out 20) ; Max number of paren/brace constructs before - ; we give up. + (pp-count-out 20) ; Max number of paren/brace constructs before + ; we give up ids ; List of identifiers in the parenthesized list. - id-start after-prec-token decl-or-cast decl-res - c-last-identifier-range identifier-ok) + id-start after-prec-token decl-or-cast + c-last-identifier-range semi-position+1) (narrow-to-region low-lim (or macro-end (point-max))) ;; Search backwards for the defun's argument list. We give up if we @@ -10840,8 +10944,8 @@ comment at the start of cc-engine.el for more info." (setq after-rparen (point))) ((eq (char-before) ?\]) (setq after-rparen nil)) - (t ; either } (hit previous defun) or = or no more - ; parens/brackets. + (t ; either } (hit previous defun) or = or no more + ; parens/brackets. (throw 'knr nil))) (if after-rparen @@ -10898,31 +11002,35 @@ comment at the start of cc-engine.el for more info." (forward-char) ; over the ) (setq after-prec-token after-rparen) (c-forward-syntactic-ws) + ;; Each time around the following checks one + ;; declaration (which may contain several identifiers). (while (and - (or (consp (setq decl-or-cast - (c-forward-decl-or-cast-1 - after-prec-token - nil ; Or 'arglist ??? - nil))) - (progn - (goto-char after-prec-token) - (c-forward-syntactic-ws) - (setq identifier-ok (eq (char-after) ?{)) - nil)) - (eq (char-after) ?\;) - (setq after-prec-token (1+ (point))) + (consp (setq decl-or-cast + (c-forward-decl-or-cast-1 + after-prec-token + nil ; Or 'arglist ??? + nil))) + (memq (char-after) '(?\; ?\,)) (goto-char (car decl-or-cast)) - (setq decl-res (c-forward-declarator)) - (setq identifier-ok - (member (buffer-substring-no-properties - (car decl-res) (cadr decl-res)) - ids)) - (progn - (goto-char after-prec-token) - (prog1 (< (point) here) - (c-forward-syntactic-ws)))) - (setq identifier-ok nil)) - identifier-ok)) + (save-excursion + (setq semi-position+1 + (c-syntactic-re-search-forward + ";" (+ (point) 1000) t))) + (c-do-declarators + semi-position+1 t nil nil + (lambda (id-start id-end _next _not-top + _func _init) + (if (not (member + (buffer-substring-no-properties + id-start id-end) + ids)) + (throw 'knr nil)))) + + (progn (forward-char) + (<= (point) here)) + (progn (c-forward-syntactic-ws) + t))) + t)) ;; ...Yes. We've identified the function's argument list. (throw 'knr (progn (goto-char after-rparen) @@ -11088,6 +11196,7 @@ comment at the start of cc-engine.el for more info." (c-backward-syntactic-ws lim) (not (or (memq (char-before) '(?\; ?} ?: nil)) (c-at-vsemi-p)))) + (not (and lim (<= (point) lim))) (save-excursion (backward-char) (not (looking-at "\\s("))) @@ -11216,7 +11325,7 @@ comment at the start of cc-engine.el for more info." (c-syntactic-re-search-forward ";" nil 'move t))) nil))) -(defun c-looking-at-decl-block (_containing-sexp goto-start &optional limit) +(defun c-looking-at-decl-block (goto-start &optional limit) ;; Assuming the point is at an open brace, check if it starts a ;; block that contains another declaration level, i.e. that isn't a ;; statement block or a brace list, and if so return non-nil. @@ -11321,7 +11430,9 @@ comment at the start of cc-engine.el for more info." ;; also might be part of a declarator expression. Currently ;; there's no such language. (not (or (looking-at c-symbol-start) - (looking-at c-type-decl-prefix-key)))))) + (looking-at c-type-decl-prefix-key) + (and (eq (char-after) ?{) + (not (c-looking-at-statement-block)))))))) ;; In Pike a list of modifiers may be followed by a brace ;; to make them apply to many identifiers. Note that the @@ -11396,9 +11507,7 @@ comment at the start of cc-engine.el for more info." ; *c-looking-at-decl-block ; containing-sexp goto-start &optional ; limit) - (when (and (c-looking-at-decl-block - (c-pull-open-brace paren-state) - nil) + (when (and (c-looking-at-decl-block nil) (looking-at c-class-key)) (goto-char (match-end 1)) (c-forward-syntactic-ws) @@ -11417,9 +11526,7 @@ comment at the start of cc-engine.el for more info." (save-excursion (goto-char open-paren-pos) (when (and (eq (char-after) ?{) - (c-looking-at-decl-block - (c-safe-position open-paren-pos paren-state) - nil)) + (c-looking-at-decl-block nil)) (back-to-indentation) (vector (point) open-paren-pos)))))) @@ -11432,7 +11539,7 @@ comment at the start of cc-engine.el for more info." (while (and open-brace (save-excursion (goto-char open-brace) - (not (c-looking-at-decl-block next-open-brace nil)))) + (not (c-looking-at-decl-block nil)))) (setq open-brace next-open-brace next-open-brace (c-pull-open-brace paren-state))) open-brace)) @@ -11530,6 +11637,194 @@ comment at the start of cc-engine.el for more info." (or (looking-at c-brace-list-key) (progn (goto-char here) nil)))) +(defun c-laomib-loop (lim) + ;; The "expensive" loop from `c-looking-at-or-maybe-in-bracelist'. Move + ;; backwards over comma separated sexps as far as possible, but no further + ;; than LIM, which may be nil, meaning no limit. Return the final value of + ;; `braceassignp', which is t if we encountered "= {", usually nil + ;; otherwise. + (let ((braceassignp 'dontknow) + (class-key + ;; Pike can have class definitions anywhere, so we must + ;; check for the class key here. + (and (c-major-mode-is 'pike-mode) + c-decl-block-key))) + (while (eq braceassignp 'dontknow) + (cond ((eq (char-after) ?\;) + (setq braceassignp nil)) + ((and class-key + (looking-at class-key)) + (setq braceassignp nil)) + ((and c-has-compound-literals + (looking-at c-return-key)) + (setq braceassignp t) + nil) + ((eq (char-after) ?=) + ;; We've seen a =, but must check earlier tokens so + ;; that it isn't something that should be ignored. + (setq braceassignp 'maybe) + (while (and (eq braceassignp 'maybe) + (zerop (c-backward-token-2 1 t lim))) + (setq braceassignp + (cond + ;; Check for operator = + ((and c-opt-op-identifier-prefix + (looking-at c-opt-op-identifier-prefix)) + nil) + ;; Check for `<opchar>= in Pike. + ((and (c-major-mode-is 'pike-mode) + (or (eq (char-after) ?`) + ;; Special case for Pikes + ;; `[]=, since '[' is not in + ;; the punctuation class. + (and (eq (char-after) ?\[) + (eq (char-before) ?`)))) + nil) + ((looking-at "\\s.") 'maybe) + ;; make sure we're not in a C++ template + ;; argument assignment + ((and + (c-major-mode-is 'c++-mode) + (save-excursion + (let ((here (point)) + (pos< (progn + (skip-chars-backward "^<>") + (point)))) + (and (eq (char-before) ?<) + (not (c-crosses-statement-barrier-p + pos< here)) + (not (c-in-literal)) + )))) + nil) + (t t))))) + ((and + (c-major-mode-is 'c++-mode) + (eq (char-after) ?\[) + ;; Be careful of "operator []" + (not (save-excursion + (c-backward-token-2 1 nil lim) + (looking-at c-opt-op-identifier-prefix)))) + (setq braceassignp t) + nil)) + (when (eq braceassignp 'dontknow) + (cond ((and + (not (eq (char-after) ?,)) + (save-excursion + (c-backward-syntactic-ws) + (eq (char-before) ?}))) + (setq braceassignp nil)) + ((/= (c-backward-token-2 1 t lim) 0) + (if (save-excursion + (and c-has-compound-literals + (eq (c-backward-token-2 1 nil lim) 0) + (eq (char-after) ?\())) + (setq braceassignp t) + (setq braceassignp nil)))))) + braceassignp)) + +;; The following variable is a cache of up to four entries, each entry of +;; which is a list representing a call to c-laomib-loop. It contains the +;; following elements: +;; 0: `lim' argument - used as an alist key, never nil. +;; 1: Position in buffer where the scan started. +;; 2: Position in buffer where the scan ended. +;; 3: Result of the call to `c-laomib-loop'. +(defvar c-laomib-cache nil) +(make-variable-buffer-local 'c-laomib-cache) + +(defun c-laomib-get-cache (containing-sexp) + ;; Get an element from `c-laomib-cache' matching CONTAINING-SEXP. + ;; Return that element or nil if one wasn't found. + (let ((elt (assq containing-sexp c-laomib-cache))) + (when elt + ;; Move the fetched `elt' to the front of the cache. + (setq c-laomib-cache (delq elt c-laomib-cache)) + (push elt c-laomib-cache) + elt))) + +(defun c-laomib-put-cache (lim start end result) + ;; Insert a new element into `c-laomib-cache', removing another element to + ;; make room, if necessary. The four parameters LIM, START, END, RESULT are + ;; the components of the new element (see comment for `c-laomib-cache'). + ;; The return value is of no significance. + (when lim + (let ((old-elt (assq lim c-laomib-cache)) + ;; (elt (cons containing-sexp (cons start nil))) + (new-elt (list lim start end result)) + big-ptr + (cur-ptr c-laomib-cache) + togo (size 0) cur-size + ) + (if old-elt (setq c-laomib-cache (delq old-elt c-laomib-cache))) + + (while (>= (length c-laomib-cache) 4) + ;; We delete the least recently used elt which doesn't enclose START, + ;; or.. + (dolist (elt c-laomib-cache) + (if (or (<= start (cadr elt)) + (> start (car (cddr elt)))) + (setq togo elt))) + + ;; ... delete the least recently used elt which isn't the biggest. + (when (not togo) + (while (cdr cur-ptr) + (setq cur-size (- (nth 2 (cadr cur-ptr)) (car (cadr cur-ptr)))) + (when (> cur-size size) + (setq size cur-size + big-ptr cur-ptr)) + (setq cur-ptr (cdr cur-ptr))) + (setq togo (if (cddr big-ptr) + (car (last big-ptr)) + (car big-ptr)))) + + (setq c-laomib-cache (delq togo c-laomib-cache))) + + (push new-elt c-laomib-cache)))) + +(defun c-laomib-fix-elt (lwm elt paren-state) + ;; Correct a c-laomib-cache entry ELT with respect to buffer changes, either + ;; doing nothing, signalling it is to be deleted, or replacing its start + ;; point with one lower in the buffer than LWM. PAREN-STATE is the paren + ;; state at LWM. Return the corrected entry, or nil (if it needs deleting). + ;; Note that corrections are made by `setcar'ing the original structure, + ;; which thus remains intact. + (cond + ((or (not lwm) (> lwm (cadr elt))) + elt) + ((<= lwm (nth 2 elt)) + nil) + (t + ;; Search for the last brace in `paren-state' before (car `lim'). This + ;; brace will become our new 2nd element of `elt'. + (while + ;; Search one brace level per iteration. + (and paren-state + (progn + ;; (setq cur-brace (c-laomib-next-BRACE paren-state)) + (while + ;; Go past non-brace levels, one per iteration. + (and paren-state + (not (eq (char-after + (c-state-cache-top-lparen paren-state)) + ?{))) + (setq paren-state (cdr paren-state))) + (cadr paren-state)) + (> (c-state-cache-top-lparen (cdr paren-state)) (car elt))) + (setq paren-state (cdr paren-state))) + (when (cadr paren-state) + (setcar (cdr elt) (c-state-cache-top-lparen paren-state)) + elt)))) + +(defun c-laomib-invalidate-cache (beg _end) + ;; Called from late in c-before-change. Amend `c-laomib-cache' to remove + ;; details pertaining to the buffer after position BEG. + (save-excursion + (goto-char beg) + (let ((paren-state (c-parse-state))) + (dolist (elt c-laomib-cache) + (when (not (c-laomib-fix-elt beg elt paren-state)) + (setq c-laomib-cache (delq elt c-laomib-cache))))))) + (defun c-looking-at-or-maybe-in-bracelist (&optional containing-sexp lim) ;; Point is at an open brace. If this starts a brace list, return a list ;; whose car is the buffer position of the start of the construct which @@ -11544,20 +11839,18 @@ comment at the start of cc-engine.el for more info." ;; POINT, or nil if there is no such position, or we do not know it. LIM is ;; a backward search limit. ;; - ;; The determination of whether the brace starts a brace list is solely by - ;; the context of the brace, not by its contents. + ;; The determination of whether the brace starts a brace list is mainly by + ;; the context of the brace, not by its contents. In exceptional + ;; circumstances (e.g. "struct A {" in C++ Mode), the contents are examined, + ;; too. ;; ;; Here, "brace list" does not include the body of an enum. (save-excursion (let ((start (point)) - (class-key - ;; Pike can have class definitions anywhere, so we must - ;; check for the class key here. - (and (c-major-mode-is 'pike-mode) - c-decl-block-key)) (braceassignp 'dontknow) inexpr-brace-list bufpos macro-start res pos after-type-id-pos - in-paren parens-before-brace) + pos2 in-paren parens-before-brace + paren-state paren-pos) (setq res (c-backward-token-2 1 t lim)) ;; Checks to do only on the first sexp before the brace. @@ -11566,16 +11859,22 @@ comment at the start of cc-engine.el for more info." (cond ((and (or (not (eq res 0)) (eq (char-after) ?,)) - (c-go-up-list-backward nil lim) ; FIXME!!! Check ; `lim' 2016-07-12. - (eq (char-after) ?\()) + (setq paren-state (c-parse-state)) + (setq paren-pos (c-pull-open-brace paren-state)) + (eq (char-after paren-pos) ?\()) + (goto-char paren-pos) (setq braceassignp 'c++-noassign in-paren 'in-paren)) - ((looking-at c-pre-id-bracelist-key) + ((looking-at c-pre-brace-non-bracelist-key) (setq braceassignp nil)) ((looking-at c-return-key)) ((and (looking-at c-symbol-start) (not (looking-at c-keywords-regexp))) - (setq after-type-id-pos (point))) + (if (save-excursion + (and (zerop (c-backward-token-2 1 t lim)) + (looking-at c-pre-id-bracelist-key))) + (setq braceassignp 'c++-noassign) + (setq after-type-id-pos (point)))) ((eq (char-after) ?\() (setq parens-before-brace t) nil) @@ -11584,11 +11883,18 @@ comment at the start of cc-engine.el for more info." (cond ((or (not (eq res 0)) (eq (char-after) ?,)) - (and (c-go-up-list-backward nil lim) ; FIXME!!! Check `lim' 2016-07-12. - (eq (char-after) ?\() - (setq in-paren 'in-paren))) - ((looking-at c-pre-id-bracelist-key)) + (and (setq paren-state (c-parse-state)) + (setq paren-pos (c-pull-open-brace paren-state)) + (eq (char-after paren-pos) ?\() + (setq in-paren 'in-paren) + (goto-char paren-pos))) + ((looking-at c-pre-brace-non-bracelist-key)) ((looking-at c-return-key)) + ((and (looking-at c-symbol-start) + (not (looking-at c-keywords-regexp)) + (save-excursion + (and (zerop (c-backward-token-2 1 t lim)) + (looking-at c-pre-id-bracelist-key))))) (t (setq after-type-id-pos (point)) nil)))) (setq braceassignp 'c++-noassign)) @@ -11639,76 +11945,46 @@ comment at the start of cc-engine.el for more info." (t (goto-char pos) - ;; Checks to do on all sexps before the brace, up to the - ;; beginning of the statement. - (while (eq braceassignp 'dontknow) - (cond ((eq (char-after) ?\;) - (setq braceassignp nil)) - ((and class-key - (looking-at class-key)) - (setq braceassignp nil)) - ((and c-has-compound-literals - (looking-at c-return-key)) - (setq braceassignp t) - nil) - ((eq (char-after) ?=) - ;; We've seen a =, but must check earlier tokens so - ;; that it isn't something that should be ignored. - (setq braceassignp 'maybe) - (while (and (eq braceassignp 'maybe) - (zerop (c-backward-token-2 1 t lim))) - (setq braceassignp - (cond - ;; Check for operator = - ((and c-opt-op-identifier-prefix - (looking-at c-opt-op-identifier-prefix)) - nil) - ;; Check for `<opchar>= in Pike. - ((and (c-major-mode-is 'pike-mode) - (or (eq (char-after) ?`) - ;; Special case for Pikes - ;; `[]=, since '[' is not in - ;; the punctuation class. - (and (eq (char-after) ?\[) - (eq (char-before) ?`)))) - nil) - ((looking-at "\\s.") 'maybe) - ;; make sure we're not in a C++ template - ;; argument assignment - ((and - (c-major-mode-is 'c++-mode) - (save-excursion - (let ((here (point)) - (pos< (progn - (skip-chars-backward "^<>") - (point)))) - (and (eq (char-before) ?<) - (not (c-crosses-statement-barrier-p - pos< here)) - (not (c-in-literal)) - )))) - nil) - (t t)))))) - (when (eq braceassignp 'dontknow) - (cond ((and - (not (eq (char-after) ?,)) - (save-excursion - (c-backward-syntactic-ws) - (eq (char-before) ?}))) - (setq braceassignp nil)) - ((/= (c-backward-token-2 1 t lim) 0) - (if (save-excursion - (and c-has-compound-literals - (eq (c-backward-token-2 1 nil lim) 0) - (eq (char-after) ?\())) - (setq braceassignp t) - (setq braceassignp nil)))))) + (when (eq braceassignp 'dontknow) + (let* ((cache-entry (and containing-sexp + (c-laomib-get-cache containing-sexp))) + (lim2 (or (cadr cache-entry) lim)) + sub-bassign-p) + (if cache-entry + (cond + ((<= (point) (cadr cache-entry)) + ;; We're inside the region we've already scanned over, so + ;; just go to that scan's end position. + (goto-char (nth 2 cache-entry)) + (setq braceassignp (nth 3 cache-entry))) + ((> (point) (cadr cache-entry)) + ;; We're beyond the previous scan region, so just scan as + ;; far as the end of that region. + (setq sub-bassign-p (c-laomib-loop lim2)) + (if (<= (point) (cadr cache-entry)) + (progn + (c-laomib-put-cache containing-sexp + start (nth 2 cache-entry) + (nth 3 cache-entry) ;; sub-bassign-p + ) + (setq braceassignp (nth 3 cache-entry)) + (goto-char (nth 2 cache-entry))) + (setq braceassignp sub-bassign-p))) + (t)) + + (setq braceassignp (c-laomib-loop lim)) + (when lim + (c-laomib-put-cache lim start (point) braceassignp))))) (cond (braceassignp ;; We've hit the beginning of the aggregate list. - (c-beginning-of-statement-1 containing-sexp) - (cons (point) (or in-paren inexpr-brace-list))) + (setq pos2 (point)) + (cons + (if (eq (c-beginning-of-statement-1 containing-sexp) 'same) + (point) + pos2) + (or in-paren inexpr-brace-list))) ((and after-type-id-pos (save-excursion (when (eq (char-after) ?\;) @@ -11720,34 +11996,36 @@ comment at the start of cc-engine.el for more info." (c-get-char-property (point) 'syntax-table)) (c-go-list-forward nil after-type-id-pos) (c-forward-syntactic-ws))) - (and - (or (not (looking-at c-class-key)) - (save-excursion - (goto-char (match-end 1)) - (c-forward-syntactic-ws) - (not (eq (point) after-type-id-pos)))) - (progn - (setq res - (c-forward-decl-or-cast-1 - (save-excursion (c-backward-syntactic-ws) (point)) - nil nil)) - (and (consp res) - (cond - ((eq (car res) after-type-id-pos)) - ((> (car res) after-type-id-pos) nil) - (t - (catch 'find-decl - (save-excursion - (goto-char (car res)) - (c-do-declarators - (point-max) t nil nil - (lambda (id-start id-end tok not-top func init) - (cond - ((> id-start after-type-id-pos) - (throw 'find-decl nil)) - ((eq id-start after-type-id-pos) - (throw 'find-decl t))))) - nil))))))))) + (if (and (not (eq (point) after-type-id-pos)) + (or (not (looking-at c-class-key)) + (save-excursion + (goto-char (match-end 1)) + (c-forward-syntactic-ws) + (not (eq (point) after-type-id-pos))))) + (progn + (setq res + (c-forward-decl-or-cast-1 (c-point 'bosws) + nil nil)) + (and (consp res) + (cond + ((eq (car res) after-type-id-pos)) + ((> (car res) after-type-id-pos) nil) + (t + (catch 'find-decl + (save-excursion + (goto-char (car res)) + (c-do-declarators + (point-max) t nil nil + (lambda (id-start _id-end _tok _not-top _func _init) + (cond + ((> id-start after-type-id-pos) + (throw 'find-decl nil)) + ((eq id-start after-type-id-pos) + (throw 'find-decl t))))) + nil)))))) + (save-excursion + (goto-char start) + (not (c-looking-at-statement-block)))))) (cons bufpos (or in-paren inexpr-brace-list))) ((or (eq (char-after) ?\;) ;; Brace lists can't contain a semicolon, so we're done. @@ -11831,7 +12109,7 @@ comment at the start of cc-engine.el for more info." (or accept-in-paren (not (eq (cdr bufpos) 'in-paren))) (car bufpos)))))) -(defun c-looking-at-special-brace-list (&optional _lim) +(defun c-looking-at-special-brace-list () ;; If we're looking at the start of a pike-style list, i.e., `({Â })', ;; `([Â ])', `(<Â >)', etc., a cons of a cons of its starting and ending ;; positions and its entry in c-special-brace-lists is returned, nil @@ -11894,47 +12172,34 @@ comment at the start of cc-engine.el for more info." (cons (list beg) type))))) (error nil)))) -(defun c-looking-at-bos (&optional _lim) - ;; Return non-nil if between two statements or declarations, assuming - ;; point is not inside a literal or comment. - ;; - ;; Obsolete - `c-at-statement-start-p' or `c-at-expression-start-p' - ;; are recommended instead. - ;; - ;; This function might do hidden buffer changes. - (c-at-statement-start-p)) -(make-obsolete 'c-looking-at-bos 'c-at-statement-start-p "22.1") - (defun c-looking-at-statement-block () ;; Point is at an opening brace. If this is a statement block (i.e. the ;; elements in the block are terminated by semicolons, or the block is - ;; empty, or the block contains a keyword) return non-nil. Otherwise, - ;; return nil. + ;; empty, or the block contains a characteristic keyword, or there is a + ;; nested statement block) return non-nil. Otherwise, return nil. (let ((here (point))) (prog1 (if (c-go-list-forward) (let ((there (point))) (backward-char) - (c-syntactic-skip-backward "^;," here t) + (c-syntactic-skip-backward "^;" here t) (cond - ((eq (char-before) ?\;) t) - ((eq (char-before) ?,) nil) - (t ; We're at (1+ here). - (cond - ((progn (c-forward-syntactic-ws) - (eq (point) (1- there)))) - ((c-syntactic-re-search-forward c-keywords-regexp there t)) - ((c-syntactic-re-search-forward "{" there t t) - (backward-char) - (c-looking-at-statement-block)) - (t nil))))) + ((eq (char-before) ?\;)) + ((progn (c-forward-syntactic-ws) + (eq (point) (1- there)))) + ((c-syntactic-re-search-forward + c-stmt-block-only-keywords-regexp there t)) + ((c-syntactic-re-search-forward "{" there t t) + (backward-char) + (c-looking-at-statement-block)) + (t nil))) (forward-char) (cond - ((c-syntactic-re-search-forward "[;,]" nil t t) - (eq (char-before) ?\;)) + ((c-syntactic-re-search-forward ";" nil t t)) ((progn (c-forward-syntactic-ws) (eobp))) - ((c-syntactic-re-search-forward c-keywords-regexp nil t t)) + ((c-syntactic-re-search-forward c-stmt-block-only-keywords-regexp + nil t t)) ((c-syntactic-re-search-forward "{" nil t t) (backward-char) (c-looking-at-statement-block)) @@ -11983,7 +12248,7 @@ comment at the start of cc-engine.el for more info." (goto-char haskell-op-pos)) (while (and (eq res 'maybe) - (progn (c-backward-syntactic-ws) + (progn (c-backward-syntactic-ws lim) (> (point) closest-lim)) (not (bobp)) (progn (backward-char) @@ -12075,7 +12340,7 @@ comment at the start of cc-engine.el for more info." (c-backward-token-2 1 nil lim) (and (not (and (c-on-identifier) - (looking-at c-symbol-chars))) + (looking-at c-symbol-char-key))) (not (looking-at c-opt-op-identifier-prefix))))))) (cons 'inlambda bracket-pos)) ((and c-recognize-paren-inexpr-blocks @@ -12472,8 +12737,7 @@ comment at the start of cc-engine.el for more info." (defun c-add-class-syntax (symbol containing-decl-open containing-decl-start - containing-decl-kwd - _paren-state) + containing-decl-kwd) ;; The inclass and class-close syntactic symbols are added in ;; several places and some work is needed to fix everything. ;; Therefore it's collected here. @@ -12522,7 +12786,7 @@ comment at the start of cc-engine.el for more info." ;; CASE B.1: class-open ((save-excursion (and (eq (char-after) ?{) - (c-looking-at-decl-block containing-sexp t) + (c-looking-at-decl-block t) (setq beg-of-same-or-containing-stmt (point)))) (c-add-syntax 'class-open beg-of-same-or-containing-stmt)) @@ -12689,7 +12953,7 @@ comment at the start of cc-engine.el for more info." literal char-before-ip before-ws-ip char-after-ip macro-start in-macro-expr c-syntactic-context placeholder step-type tmpsymbol keyword injava-inher special-brace-list tmp-pos - containing-< + tmp-pos2 containing-< ;; The following record some positions for the containing ;; declaration block if we're directly within one: ;; `containing-decl-open' is the position of the open @@ -12725,10 +12989,7 @@ comment at the start of cc-engine.el for more info." (goto-char containing-sexp) (eq (char-after) ?{)) (setq placeholder - (c-looking-at-decl-block - (c-most-enclosing-brace paren-state - containing-sexp) - t))) + (c-looking-at-decl-block t))) (setq containing-decl-open containing-sexp containing-decl-start (point) containing-sexp nil) @@ -12758,7 +13019,7 @@ comment at the start of cc-engine.el for more info." (setq paren-state (cons containing-sexp paren-state) containing-sexp nil))) (setq lim (1+ containing-sexp)))) - (setq lim (point-min))) + (setq lim (c-determine-limit 1000))) ;; If we're in a parenthesis list then ',' delimits the ;; "statements" rather than being an operator (with the @@ -12970,8 +13231,7 @@ comment at the start of cc-engine.el for more info." (setq placeholder (c-add-class-syntax 'inclass containing-decl-open containing-decl-start - containing-decl-kwd - paren-state)) + containing-decl-kwd)) ;; Append access-label with the same anchor point as ;; inclass gets. (c-append-syntax 'access-label placeholder)) @@ -13001,7 +13261,9 @@ comment at the start of cc-engine.el for more info." ;; CASE 4: In-expression statement. C.f. cases 7B, 16A and ;; 17E. ((setq placeholder (c-looking-at-inexpr-block - (c-safe-position containing-sexp paren-state) + (or + (c-safe-position containing-sexp paren-state) + (c-determine-limit 1000 containing-sexp)) containing-sexp ;; Have to turn on the heuristics after ;; the point even though it doesn't work @@ -13043,7 +13305,7 @@ comment at the start of cc-engine.el for more info." ((save-excursion (let (tmp) (and (eq char-after-ip ?{) - (setq tmp (c-looking-at-decl-block containing-sexp t)) + (setq tmp (c-looking-at-decl-block t)) (progn (setq placeholder (point)) (goto-char tmp) @@ -13064,7 +13326,7 @@ comment at the start of cc-engine.el for more info." (goto-char indent-point) (skip-chars-forward " \t") (and (eq (char-after) ?{) - (c-looking-at-decl-block containing-sexp t) + (c-looking-at-decl-block t) (setq placeholder (point)))) (c-add-syntax 'class-open placeholder)) @@ -13104,8 +13366,7 @@ comment at the start of cc-engine.el for more info." (c-add-class-syntax 'inclass containing-decl-open containing-decl-start - containing-decl-kwd - paren-state)) + containing-decl-kwd)) ;; CASE 5A.5: ordinary defun open (t @@ -13127,7 +13388,8 @@ comment at the start of cc-engine.el for more info." ;; init lists can, in practice, be very large. ((save-excursion (when (and (c-major-mode-is 'c++-mode) - (setq placeholder (c-back-over-member-initializers))) + (setq placeholder (c-back-over-member-initializers + lim))) (setq tmp-pos (point)))) (if (= (c-point 'bosws) (1+ tmp-pos)) (progn @@ -13168,8 +13430,7 @@ comment at the start of cc-engine.el for more info." (c-add-class-syntax 'inclass containing-decl-open containing-decl-start - containing-decl-kwd - paren-state))) + containing-decl-kwd))) ;; CASE 5B.4: Nether region after a C++ or Java func ;; decl, which could include a `throws' declaration. @@ -13239,8 +13500,7 @@ comment at the start of cc-engine.el for more info." (c-add-class-syntax 'inclass containing-decl-open containing-decl-start - containing-decl-kwd - paren-state))) + containing-decl-kwd))) ;; CASE 5C.3: in a Java implements/extends (injava-inher @@ -13426,8 +13686,7 @@ comment at the start of cc-engine.el for more info." (c-add-class-syntax 'class-close containing-decl-open containing-decl-start - containing-decl-kwd - paren-state)) + containing-decl-kwd)) ;; CASE 5H: we could be looking at subsequent knr-argdecls ((and c-recognize-knr-p @@ -13449,7 +13708,7 @@ comment at the start of cc-engine.el for more info." ;; CASE 5I: ObjC method definition. ((and c-opt-method-key (looking-at c-opt-method-key)) - (c-beginning-of-statement-1 nil t) + (c-beginning-of-statement-1 (c-determine-limit 1000) t) (if (= (point) indent-point) ;; Handle the case when it's the first (non-comment) ;; thing in the buffer. Can't look for a 'same return @@ -13522,7 +13781,16 @@ comment at the start of cc-engine.el for more info." (if (>= (point) indent-point) (throw 'not-in-directive t)) (setq placeholder (point))) - nil))))) + nil)) + (and macro-start + (not (c-beginning-of-statement-1 lim nil nil nil t)) + (setq placeholder + (let ((ps-top (car paren-state))) + (if (consp ps-top) + (progn + (goto-char (cdr ps-top)) + (c-forward-syntactic-ws indent-point)) + (point-min)))))))) ;; For historic reasons we anchor at bol of the last ;; line of the previous declaration. That's clearly ;; highly bogus and useless, and it makes our lives hard @@ -13548,8 +13816,7 @@ comment at the start of cc-engine.el for more info." (c-add-class-syntax 'inclass containing-decl-open containing-decl-start - containing-decl-kwd - paren-state))) + containing-decl-kwd))) (when (and c-syntactic-indentation-in-macros macro-start (/= macro-start (c-point 'boi indent-point))) @@ -13572,31 +13839,47 @@ comment at the start of cc-engine.el for more info." (eq (char-before) ?<) (not (and c-overloadable-operators-regexp (c-after-special-operator-id lim)))) - (c-beginning-of-statement-1 (c-safe-position (point) paren-state)) + (c-beginning-of-statement-1 + (or + (c-safe-position (point) paren-state) + (c-determine-limit 1000))) (c-add-syntax 'template-args-cont (c-point 'boi))) ;; CASE 5Q: we are at a statement within a macro. - (macro-start - (c-beginning-of-statement-1 containing-sexp) + ((and + macro-start + (save-excursion + (prog1 + (not (eq (c-beginning-of-statement-1 + (or containing-sexp (c-determine-limit 1000)) + nil nil nil t) + nil))) + (setq placeholder (point)))) + (goto-char placeholder) (c-add-stmt-syntax 'statement nil t containing-sexp paren-state)) - ;;CASE 5N: We are at a topmost continuation line and the only + ;;CASE 5S: We are at a topmost continuation line and the only ;;preceding items are annotations. ((and (c-major-mode-is 'java-mode) (setq placeholder (point)) - (c-beginning-of-statement-1) + (c-beginning-of-statement-1 lim) (progn - (while (and (c-forward-annotation)) - (c-forward-syntactic-ws)) + (while (and (setq tmp-pos (point)) + (< (point) placeholder) + (c-forward-annotation)) + (c-forward-syntactic-ws) + (setq tmp-pos2 tmp-pos)) t) (prog1 (>= (point) placeholder) (goto-char placeholder))) - (c-add-syntax 'annotation-top-cont (c-point 'boi))) + (c-add-syntax 'annotation-top-cont (c-point 'boi tmp-pos2))) ;; CASE 5M: we are at a topmost continuation line (t - (c-beginning-of-statement-1 (c-safe-position (point) paren-state)) + (c-beginning-of-statement-1 + (or (c-safe-position (point) paren-state) + (c-determine-limit 1000))) (when (c-major-mode-is 'objc-mode) (setq placeholder (point)) (while (and (c-forward-objc-directive) @@ -13652,8 +13935,9 @@ comment at the start of cc-engine.el for more info." (setq tmpsymbol '(block-open . inexpr-statement) placeholder (cdr-safe (c-looking-at-inexpr-block - (c-safe-position containing-sexp - paren-state) + (or + (c-safe-position containing-sexp paren-state) + (c-determine-limit 1000 containing-sexp)) containing-sexp))) ;; placeholder is nil if it's a block directly in ;; a function arglist. That makes us skip out of @@ -13785,7 +14069,9 @@ comment at the start of cc-engine.el for more info." (setq placeholder (c-guess-basic-syntax)))) (setq c-syntactic-context placeholder) (c-beginning-of-statement-1 - (c-safe-position (1- containing-sexp) paren-state)) + (or + (c-safe-position (1- containing-sexp) paren-state) + (c-determine-limit 1000 (1- containing-sexp)))) (c-forward-token-2 0) (while (cond ((looking-at c-specifier-key) @@ -13819,7 +14105,8 @@ comment at the start of cc-engine.el for more info." (c-add-syntax 'brace-list-close (point)) (setq lim (or (save-excursion (and - (c-back-over-member-initializers) + (c-back-over-member-initializers + (c-determine-limit 1000)) (point))) (c-most-enclosing-brace state-cache (point)))) (c-beginning-of-statement-1 lim nil nil t) @@ -13852,7 +14139,8 @@ comment at the start of cc-engine.el for more info." (c-add-syntax 'brace-list-intro (point)) (setq lim (or (save-excursion (and - (c-back-over-member-initializers) + (c-back-over-member-initializers + (c-determine-limit 1000)) (point))) (c-most-enclosing-brace state-cache (point)))) (c-beginning-of-statement-1 lim nil nil t) @@ -13865,7 +14153,7 @@ comment at the start of cc-engine.el for more info." (save-excursion (goto-char indent-point) (c-forward-syntactic-ws (c-point 'eol)) - (c-looking-at-special-brace-list (point))))) + (c-looking-at-special-brace-list)))) (c-add-syntax 'brace-entry-open (point)) (c-add-stmt-syntax 'brace-list-entry nil t containing-sexp paren-state (point)) @@ -13908,7 +14196,9 @@ comment at the start of cc-engine.el for more info." ;; CASE 16A: closing a lambda defun or an in-expression ;; block? C.f. cases 4, 7B and 17E. ((setq placeholder (c-looking-at-inexpr-block - (c-safe-position containing-sexp paren-state) + (or + (c-safe-position containing-sexp paren-state) + (c-determine-limit 1000 containing-sexp)) nil)) (setq tmpsymbol (if (eq (car placeholder) 'inlambda) 'inline-close @@ -13931,9 +14221,7 @@ comment at the start of cc-engine.el for more info." (and lim (progn (goto-char lim) - (c-looking-at-decl-block - (c-most-enclosing-brace paren-state lim) - nil)) + (c-looking-at-decl-block nil)) (setq placeholder (point)))) (c-backward-to-decl-anchor lim) (back-to-indentation) @@ -14073,7 +14361,9 @@ comment at the start of cc-engine.el for more info." ;; CASE 17E: first statement in an in-expression block. ;; C.f. cases 4, 7B and 16A. ((setq placeholder (c-looking-at-inexpr-block - (c-safe-position containing-sexp paren-state) + (or + (c-safe-position containing-sexp paren-state) + (c-determine-limit 1000 containing-sexp)) nil)) (setq tmpsymbol (if (eq (car placeholder) 'inlambda) 'defun-block-intro @@ -14101,9 +14391,7 @@ comment at the start of cc-engine.el for more info." (and (progn (goto-char placeholder) (eq (char-after) ?{)) - (c-looking-at-decl-block (c-most-enclosing-brace - paren-state (point)) - nil)))) + (c-looking-at-decl-block nil)))) (c-backward-to-decl-anchor lim) (back-to-indentation) (c-add-syntax 'defun-block-intro (point))) diff --git a/lisp/progmodes/cc-fonts.el b/lisp/progmodes/cc-fonts.el index fd00d65e33..4e283764ce 100644 --- a/lisp/progmodes/cc-fonts.el +++ b/lisp/progmodes/cc-fonts.el @@ -76,9 +76,6 @@ (cc-require-when-compile 'cc-langs) (cc-require 'cc-vars) (cc-require 'cc-engine) -(cc-require-when-compile 'cc-awk) ; Change from cc-require, 2003/6/18 to -;; prevent cc-awk being loaded when it's not needed. There is now a (require -;; 'cc-awk) in (defun awk-mode ..). ;; Avoid repeated loading through the eval-after-load directive in ;; cc-mode.el. @@ -947,7 +944,7 @@ casts and declarations are fontified. Used on level 2 and higher." ;; closest token before the region. (save-excursion (let ((pos (point))) - (c-backward-syntactic-ws) + (c-backward-syntactic-ws (max (- (point) 500) (point-min))) (c-clear-char-properties (if (and (not (bobp)) (memq (c-get-char-property (1- (point)) 'c-type) @@ -969,7 +966,7 @@ casts and declarations are fontified. Used on level 2 and higher." ;; The declared identifiers are font-locked correctly as types, if ;; that is what they are. (let ((prop (save-excursion - (c-backward-syntactic-ws) + (c-backward-syntactic-ws (max (- (point) 500) (point-min))) (unless (bobp) (c-get-char-property (1- (point)) 'c-type))))) (when (memq prop '(c-decl-id-start c-decl-type-start)) @@ -1008,82 +1005,92 @@ casts and declarations are fontified. Used on level 2 and higher." (boundp 'parse-sexp-lookup-properties))) (c-parse-and-markup-<>-arglists t) c-restricted-<>-arglists - id-start id-end id-face pos kwd-sym) + id-start id-end id-face pos kwd-sym + old-pos) (while (and (< (point) limit) - (re-search-forward c-opt-<>-arglist-start limit t)) - - (setq id-start (match-beginning 1) - id-end (match-end 1) - pos (point)) - - (goto-char id-start) - (unless (c-skip-comments-and-strings limit) - (setq kwd-sym nil - c-restricted-<>-arglists nil - id-face (get-text-property id-start 'face)) - - (if (cond - ((eq id-face 'font-lock-type-face) - ;; The identifier got the type face so it has already been - ;; handled in `c-font-lock-declarations'. - nil) - - ((eq id-face 'font-lock-keyword-face) - (when (looking-at c-opt-<>-sexp-key) - ;; There's a special keyword before the "<" that tells - ;; that it's an angle bracket arglist. - (setq kwd-sym (c-keyword-sym (match-string 1))))) - - (t - ;; There's a normal identifier before the "<". If we're not in - ;; a declaration context then we set `c-restricted-<>-arglists' - ;; to avoid recognizing templates in function calls like "foo (a - ;; < b, c > d)". - (c-backward-syntactic-ws) - (when (and (memq (char-before) '(?\( ?,)) - (not (eq (get-text-property (1- (point)) 'c-type) - 'c-decl-arg-start))) - (setq c-restricted-<>-arglists t)) - t)) + (setq old-pos (point)) + (c-syntactic-re-search-forward "<" limit t nil t)) + (setq pos (point)) + (save-excursion + (backward-char) + (c-backward-syntactic-ws old-pos) + (if (re-search-backward + (concat "\\(\\`\\|" c-nonsymbol-key "\\)\\(" c-symbol-key"\\)\\=") + old-pos t) + (setq id-start (match-beginning 2) + id-end (match-end 2)) + (setq id-start nil id-end nil))) + + (when id-start + (goto-char id-start) + (unless (c-skip-comments-and-strings limit) + (setq kwd-sym nil + c-restricted-<>-arglists nil + id-face (get-text-property id-start 'face)) + + (if (cond + ((eq id-face 'font-lock-type-face) + ;; The identifier got the type face so it has already been + ;; handled in `c-font-lock-declarations'. + nil) - (progn - (goto-char (1- pos)) - ;; Check for comment/string both at the identifier and - ;; at the "<". - (unless (c-skip-comments-and-strings limit) - - (c-fontify-types-and-refs () - (when (c-forward-<>-arglist (c-keyword-member - kwd-sym 'c-<>-type-kwds)) - (when (and c-opt-identifier-concat-key - (not (get-text-property id-start 'face))) - (c-forward-syntactic-ws) - (cond ((looking-at c-opt-identifier-concat-key) - (c-put-font-lock-face id-start id-end - c-reference-face-name)) - ((eq (char-after) ?\()) - (t (c-put-font-lock-face id-start id-end - 'font-lock-type-face)))))) - - (goto-char pos))) - (goto-char pos)))))) + ((eq id-face 'font-lock-keyword-face) + (when (looking-at c-opt-<>-sexp-key) + ;; There's a special keyword before the "<" that tells + ;; that it's an angle bracket arglist. + (setq kwd-sym (c-keyword-sym (match-string 2))))) + + (t + ;; There's a normal identifier before the "<". If we're not in + ;; a declaration context then we set `c-restricted-<>-arglists' + ;; to avoid recognizing templates in function calls like "foo (a + ;; < b, c > d)". + (c-backward-syntactic-ws) + (when (and (memq (char-before) '(?\( ?,)) + (not (eq (get-text-property (1- (point)) 'c-type) + 'c-decl-arg-start))) + (setq c-restricted-<>-arglists t)) + t)) + + (progn + (goto-char (1- pos)) + ;; Check for comment/string both at the identifier and + ;; at the "<". + (unless (c-skip-comments-and-strings limit) + + (c-fontify-types-and-refs () + (when (c-forward-<>-arglist (c-keyword-member + kwd-sym 'c-<>-type-kwds)) + (when (and c-opt-identifier-concat-key + (not (get-text-property id-start 'face))) + (c-forward-syntactic-ws) + (cond ((looking-at c-opt-identifier-concat-key) + (c-put-font-lock-face id-start id-end + c-reference-face-name)) + ((eq (char-after) ?\()) + (t (c-put-font-lock-face id-start id-end + 'font-lock-type-face)))))) + + (goto-char pos))) + (goto-char pos))))))) nil) (defun c-font-lock-declarators (limit list types not-top &optional template-class) ;; Assuming the point is at the start of a declarator in a declaration, - ;; fontify the identifier it declares. (If TYPES is set, it does this via - ;; the macro `c-fontify-types-and-refs'.) + ;; fontify the identifier it declares. (If TYPES is t, it does this via the + ;; macro `c-fontify-types-and-refs'.) ;; ;; If LIST is non-nil, also fontify the ids in any following declarators in ;; a comma separated list (e.g. "foo" and "*bar" in "int foo = 17, *bar;"); ;; additionally, mark the commas with c-type property 'c-decl-id-start or ;; 'c-decl-type-start (according to TYPES). Stop at LIMIT. ;; - ;; If TYPES is non-nil, fontify all identifiers as types. If NOT-TOP is - ;; non-nil, we are not at the top-level ("top-level" includes being directly - ;; inside a class or namespace, etc.). + ;; If TYPES is t, fontify all identifiers as types, if it is nil fontify as + ;; either variables or functions, otherwise TYPES is a face to use. If + ;; NOT-TOP is non-nil, we are not at the top-level ("top-level" includes + ;; being directly inside a class or namespace, etc.). ;; ;; TEMPLATE-CLASS is non-nil when the declaration is in template delimiters ;; and was introduced by, e.g. "typename" or "class", such that if there is @@ -1100,9 +1107,10 @@ casts and declarations are fontified. Used on level 2 and higher." () (c-do-declarators limit list not-top - (if types 'c-decl-type-start 'c-decl-id-start) + (cond ((eq types t) 'c-decl-type-start) + ((null types) 'c-decl-id-start)) (lambda (id-start _id-end end-pos _not-top is-function init-char) - (if types + (if (eq types t) ;; Register and fontify the identifier as a type. (let ((c-promote-possible-types t)) (goto-char id-start) @@ -1121,9 +1129,10 @@ casts and declarations are fontified. Used on level 2 and higher." ;; `c-forward-declarator'. (c-put-font-lock-face (car c-last-identifier-range) (cdr c-last-identifier-range) - (if is-function - 'font-lock-function-name-face - 'font-lock-variable-name-face)))) + (cond + ((not (memq types '(nil t))) types) + (is-function 'font-lock-function-name-face) + (t 'font-lock-variable-name-face))))) (and template-class (eq init-char ?=) ; C++ "<class X = Y>"? (progn @@ -1357,7 +1366,8 @@ casts and declarations are fontified. Used on level 2 and higher." 'c-decl-id-start))))) (c-font-lock-declarators (min limit (point-max)) decl-list - (cadr decl-or-cast) (not toplev) template-class)) + (not (null (cadr decl-or-cast))) + (not toplev) template-class)) ;; A declaration has been successfully identified, so do all the ;; fontification of types and refs that've been recorded. @@ -1492,7 +1502,8 @@ casts and declarations are fontified. Used on level 2 and higher." ;; Check we haven't missed a preceding "typedef". (when (not (looking-at c-typedef-key)) - (c-backward-syntactic-ws) + (c-backward-syntactic-ws + (max (- (point) 1000) (point-min))) (c-backward-token-2) (or (looking-at c-typedef-key) (goto-char start-pos))) @@ -1532,8 +1543,10 @@ casts and declarations are fontified. Used on level 2 and higher." (c-backward-token-2) (and (not (looking-at c-opt-<>-sexp-key)) - (progn (c-backward-syntactic-ws) - (memq (char-before) '(?\( ?,))) + (progn + (c-backward-syntactic-ws + (max (- (point) 1000) (point-min))) + (memq (char-before) '(?\( ?,))) (not (eq (c-get-char-property (1- (point)) 'c-type) 'c-decl-arg-start)))))) @@ -2004,6 +2017,9 @@ on level 2 only and so aren't combined with `c-complex-decl-matchers'." ,@(when (c-major-mode-is 'c++-mode) '(c-font-lock-c++-lambda-captures)) + ,@(when (c-lang-const c-using-key) + `(c-font-lock-c++-using)) + ;; The first two rules here mostly find occurrences that ;; `c-font-lock-declarations' has found already, but not ;; declarations containing blocks in the type (see note below). @@ -2263,6 +2279,41 @@ need for `c-font-lock-extra-types'.") ;;; C++. +(defun c-font-lock-c++-using (limit) + ;; Fontify any clauses starting with the keyword `using'. + ;; + ;; This function will be called from font-lock- for a region bounded by + ;; POINT and LIMIT, as though it were to identify a keyword for + ;; font-lock-keyword-face. It always returns NIL to inhibit this and + ;; prevent a repeat invocation. See elisp/lispref page "Search-based + ;; fontification". + (let (pos after-name) + (while (c-syntactic-re-search-forward c-using-key limit 'end) + (while ; Do one declarator of a comma separated list, each time around. + (progn + (c-forward-syntactic-ws) + (setq pos (point)) ; token after "using". + (when (and (c-on-identifier) + (c-forward-name)) + (setq after-name (point)) + (cond + ((eq (char-after) ?=) ; using foo = <type-id>; + (goto-char pos) + (c-font-lock-declarators limit nil t nil)) + ((save-excursion + (and c-colon-type-list-re + (c-go-up-list-backward) + (eq (char-after) ?{) + (eq (car (c-beginning-of-decl-1 + (c-determine-limit 1000))) 'same) + (looking-at c-colon-type-list-re))) + ;; Inherited protected member: leave unfontified + ) + (t (goto-char pos) + (c-font-lock-declarators limit nil c-label-face-name nil))) + (eq (char-after) ?,))) + (forward-char))) ; over the comma. + nil)) (defun c-font-lock-c++-new (limit) ;; FIXME!!! Put in a comment about the context of this function's @@ -3016,6 +3067,84 @@ need for `pike-font-lock-extra-types'.") (c-font-lock-doc-comments "/[*/]!" limit autodoc-font-lock-doc-comments))))) +;; Doxygen + +(defconst doxygen-font-lock-doc-comments + ;; TODO: Handle @code, @verbatim, @dot, @f etc. better by not highlighting + ;; text inside of those commands. Something smarter than just regexes may be + ;; needed to do that efficiently. + `((,(concat + ;; Make sure that the special character has not been escaped. E.g. in + ;; `\@foo' only `\@' is a command (similarly for other characters like + ;; `\\foo', `\<foo' and `\&foo'). The downside now is that we don't + ;; match command started just after an escaped character, e.g. in + ;; `\@\foo' we should match `\@' as well as `\foo' but only the former + ;; is matched. + "\\(?:^\\|[^\\@]\\)\\(" + ;; Doxygen commands start with backslash or an at sign. Note that for + ;; brevity in the comments only `\' will be mentioned. + "[\\@]\\(?:" + ;; Doxygen commands except those starting with `f' + "[a-eg-z][a-z]*" + ;; Doxygen command starting with `f': + "\\|f\\(?:" + "[][$}]" ; \f$ \f} \f[ \f] + "\\|{\\(?:[a-zA-Z]+\\*?}{?\\)?" ; \f{ \f{env} \f{env}{ + "\\|[a-z]+" ; \foo + "\\)" + "\\|~[a-zA-Z]*" ; \~ \~language + "\\|[$@&~<=>#%\".|\\\\]" ; single-character escapes + "\\|::\\|---?" ; \:: \-- \--- + "\\)" + ;; HTML tags and entities: + "\\|</?\\sw\\(?:\\sw\\|\\s \\|[=\n\r*.:]\\|\"[^\"]*\"\\|'[^']*'\\)*>" + "\\|&\\(?:\\sw+\\|#[0-9]+\\|#x[0-9a-fA-F]+\\);" + "\\)") + 1 ,c-doc-markup-face-name prepend nil) + ;; Commands inside of strings are not commands so override highlighting with + ;; string face. This also affects HTML attribute values if they are + ;; surrounded with double quotes which may or may not be considered a good + ;; thing. + ("\\(?:^\\|[^\\@]\\)\\(\"[^\"[:cntrl:]]+\"\\)" + 1 font-lock-string-face prepend nil) + ;; HTML comments inside of the Doxygen comments. + ("\\(?:^\\|[^\\@]\\)\\(<!--.*?-->\\)" + 1 font-lock-comment-face prepend nil) + ;; Autolinking. Doxygen auto-links anything that is a class name but we have + ;; no hope of matching those. We are, however, able to match functions and + ;; members using explicit scoped syntax. For functions, we can also find + ;; them by noticing argument-list. Note that Doxygen accepts `::' as well + ;; as `#' as scope operators. + (,(let* ((ref "[\\@]ref\\s-+") + (ref-opt (concat "\\(?:" ref "\\)?")) + (id "[a-zA-Z_][a-zA-Z_0-9]*") + (args "\\(?:()\\|([^()]*)\\)") + (scope "\\(?:#\\|::\\)")) + (concat + "\\(?:^\\|[^\\@/%:]\\)\\(?:" + ref-opt "\\(?1:" scope "?" "\\(?:" id scope "\\)+" "~?" id "\\)" + "\\|" ref-opt "\\(?1:" scope "~?" id "\\)" + "\\|" ref-opt "\\(?1:" scope "?" "~?" id "\\)" args + "\\|" ref "\\(?1:" "~?" id "\\)" + "\\|" ref-opt "\\(?1:~[A-Z][a-zA-Z0-9_]+\\)" + "\\)")) + 1 font-lock-function-name-face prepend nil) + ;; Match URLs and emails. This has two purposes. First of all, Doxygen + ;; autolinks URLs. Second of all, `@bar' in `foo@bar.baz' has been matched + ;; above as a command; try and overwrite it. + (,(let* ((host "[A-Za-z0-9]\\(?:[A-Za-z0-9-]\\{0,61\\}[A-Za-z0-9]\\)") + (fqdn (concat "\\(?:" host "\\.\\)+" host)) + (comp "[!-(*--/-=?-~]+") + (path (concat "/\\(?:" comp "[.]+" "\\)*" comp))) + (concat "\\(?:mailto:\\)?[a-zA-0_.]+@" fqdn + "\\|https?://" fqdn "\\(?:" path "\\)?")) + 0 font-lock-keyword-face prepend nil))) + +(defconst doxygen-font-lock-keywords + `((,(lambda (limit) + (c-font-lock-doc-comments "/\\(?:/[/!]\\|\\*[\\*!]\\)" + limit doxygen-font-lock-doc-comments))))) + ;; 2006-07-10: awk-font-lock-keywords has been moved back to cc-awk.el. (cc-provide 'cc-fonts) diff --git a/lisp/progmodes/cc-langs.el b/lisp/progmodes/cc-langs.el index acdb72fb7b..fa4e73087e 100644 --- a/lisp/progmodes/cc-langs.el +++ b/lisp/progmodes/cc-langs.el @@ -457,13 +457,11 @@ so that all identifiers are recognized as words.") c-before-change-check-raw-strings c-before-change-check-<>-operators c-depropertize-CPP - c-invalidate-macro-cache c-truncate-bs-cache c-before-change-check-unbalanced-strings c-parse-quotes-before-change) (c objc) '(c-extend-region-for-CPP c-depropertize-CPP - c-invalidate-macro-cache c-truncate-bs-cache c-before-change-check-unbalanced-strings c-parse-quotes-before-change) @@ -549,7 +547,7 @@ parameters (point-min), (point-max) and <buffer size>.") (c-lang-defconst c-before-context-fontification-functions t 'c-context-expand-fl-region - awk nil) + awk 'c-awk-context-expand-fl-region) ;; For documentation see the following c-lang-defvar of the same name. ;; The value here may be a list of functions or a single function. (c-lang-defvar c-before-context-fontification-functions @@ -581,12 +579,14 @@ don't have EOL terminated statements. " (c-lang-defvar c-at-vsemi-p-fn (c-lang-const c-at-vsemi-p-fn)) (c-lang-defconst c-vsemi-status-unknown-p-fn - "Contains a function \"are we unsure whether there is a virtual semicolon on this line?\". -The (admittedly kludgy) purpose of such a function is to prevent an infinite -recursion in c-beginning-of-statement-1 when point starts at a `while' token. -The function MUST NOT UNDER ANY CIRCUMSTANCES call c-beginning-of-statement-1, -even indirectly. This variable contains nil for languages which don't have -EOL terminated statements." + "Contains a predicate regarding the presence of virtual semicolons. +More precisely, the function answers the question, \"are we unsure whether a +virtual semicolon exists on this line?\". The (admittedly kludgy) purpose of +such a function is to prevent an infinite recursion in +`c-beginning-of-statement-1' when point starts at a `while' token. The function +MUST NOT UNDER ANY CIRCUMSTANCES call `c-beginning-of-statement-1', even +indirectly. This variable contains nil for languages which don't have EOL +terminated statements." t nil (c c++ objc) 'c-macro-vsemi-status-unknown-p awk 'c-awk-vsemi-status-unknown-p) @@ -699,6 +699,7 @@ It's assumed to not contain any submatchers." ;; The same thing regarding Unicode identifiers applies here as to ;; `c-symbol-key'. t (concat "[" (c-lang-const c-nonsymbol-chars) "]")) +(c-lang-defvar c-nonsymbol-key (c-lang-const c-nonsymbol-key)) (c-lang-defconst c-identifier-ops "The operators that make up fully qualified identifiers. nil in @@ -1174,7 +1175,7 @@ since CC Mode treats every identifier as an expression." ;; Exception. ,@(when (c-major-mode-is 'c++-mode) - '((prefix "throw"))) + '((prefix "throw" "co_await" "co_yield"))) ;; Sequence. (left-assoc ",")) @@ -1769,7 +1770,7 @@ ender." `comment-start-skip' is initialized from this." ;; Default: Allow the last char of the comment starter(s) to be ;; repeated, then allow any amount of horizontal whitespace. - t (concat "\\(" + t (concat "\\(?:" (c-concat-separated (mapcar (lambda (cs) (when cs @@ -2040,6 +2041,7 @@ the appropriate place for that." (c-lang-defconst c-return-kwds "Keywords which return a value to the calling function." t '("return") + c++ '("return" "co_return") idl nil) (c-lang-defconst c-return-key @@ -2120,7 +2122,9 @@ fontified with the keyword face and not the type face." t nil c '("const" "restrict" "volatile") c++ '("const" "noexcept" "volatile") - objc '("const" "volatile")) + objc '("const" "volatile") + t (append (c-lang-const c-no-type-kwds) + (c-lang-const c-type-modifier-prefix-kwds))) (c-lang-defconst c-opt-type-modifier-prefix-key ;; Adorned regexp matching `c-type-modifier-prefix-kwds', or nil in @@ -2337,6 +2341,26 @@ will be handled." t (c-make-keywords-re t (c-lang-const c-typedef-decl-kwds))) (c-lang-defvar c-typedef-decl-key (c-lang-const c-typedef-decl-key)) +(c-lang-defconst c-using-kwds + "Keywords which behave like `using' in C++" + t nil + c++ '("using")) + +(c-lang-defconst c-using-key + ;; Regexp matching C++'s `using'. + t (c-make-keywords-re t (c-lang-const c-using-kwds))) +(c-lang-defvar c-using-key (c-lang-const c-using-key)) + +(c-lang-defconst c-no-type-kwds + "Keywords which remove the need to specify a type in declarations" + t nil + c++ '("auto")) + +(c-lang-defconst c-no-type-key + ;; Regexp matching an entry from `c-no-type-kwds' + t (c-make-keywords-re t (c-lang-const c-no-type-kwds))) +(c-lang-defvar c-no-type-key (c-lang-const c-no-type-key)) + (c-lang-defconst c-typeless-decl-kwds "Keywords introducing declarations where the (first) identifier \(declarator) follows directly after the keyword, without any type. @@ -2350,7 +2374,6 @@ will be handled." ;; {...}"). t (append (c-lang-const c-class-decl-kwds) (c-lang-const c-brace-list-decl-kwds)) - c++ (append (c-lang-const c-typeless-decl-kwds) '("auto")) ; C++11. ;; Note: "manages" for CORBA CIDL clashes with its presence on ;; `c-type-list-kwds' for IDL. idl (append (c-lang-const c-typeless-decl-kwds) @@ -2385,9 +2408,11 @@ If any of these also are on `c-type-list-kwds', `c-ref-list-kwds', `c-<>-type-kwds', or `c-<>-arglist-kwds' then the associated clauses will be handled." t nil - (c c++) '("auto" "extern" "inline" "register" "static") + (c c++) '("extern" "inline" "register" "static") + c (append '("auto") (c-lang-const c-modifier-kwds)) c++ (append '("constexpr" "explicit" "friend" "mutable" "template" - "thread_local" "using" "virtual") + "thread_local" "virtual") + ;; "using" is now handled specially (2020-09-14). (c-lang-const c-modifier-kwds)) objc '("auto" "bycopy" "byref" "extern" "in" "inout" "oneway" "out" "static") ;; FIXME: Some of those below ought to be on `c-other-decl-kwds' instead. @@ -2415,7 +2440,8 @@ If any of these also are on `c-type-list-kwds', `c-ref-list-kwds', `c-<>-type-kwds', or `c-<>-arglist-kwds' then the associated clauses will be handled." t nil - objc '("@class" "@end" "@defs") + objc '("@class" "@defs" "@end" "@property" "@dynamic" "@synthesize" + "@compatibility_alias") java '("import" "package") pike '("import" "inherit")) @@ -2538,7 +2564,8 @@ one of `c-type-list-kwds', `c-ref-list-kwds', "Access protection label keywords in classes." t nil c++ '("private" "protected" "public") - objc '("@private" "@protected" "@public")) + objc '("@private" "@protected" "@package" "@public" + "@required" "@optional")) (c-lang-defconst c-protection-key ;; A regexp match an element of `c-protection-kwds' cleanly. @@ -2753,7 +2780,7 @@ identifiers that follows the type in a normal declaration." "Statement keywords followed directly by a substatement." t '("do" "else") c++ '("do" "else" "try") - objc '("do" "else" "@finally" "@try") + objc '("do" "else" "@finally" "@try" "@autoreleasepool") java '("do" "else" "finally" "try") idl nil) @@ -2783,7 +2810,7 @@ Keywords here should also be in `c-block-stmt-1-kwds'." java '("for" "if" "switch" "while" "catch" "synchronized") idl nil pike '("for" "if" "switch" "while" "foreach") - awk '("for" "if" "while")) + awk '("for" "if" "switch" "while")) (c-lang-defconst c-block-stmt-2-key ;; Regexp matching the start of any statement followed by a paren sexp @@ -2822,6 +2849,7 @@ Keywords here should also be in `c-block-stmt-1-kwds'." (c-lang-defconst c-simple-stmt-kwds "Statement keywords followed by an expression or nothing." t '("break" "continue" "goto" "return") + c++ '("break" "continue" "goto" "return" "co_return") objc '("break" "continue" "goto" "return" "@throw") ;; Note: `goto' is not valid in Java, but the keyword is still reserved. java '("break" "continue" "goto" "return" "throw") @@ -2862,8 +2890,7 @@ nevertheless contains a list separated with `;' and not `,'." (c-lang-defconst c-case-kwds "The keyword(s) which introduce a \"case\" like construct. This construct is \"<keyword> <expression> :\"." - t '("case") - awk nil) + t '("case")) (c-lang-defconst c-case-kwds-regexp ;; Adorned regexp matching any "case"-like keyword. @@ -2895,7 +2922,8 @@ This construct is \"<keyword> <expression> :\"." c++ (append '("nullptr") (c-lang-const c-constant-kwds c)) - objc '("nil" "Nil" "YES" "NO" "NS_DURING" "NS_HANDLER" "NS_ENDHANDLER") + objc '("nil" "Nil" "YES" "NO" "IBAction" "IBOutlet" + "NS_DURING" "NS_HANDLER" "NS_ENDHANDLER") idl '("TRUE" "FALSE") java '("true" "false" "null") ; technically "literals", not keywords pike '("UNDEFINED")) ;; Not a keyword, but practically works as one. @@ -3030,7 +3058,14 @@ Note that Java specific rules are currently applied to tell this from ;; can start a declaration.) "entity" "process" "service" "session" "storage")) - +(c-lang-defconst c-std-abbrev-keywords + "List of keywords which may need to cause electric indentation." + t '("else" "while") + c++ (append (c-lang-const c-std-abbrev-keywords) '("catch")) + java (append (c-lang-const c-std-abbrev-keywords) '("catch" "finally")) + idl nil) +(c-lang-defvar c-std-abbrev-keywords (c-lang-const c-std-abbrev-keywords)) + ;;; Constants built from keywords. ;; Note: No `*-kwds' language constants may be defined below this point. @@ -3063,6 +3098,36 @@ Note that Java specific rules are currently applied to tell this from t (c-make-keywords-re t (c-lang-const c-keywords))) (c-lang-defvar c-keywords-regexp (c-lang-const c-keywords-regexp)) +(c-lang-defconst c-stmt-block-only-keywords + "All keywords which unambiguously signify a statement block (as opposed to + a brace list) when occurring inside braces." + t (c--set-difference + (c-lang-const c-keywords) + (append (c-lang-const c-primary-expr-kwds) + (c-lang-const c-constant-kwds) + `(,@(when (c-major-mode-is 'c++-mode) + '("typeid" "dynamic_cast" "static_cast" "const_cast" + "reinterpret_cast" "alignof"))) + (c-lang-const c-type-modifier-prefix-kwds) + (c-lang-const c-overloadable-operators) + (c-lang-const c-template-typename-kwds) + `(,@(when (c-major-mode-is 'c++-mode) + '("reflexpr"))) + `(,@(when (c-major-mode-is '(c-mode c++-mode)) + '("sizeof"))) + (c-lang-const c-pre-lambda-tokens) + (c-lang-const c-block-decls-with-vars) + (c-lang-const c-primitive-type-kwds)) + :test 'string-equal)) + +(c-lang-defconst c-stmt-block-only-keywords-regexp + ;; A regexp matching a keyword in `c-stmt-block-only-keywords'. Such a + ;; match can start and end only at token boundaries. + t (concat "\\(^\\|\\=\\|[^" (c-lang-const c-symbol-chars) "]\\)" + (c-make-keywords-re t (c-lang-const c-stmt-block-only-keywords)))) +(c-lang-defvar c-stmt-block-only-keywords-regexp + (c-lang-const c-stmt-block-only-keywords-regexp)) + (c-lang-defconst c-keyword-member-alist ;; An alist with all the keywords in the cars. The cdr for each ;; keyword is a list of the symbols for the `*-kwds' lists that @@ -3398,35 +3463,47 @@ possible for good performance." t (c-make-bare-char-alt (c-lang-const c-block-prefix-disallowed-chars) t)) (c-lang-defvar c-block-prefix-charset (c-lang-const c-block-prefix-charset)) +(c-lang-defconst c-type-decl-prefix-keywords-key + ;; Regexp matching any keyword operator that might precede the identifier in + ;; a declaration, e.g. "const" or nil. It doesn't test there is no "_" + ;; following the keyword. + t (if (or (c-lang-const c-type-modifier-kwds) (c-lang-const c-modifier-kwds)) + (concat + (regexp-opt (c--delete-duplicates + (append (c-lang-const c-type-modifier-kwds) + (c-lang-const c-modifier-kwds)) + :test 'string-equal) + t) + "\\>"))) + (c-lang-defconst c-type-decl-prefix-key "Regexp matching any declarator operator that might precede the identifier in a declaration, e.g. the \"*\" in \"char *argv\". This regexp should match \"(\" if parentheses are valid in declarators. -The end of the first submatch is taken as the end of the operator. -Identifier syntax is in effect when this is matched (see -`c-identifier-syntax-table')." - t (if (c-lang-const c-type-modifier-kwds) - (concat (regexp-opt (c-lang-const c-type-modifier-kwds) t) "\\>") - ;; Default to a regexp that never matches. - regexp-unmatchable) +The operator found is either the first submatch (if it is not a +keyword) or the second submatch (if it is)." + t (if (c-lang-const c-type-decl-prefix-keywords-key) + (concat "\\(\\`a\\`\\)\\|" ; 1 - will never match. + (c-lang-const c-type-decl-prefix-keywords-key) ; 2 + "\\([^_]\\|$\\)") ; 3 + "\\`a\\`") ;; Default to a regexp that never matches. ;; Check that there's no "=" afterwards to avoid matching tokens ;; like "*=". - (c objc) (concat "\\(" + (c objc) (concat "\\(" ; 1 "[*(]" - "\\|" - (c-lang-const c-type-decl-prefix-key) - "\\)" - "\\([^=]\\|$\\)") - c++ (concat "\\(" + "\\)\\|" + (c-lang-const c-type-decl-prefix-keywords-key) ; 2 + "\\([^=_]\\|$\\)") ; 3 + c++ (concat "\\(" ; 1 "&&" "\\|" "\\.\\.\\." "\\|" "[*(&~]" + "\\)\\|\\(" ; 2 + (c-lang-const c-type-decl-prefix-keywords-key) ; 3 "\\|" - (c-lang-const c-type-decl-prefix-key) - "\\|" - (concat "\\(" ; 3 + (concat "\\(" ; 4 ;; If this matches there's special treatment in ;; `c-font-lock-declarators' and ;; `c-font-lock-declarations' that check for a @@ -3434,8 +3511,9 @@ Identifier syntax is in effect when this is matched (see (c-lang-const c-identifier-start) "\\)") "\\)" - "\\([^=]\\|$\\)") + "\\([^=_]\\|$\\)") ; 5 pike "\\(\\*\\)\\([^=]\\|$\\)") + (c-lang-defvar c-type-decl-prefix-key (c-lang-const c-type-decl-prefix-key) 'dont-doc) @@ -3602,13 +3680,25 @@ list." c t) (c-lang-defvar c-recognize-knr-p (c-lang-const c-recognize-knr-p)) +(c-lang-defconst c-pre-id-bracelist-kwds + "Keywords which, preceding an identifier and brace, signify a bracelist. +This is only used in c++-mode." + t nil + c++ '("new" "throw")) + (c-lang-defconst c-pre-id-bracelist-key - "A regexp matching tokens which, preceding an identifier, signify a bracelist. -" - t regexp-unmatchable - c++ "new\\([^[:alnum:]_$]\\|$\\)\\|&&?\\(\\S.\\|$\\)") + ;; A regexp matching keywords which, preceding an identifier and brace, + ;; signify a bracelist. Only used in c++-mode. + t (c-make-keywords-re t (c-lang-const c-pre-id-bracelist-kwds))) (c-lang-defvar c-pre-id-bracelist-key (c-lang-const c-pre-id-bracelist-key)) +(c-lang-defconst c-pre-brace-non-bracelist-key + "A regexp matching tokens which, preceding a brace, make it a non-bracelist." + t regexp-unmatchable + c++ "&&?\\(\\S.\\|$\\)") +(c-lang-defvar c-pre-brace-non-bracelist-key + (c-lang-const c-pre-brace-non-bracelist-key)) + (c-lang-defconst c-recognize-typeless-decls "Non-nil means function declarations without return type should be recognized. That can introduce an ambiguity with parenthesized macro diff --git a/lisp/progmodes/cc-mode.el b/lisp/progmodes/cc-mode.el index 601e181192..cfb23d0d45 100644 --- a/lisp/progmodes/cc-mode.el +++ b/lisp/progmodes/cc-mode.el @@ -113,6 +113,7 @@ ;; Silence the compiler. (cc-bytecomp-defvar adaptive-fill-first-line-regexp) ; Emacs (cc-bytecomp-defun run-mode-hooks) ; Emacs 21.1 +(cc-bytecomp-defvar awk-mode-syntax-table) ;; We set this variable during mode init, yet we don't require ;; font-lock. @@ -278,6 +279,29 @@ control). See \"cc-mode.el\" for more info." (setq defs (cdr defs))))) (put 'c-define-abbrev-table 'lisp-indent-function 1) +(defun c-populate-abbrev-table () + ;; Insert the standard keywords which may need electric indentation into the + ;; current mode's abbreviation table. + (let ((table (intern (concat (symbol-name major-mode) "-abbrev-table"))) + (defs c-std-abbrev-keywords) + ) + (unless (and (boundp table) + (abbrev-table-p (symbol-value table))) + (define-abbrev-table table nil)) + (setq local-abbrev-table (symbol-value table)) + (while defs + (unless (intern-soft (car defs) local-abbrev-table) ; Don't overwrite the + ; abbrev's use count. + (condition-case nil + (define-abbrev (symbol-value table) + (car defs) (car defs) + 'c-electric-continued-statement 0 t) + (wrong-number-of-arguments + (define-abbrev (symbol-value table) + (car defs) (car defs) + 'c-electric-continued-statement 0)))) + (setq defs (cdr defs))))) + (defun c-bind-special-erase-keys () ;; Only used in Emacs to bind C-c C-<delete> and C-c C-<backspace> ;; to the proper keys depending on `normal-erase-is-backspace'. @@ -476,11 +500,14 @@ preferably use the `c-mode-menu' language constant directly." (save-excursion (when (< beg end) (goto-char beg) + (let ((lim (c-determine-limit 1000)) + (lim+ (c-determine-+ve-limit 1000 end))) (when (and (not (bobp)) - (progn (c-backward-syntactic-ws) (eq (point) beg)) + (progn (c-backward-syntactic-ws lim) (eq (point) beg)) (/= (skip-chars-backward c-symbol-chars (1- (point))) 0) - (progn (goto-char beg) (c-forward-syntactic-ws) (<= (point) end)) + (progn (goto-char beg) (c-forward-syntactic-ws lim+) + (<= (point) end)) (> (point) beg) (goto-char end) (looking-at c-symbol-char-key)) @@ -491,14 +518,14 @@ preferably use the `c-mode-menu' language constant directly." (goto-char end) (when (and (not (eobp)) - (progn (c-forward-syntactic-ws) (eq (point) end)) + (progn (c-forward-syntactic-ws lim+) (eq (point) end)) (looking-at c-symbol-char-key) - (progn (c-backward-syntactic-ws) (>= (point) beg)) + (progn (c-backward-syntactic-ws lim) (>= (point) beg)) (< (point) end) (/= (skip-chars-backward c-symbol-chars (1- (point))) 0)) (goto-char (1+ end)) (c-end-of-current-token) - (c-unfind-type (buffer-substring-no-properties end (point))))))) + (c-unfind-type (buffer-substring-no-properties 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 @@ -535,6 +562,18 @@ preferably use the `c-mode-menu' language constant directly." ;; and `after-change-functions'. Note that this variable is not set when ;; `c-before-change' is invoked by a change to text properties. +(defvar c-min-syn-tab-mkr nil) +;; The minimum buffer position where there's a `c-fl-syn-tab' text property, +;; or nil if there aren't any. This is a marker, or nil if there's currently +;; no such text property. +(make-variable-buffer-local 'c-min-syn-tab-mkr) + +(defvar c-max-syn-tab-mkr nil) +;; The maximum buffer position plus 1 where there's a `c-fl-syn-tab' text +;; property, or nil if there aren't any. This is a marker, or nil if there's +;; currently no such text property. +(make-variable-buffer-local 'c-max-syn-tab-mkr) + (defun c-basic-common-init (mode default-style) "Do the necessary initialization for the syntax handling routines and the line breaking/filling code. Intended to be used by other @@ -550,6 +589,8 @@ that requires a literal mode spec at compile time." (setq c-buffer-is-cc-mode mode) + (c-populate-abbrev-table) + ;; these variables should always be buffer local; they do not affect ;; indentation style. (make-local-variable 'comment-start) @@ -599,6 +640,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 cache for `c-looking-at-or-maybe-in-bracelist'. + (setq c-laomib-cache nil) ;; Initialize the three literal sub-caches. (c-truncate-lit-pos-cache 1) ;; Initialize the cache of brace pairs, and opening braces/brackets/parens. @@ -606,6 +649,10 @@ that requires a literal mode spec at compile time." ;; Initialize the "brace stack" cache. (c-init-bs-cache) + ;; Keep track of where `c-fl-syn-tab' text properties are set. + (setq c-min-syn-tab-mkr nil) + (setq c-max-syn-tab-mkr nil) + (when (or c-recognize-<>-arglists (c-major-mode-is 'awk-mode) (c-major-mode-is '(java-mode c-mode c++-mode objc-mode pike-mode))) @@ -684,8 +731,8 @@ that requires a literal mode spec at compile time." ;; ;; Put submode indicators onto minor-mode-alist, but only once. ;; (or (assq 'c-submode-indicators minor-mode-alist) ;; (setq minor-mode-alist -;; (cons '(c-submode-indicators c-submode-indicators) -;; minor-mode-alist))) +;; (cons '(c-submode-indicators c-submode-indicators) +;; minor-mode-alist))) (c-update-modeline) ;; Install the functions that ensure that various internal caches @@ -1207,52 +1254,94 @@ Note that the style variables are always made local to the buffer." (c-put-syn-tab (1- (point)) '(15))) (t nil))))) -(defvar c-fl-syn-tab-region nil) - ;; Non-nil when a `c-restore-string-fences' is "in force". It's value is a - ;; cons of the BEG and END of the region currently "mirroring" the - ;; c-fl-syn-tab properties as syntax-table properties. +(defun c-put-syn-tab (pos value) + ;; Set both the syntax-table and the c-fl-syn-tab text properties at POS to + ;; VALUE (which should not be nil). + ;; `(let ((-pos- ,pos) + ;; (-value- ,value)) + (c-put-char-property pos 'syntax-table value) + (c-put-char-property pos 'c-fl-syn-tab value) + (cond + ((null c-min-syn-tab-mkr) + (setq c-min-syn-tab-mkr (copy-marker pos t))) + ((< pos c-min-syn-tab-mkr) + (move-marker c-min-syn-tab-mkr pos))) + (cond + ((null c-max-syn-tab-mkr) + (setq c-max-syn-tab-mkr (copy-marker (1+ pos) nil))) + ((>= pos c-max-syn-tab-mkr) + (move-marker c-max-syn-tab-mkr (1+ pos)))) + (c-truncate-lit-pos-cache pos)) + +(defun c-clear-syn-tab (pos) + ;; Remove both the 'syntax-table and `c-fl-syn-tab properties at POS. + (c-clear-char-property pos 'syntax-table) + (c-clear-char-property pos 'c-fl-syn-tab) + (when c-min-syn-tab-mkr + (if (and (eq pos (marker-position c-min-syn-tab-mkr)) + (eq (1+ pos) (marker-position c-max-syn-tab-mkr))) + (progn + (move-marker c-min-syn-tab-mkr nil) + (move-marker c-max-syn-tab-mkr nil) + (setq c-min-syn-tab-mkr nil c-max-syn-tab-mkr nil)) + (when (eq pos (marker-position c-min-syn-tab-mkr)) + (move-marker c-min-syn-tab-mkr + (if (c-get-char-property (1+ pos) 'c-fl-syn-tab) + (1+ pos) + (c-next-single-property-change + (1+ pos) 'c-fl-syn-tab nil c-max-syn-tab-mkr)))) + (when (eq (1+ pos) (marker-position c-max-syn-tab-mkr)) + (move-marker c-max-syn-tab-mkr + (if (c-get-char-property (1- pos) 'c-fl-syn-tab) + pos + (c-previous-single-property-change + pos 'c-fl-syn-tab nil (1+ c-min-syn-tab-mkr))))))) + (c-truncate-lit-pos-cache pos)) (defun c-clear-string-fences () - ;; Clear syntax-table text properties in the region defined by - ;; `c-cl-syn-tab-region' which are "mirrored" by c-fl-syn-tab text - ;; properties. However, any such " character which ends up not being + ;; Clear syntax-table text properties which are "mirrored" by c-fl-syn-tab + ;; text properties. However, any such " character which ends up not being ;; balanced by another " is left with a '(1) syntax-table property. - (when c-fl-syn-tab-region - (let ((beg (car c-fl-syn-tab-region)) - (end (cdr c-fl-syn-tab-region)) - s pos) - (setq pos beg) + (when + (and c-min-syn-tab-mkr c-max-syn-tab-mkr) + (let (s pos) + (setq pos c-min-syn-tab-mkr) (while (and - (< pos end) - (setq pos - (c-min-property-position pos end 'c-fl-syn-tab)) - (< pos end)) + (< pos c-max-syn-tab-mkr) + (setq pos (c-min-property-position pos + c-max-syn-tab-mkr + 'c-fl-syn-tab)) + (< pos c-max-syn-tab-mkr)) (c-clear-char-property pos 'syntax-table) (setq pos (1+ pos))) ;; Check we haven't left any unbalanced "s. (save-excursion - (setq pos beg) + (setq pos c-min-syn-tab-mkr) ;; Is there already an unbalanced " before BEG? - (setq pos (c-min-property-position pos end 'c-fl-syn-tab)) - (when (< pos end) (goto-char pos)) + (setq pos (c-min-property-position pos c-max-syn-tab-mkr + 'c-fl-syn-tab)) + (when (< pos c-max-syn-tab-mkr) + (goto-char pos)) (when (and (save-match-data (c-search-backward-char-property-with-value-on-char 'c-fl-syn-tab '(15) ?\" (max (- (point) 500) (point-min)))) (not (equal (c-get-char-property (point) 'syntax-table) '(1)))) (setq pos (1+ pos))) - (while (< pos end) + (while (< pos c-max-syn-tab-mkr) (setq pos - (c-min-property-position pos end 'c-fl-syn-tab)) - (when (< pos end) + (c-min-property-position pos c-max-syn-tab-mkr 'c-fl-syn-tab)) + (when (< pos c-max-syn-tab-mkr) (if (memq (char-after pos) c-string-delims) (progn ;; Step over the ". - (setq s (parse-partial-sexp pos end nil nil nil + (setq s (parse-partial-sexp pos c-max-syn-tab-mkr + nil nil nil 'syntax-table)) ;; Seek a (bogus) matching ". - (setq s (parse-partial-sexp (point) end nil nil s + (setq s (parse-partial-sexp (point) c-max-syn-tab-mkr + nil nil s 'syntax-table)) ;; When a bogus matching " is found, do nothing. ;; Otherwise mark the " with 'syntax-table '(1). @@ -1262,23 +1351,22 @@ Note that the style variables are always made local to the buffer." (c-get-char-property (1- (point)) 'c-fl-syn-tab)) (c-put-char-property pos 'syntax-table '(1))) (setq pos (point))) - (setq pos (1+ pos)))))) - (setq c-fl-syn-tab-region nil)))) - -(defun c-restore-string-fences (beg end) - ;; Restore any syntax-table text properties in the region (BEG END) which - ;; are "mirrored" by c-fl-syn-tab text properties. - (let ((pos beg)) - (while - (and - (< pos end) - (setq pos - (c-min-property-position pos end 'c-fl-syn-tab)) - (< pos end)) - (c-put-char-property pos 'syntax-table - (c-get-char-property pos 'c-fl-syn-tab)) - (setq pos (1+ pos))) - (setq c-fl-syn-tab-region (cons beg end)))) + (setq pos (1+ pos))))))))) + +(defun c-restore-string-fences () + ;; Restore any syntax-table text properties which are "mirrored" by + ;; c-fl-syn-tab text properties. + (when (and c-min-syn-tab-mkr c-max-syn-tab-mkr) + (let ((pos c-min-syn-tab-mkr)) + (while + (and + (< pos c-max-syn-tab-mkr) + (setq pos + (c-min-property-position pos c-max-syn-tab-mkr 'c-fl-syn-tab)) + (< pos c-max-syn-tab-mkr)) + (c-put-char-property pos 'syntax-table + (c-get-char-property pos 'c-fl-syn-tab)) + (setq pos (1+ pos)))))) (defvar c-bc-changed-stringiness nil) ;; Non-nil when, in a before-change function, the deletion of a range of text @@ -1396,9 +1484,11 @@ Note that the style variables are always made local to the buffer." (c-will-be-escaped end beg end)) (c-remove-string-fences end) (goto-char (1+ end))) - ;; Are we unescaping a newline by inserting stuff between \ and \n? - ((and (eq end beg) - (c-is-escaped end)) + ;; Are we unescaping a newline ... + ((and + (c-is-escaped end) + (or (eq beg end) ; .... by inserting stuff between \ and \n? + (c-will-be-unescaped beg))) ; ... by removing an odd number of \s? (goto-char (1+ end))) ; To after the NL which is being unescaped. (t (goto-char end))) @@ -1406,7 +1496,7 @@ Note that the style variables are always made local to the buffer." ;; 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\\)\\|[^\\\n\r]\\)*" nil t) + (re-search-forward "\\(?:\\\\\\(?:.\\|\n\\)\\|[^\\\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)) @@ -1436,10 +1526,11 @@ Note that the style variables are always made local to the buffer." (not (c-characterp c-multiline-string-start-char)))) (when (and (eq end-literal-type 'string) (not (eq (char-before (cdr end-limits)) ?\()) - (memq (char-after (car end-limits)) c-string-delims) - (equal (c-get-char-property (car end-limits) 'syntax-table) - '(15))) - (c-remove-string-fences (car end-limits)) + (memq (char-after (car end-limits)) c-string-delims)) + (setq c-new-END (max c-new-END (cdr end-limits))) + (when (equal (c-get-char-property (car end-limits) 'syntax-table) + '(15)) + (c-remove-string-fences (car end-limits))) (setq c-new-END (max c-new-END (cdr end-limits)))) (when (and (eq beg-literal-type 'string) @@ -1512,9 +1603,13 @@ Note that the style variables are always made local to the buffer." ; 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\\)\\|[^\\\n\r]\\)*" + (goto-char + (if (and (memq (char-after end) '(?\n ?\r)) + (c-is-escaped end)) + (min (1+ end) ; 1+, if we're inside an escaped NL. + (point-max)) + end)) + (re-search-forward "\\(?:\\\\\\(?:.\\|\n\\)\\|[^\\\n\r]\\)*" nil t) (point)) c-new-END)) @@ -1595,7 +1690,7 @@ Note that the style variables are always made local to the buffer." (c-beginning-of-macro)))) (goto-char (1+ end)) ; After the \ ;; Search forward for EOLL - (setq lim (re-search-forward "\\(\\\\\\(.\\|\n\\)\\|[^\\\n\r]\\)*" + (setq lim (re-search-forward "\\(?:\\\\\\(?:.\\|\n\\)\\|[^\\\n\r]\\)*" nil t)) (goto-char (1+ end)) (when (c-search-forward-char-property-with-value-on-char @@ -1888,7 +1983,7 @@ Note that this is a strict tail, so won't match, e.g. \"0x....\".") (widen) (unwind-protect (progn - (c-restore-string-fences (point-min) (point-max)) + (c-restore-string-fences) (save-excursion ;; Are we inserting/deleting stuff in the middle of an ;; identifier? @@ -1907,7 +2002,7 @@ Note that this is a strict tail, so won't match, e.g. \"0x....\".") ;; We search for appropriate c-type properties "near" ;; the change. First, find an appropriate boundary ;; for this property search. - (let (lim + (let (lim lim-2 type type-pos marked-id term-pos (end1 @@ -1918,8 +2013,11 @@ Note that this is a strict tail, so won't match, e.g. \"0x....\".") (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 "^;{}") 0) + (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)))) @@ -1943,7 +2041,8 @@ Note that this is a strict tail, so won't match, e.g. \"0x....\".") (buffer-substring-no-properties (point) type-pos))) (goto-char end1) - (skip-chars-forward "^;{}") ; FIXME!!! loop for + (setq lim-2 (c-determine-+ve-limit 1000)) + (skip-chars-forward "^;{}" lim-2) ; FIXME!!! loop for ; comment, maybe (setq lim (point)) (setq term-pos @@ -1958,13 +2057,19 @@ Note that this is a strict tail, so won't match, e.g. \"0x....\".") (if c-get-state-before-change-functions (mapc (lambda (fn) (funcall fn beg end)) - c-get-state-before-change-functions)))) + c-get-state-before-change-functions)) + + (c-laomib-invalidate-cache beg end))) (c-clear-string-fences)))) (c-truncate-lit-pos-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 beg))) + (c-invalidate-state-cache beg) + ;; The following must happen after the previous, which likely alters + ;; the macro cache. + (when c-opt-cpp-symbol + (c-invalidate-macro-cache beg end)))) (defvar c-in-after-change-fontification nil) (make-variable-buffer-local 'c-in-after-change-fontification) @@ -2018,7 +2123,7 @@ Note that this is a strict tail, so won't match, e.g. \"0x....\".") (widen) (unwind-protect (progn - (c-restore-string-fences (point-min) (point-max)) + (c-restore-string-fences) (when (> end (point-max)) ;; Some emacsen might return positions past the end. This ;; has been observed in Emacs 20.7 when rereading a buffer @@ -2109,7 +2214,8 @@ Note that this is a strict tail, so won't match, e.g. \"0x....\".") old-pos (new-pos pos) capture-opener - bod-lim bo-decl) + bod-lim bo-decl + paren-state containing-brace) (goto-char (c-point 'bol new-pos)) (unless lit-start (setq bod-lim (c-determine-limit 500)) @@ -2128,12 +2234,16 @@ Note that this is a strict tail, so won't match, e.g. \"0x....\".") (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)))))) + (and + ;; N.B. `c-syntactic-skip-backward' doesn't check (> (point) + ;; lim) and can loop if that's not the case. + (> (point) bod-lim) + (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) @@ -2166,7 +2276,14 @@ Note that this is a strict tail, so won't match, e.g. \"0x....\".") (and (eq (char-before) ?{) (save-excursion (backward-char) - (consp (c-looking-at-or-maybe-in-bracelist)))) + (setq paren-state (c-parse-state)) + (while + (and + (setq containing-brace + (c-pull-open-brace paren-state)) + (not (eq (char-after containing-brace) ?{)))) + (consp (c-looking-at-or-maybe-in-bracelist + containing-brace containing-brace)))) ))) (not (bobp))) (backward-char)) ; back over (, [, <. @@ -2177,25 +2294,47 @@ Note that this is a strict tail, so won't match, e.g. \"0x....\".") (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. POS being in a literal does not - ;; count as being in a declarator (on pragmatic grounds). + ;; count as being in a declarator (on pragmatic grounds). POINT is not + ;; preserved. (goto-char pos) (let ((lit-start (c-literal-start)) + (lim (c-determine-limit 1000)) enclosing-attribute pos1) (unless lit-start - (c-backward-syntactic-ws) - (when (setq enclosing-attribute (c-slow-enclosing-c++-attribute)) + (c-backward-syntactic-ws + lim) + (when (setq enclosing-attribute (c-enclosing-c++-attribute)) (goto-char (car enclosing-attribute))) ; Only happens in C++ Mode. (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))))))) + (and (c-forward-declarator lim) + (if (eq (char-after) ?\() + (and + (c-go-list-forward nil lim) + (progn (c-forward-syntactic-ws lim) + (not (eobp))) + (progn + (if (looking-at c-symbol-char-key) + ;; Deal with baz (foo((bar)) type var), where + ;; foo((bar)) is not semantically valid. The result + ;; must be after var). + (and + (goto-char pos) + (setq pos1 (c-on-identifier)) + (goto-char pos1) + (progn + (c-backward-syntactic-ws lim) + (eq (char-before) ?\()) + (c-fl-decl-end (1- (point)))) + (c-backward-syntactic-ws lim) + (point)))) + (and (progn (c-forward-syntactic-ws lim) + (not (eobp))) + (c-backward-syntactic-ws lim) + (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 @@ -2255,69 +2394,48 @@ Note that this is a strict tail, so won't match, e.g. \"0x....\".") ;; line was fouled up by context fontification. (save-restriction (widen) - (let (new-beg new-end new-region case-fold-search string-fence-beg lim) - ;; Check how far back we need to extend the region where we reapply the - ;; string fence syntax-table properties. These must be in place for the - ;; coming fontification operations. - (save-excursion - (goto-char (if c-in-after-change-fontification - (min beg c-new-BEG) - beg)) - (setq lim (max (- (point) 500) (point-min))) - (while + (let (new-beg new-end new-region case-fold-search) + (c-save-buffer-state nil + ;; Temporarily reapply the string fence syntax-table properties. + (unwind-protect (progn - (skip-chars-backward "^\"" lim) - (or (bobp) (backward-char)) - (save-excursion - (eq (logand (skip-chars-backward "\\\\") 1) 1)))) - (setq string-fence-beg - (cond ((c-get-char-property (point) 'c-fl-syn-tab) - (point)) - (c-in-after-change-fontification - c-new-BEG) - (t beg))) - (c-save-buffer-state nil - ;; Temporarily reapply the string fence syntax-table properties. - (c-with-extended-string-fences - string-fence-beg (if c-in-after-change-fontification - (max end c-new-END) - end) - - (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))) - ;; Finally invoke font lock's functionality. - (funcall (default-value 'font-lock-fontify-region-function) - new-beg new-end verbose))))))) + (c-restore-string-fences) + (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))) + ;; Finally invoke font lock's functionality. + (funcall (default-value 'font-lock-fontify-region-function) + new-beg new-end verbose)) + (c-clear-string-fences)))))) (defun c-after-font-lock-init () ;; Put on `font-lock-mode-hook'. This function ensures our after-change @@ -2444,11 +2562,6 @@ opening \" and the next unescaped end of line." (funcall (c-lang-const c-make-mode-syntax-table c)) "Syntax table used in c-mode buffers.") -(c-define-abbrev-table 'c-mode-abbrev-table - '(("else" "else" c-electric-continued-statement 0) - ("while" "while" c-electric-continued-statement 0)) - "Abbreviation table used in c-mode buffers.") - (defvar c-mode-map (let ((map (c-make-inherited-keymap))) map) @@ -2514,20 +2627,29 @@ Key bindings: (setq abbrev-mode t) (c-init-language-vars-for 'c-mode) (c-common-init 'c-mode) - (easy-menu-add c-c-menu) + (when (featurep 'xemacs) + (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 (eval-when-compile - (let ((id "[a-zA-Z0-9_]+") (ws "[ \t\r]+") (ws-maybe "[ \t\r]*")) + (let ((id "[a-zA-Z_][a-zA-Z0-9_]*") (ws "[ \t]+") (ws-maybe "[ \t]*") + (headers '("string" "string_view" "iostream" "map" "unordered_map" + "set" "unordered_set" "vector" "tuple"))) (concat "^" ws-maybe "\\(?:" - "using" ws "\\(?:namespace" ws "std;\\|std::\\)" - "\\|" "namespace" "\\(:?" ws id "\\)?" ws-maybe "{" - "\\|" "class" ws id ws-maybe "[:{\n]" - "\\|" "template" ws-maybe "<.*>" - "\\|" "#include" ws-maybe "<\\(?:string\\|iostream\\|map\\)>" + "using" ws "\\(?:namespace" ws + "\\|" id "::" + "\\|" id ws-maybe "=\\)" + "\\|" "\\(?:inline" ws "\\)?namespace" + "\\(:?" ws "\\(?:" id "::\\)*" id "\\)?" ws-maybe "{" + "\\|" "class" ws id + "\\(?:" ws "final" "\\)?" ws-maybe "[:{;\n]" + "\\|" "struct" ws id "\\(?:" ws "final" ws-maybe "[:{\n]" + "\\|" ws-maybe ":\\)" + "\\|" "template" ws-maybe "<.*?>" + "\\|" "#include" ws-maybe "<" (regexp-opt headers) ">" "\\)"))) "A regexp applied to C header files to check if they are really C++.") @@ -2543,6 +2665,7 @@ should be used. This function attempts to use file contents to determine whether the code is C or C++ and based on that chooses whether to enable `c-mode' or `c++-mode'." + (interactive) (if (save-excursion (save-restriction (save-match-data @@ -2560,12 +2683,6 @@ the code is C or C++ and based on that chooses whether to enable (funcall (c-lang-const c-make-mode-syntax-table c++)) "Syntax table used in c++-mode buffers.") -(c-define-abbrev-table 'c++-mode-abbrev-table - '(("else" "else" c-electric-continued-statement 0) - ("while" "while" c-electric-continued-statement 0) - ("catch" "catch" c-electric-continued-statement 0)) - "Abbreviation table used in c++-mode buffers.") - (defvar c++-mode-map (let ((map (c-make-inherited-keymap))) map) @@ -2602,7 +2719,8 @@ Key bindings: (setq abbrev-mode t) (c-init-language-vars-for 'c++-mode) (c-common-init 'c++-mode) - (easy-menu-add c-c++-menu) + (when (featurep 'xemacs) + (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)) @@ -2614,11 +2732,6 @@ Key bindings: (funcall (c-lang-const c-make-mode-syntax-table objc)) "Syntax table used in objc-mode buffers.") -(c-define-abbrev-table 'objc-mode-abbrev-table - '(("else" "else" c-electric-continued-statement 0) - ("while" "while" c-electric-continued-statement 0)) - "Abbreviation table used in objc-mode buffers.") - (defvar objc-mode-map (let ((map (c-make-inherited-keymap))) map) @@ -2654,7 +2767,8 @@ Key bindings: (setq abbrev-mode t) (c-init-language-vars-for 'objc-mode) (c-common-init 'objc-mode) - (easy-menu-add c-objc-menu) + (when (featurep 'xemacs) + (easy-menu-add c-objc-menu)) (cc-imenu-init nil 'cc-imenu-objc-function) (c-run-mode-hooks 'c-mode-common-hook)) @@ -2665,13 +2779,6 @@ Key bindings: (funcall (c-lang-const c-make-mode-syntax-table java)) "Syntax table used in java-mode buffers.") -(c-define-abbrev-table 'java-mode-abbrev-table - '(("else" "else" c-electric-continued-statement 0) - ("while" "while" c-electric-continued-statement 0) - ("catch" "catch" c-electric-continued-statement 0) - ("finally" "finally" c-electric-continued-statement 0)) - "Abbreviation table used in java-mode buffers.") - (defvar java-mode-map (let ((map (c-make-inherited-keymap))) map) @@ -2683,7 +2790,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-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))) @@ -2711,7 +2818,8 @@ Key bindings: (setq abbrev-mode t) (c-init-language-vars-for 'java-mode) (c-common-init 'java-mode) - (easy-menu-add c-java-menu) + (when (featurep 'xemacs) + (easy-menu-add c-java-menu)) (cc-imenu-init cc-imenu-java-generic-expression) (c-run-mode-hooks 'c-mode-common-hook)) @@ -2722,9 +2830,6 @@ Key bindings: (funcall (c-lang-const c-make-mode-syntax-table idl)) "Syntax table used in idl-mode buffers.") -(c-define-abbrev-table 'idl-mode-abbrev-table nil - "Abbreviation table used in idl-mode buffers.") - (defvar idl-mode-map (let ((map (c-make-inherited-keymap))) map) @@ -2756,7 +2861,8 @@ Key bindings: (c-initialize-cc-mode t) (c-init-language-vars-for 'idl-mode) (c-common-init 'idl-mode) - (easy-menu-add c-idl-menu) + (when (featurep 'xemacs) + (easy-menu-add c-idl-menu)) ;;(cc-imenu-init cc-imenu-idl-generic-expression) ;TODO (c-run-mode-hooks 'c-mode-common-hook)) @@ -2767,11 +2873,6 @@ Key bindings: (funcall (c-lang-const c-make-mode-syntax-table pike)) "Syntax table used in pike-mode buffers.") -(c-define-abbrev-table 'pike-mode-abbrev-table - '(("else" "else" c-electric-continued-statement 0) - ("while" "while" c-electric-continued-statement 0)) - "Abbreviation table used in pike-mode buffers.") - (defvar pike-mode-map (let ((map (c-make-inherited-keymap))) map) @@ -2806,7 +2907,8 @@ Key bindings: (setq abbrev-mode t) (c-init-language-vars-for 'pike-mode) (c-common-init 'pike-mode) - (easy-menu-add c-pike-menu) + (when (featurep 'xemacs) + (easy-menu-add c-pike-menu)) ;;(cc-imenu-init cc-imenu-pike-generic-expression) ;TODO (c-run-mode-hooks 'c-mode-common-hook)) @@ -2819,11 +2921,6 @@ Key bindings: ;;;###autoload (add-to-list 'interpreter-mode-alist '("nawk" . awk-mode)) ;;;###autoload (add-to-list 'interpreter-mode-alist '("gawk" . awk-mode)) -(c-define-abbrev-table 'awk-mode-abbrev-table - '(("else" "else" c-electric-continued-statement 0) - ("while" "while" c-electric-continued-statement 0)) - "Abbreviation table used in awk-mode buffers.") - (defvar awk-mode-map (let ((map (c-make-inherited-keymap))) map) diff --git a/lisp/progmodes/cc-styles.el b/lisp/progmodes/cc-styles.el index e0dc9e83c7..aec259f1b3 100644 --- a/lisp/progmodes/cc-styles.el +++ b/lisp/progmodes/cc-styles.el @@ -395,8 +395,7 @@ a null operation." ;; remain. This is not necessary for c-offsets-alist, since ;; c-get-style-variables contains every valid offset type in the ;; fallback entry. - (setq c-special-indent-hook - (default-value 'c-special-indent-hook))) + (kill-local-variable 'c-special-indent-hook)) (mapc (lambda (elem) (c-set-style-1 elem dont-override)) ;; Need to go through the variables backwards when we @@ -644,7 +643,7 @@ CC Mode by making sure the proper entries are present on (defun c-make-styles-buffer-local (&optional this-buf-only-p) "Make all CC Mode style variables buffer local. -If `this-buf-only-p' is non-nil, the style variables will be made +If THIS-BUF-ONLY-P is non-nil, the style variables will be made buffer local only in the current buffer. Otherwise they'll be made permanently buffer local in any buffer that changes their values. @@ -662,7 +661,6 @@ any reason to call this function directly." ;; Hooks must be handled specially (if this-buf-only-p (if (featurep 'xemacs) (make-local-hook 'c-special-indent-hook)) - (with-no-warnings (make-variable-buffer-local 'c-special-indent-hook)) (setq c-style-variables-are-local-p t)) )) diff --git a/lisp/progmodes/cc-vars.el b/lisp/progmodes/cc-vars.el index 407dcbac1b..88ee092da7 100644 --- a/lisp/progmodes/cc-vars.el +++ b/lisp/progmodes/cc-vars.el @@ -575,7 +575,9 @@ comment styles: javadoc -- Javadoc style for \"/** ... */\" comments (default in Java mode). autodoc -- Pike autodoc style for \"//! ...\" comments (default in Pike mode). - gtkdoc -- GtkDoc style for \"/** ... **/\" comments (default in C and C++ modes). + gtkdoc -- GtkDoc style for \"/** ... **/\" comments + (default in C and C++ modes). + doxygen -- Doxygen style. The value may also be a list of doc comment styles, in which case all of them are recognized simultaneously (presumably with markup cues @@ -1649,6 +1651,15 @@ white space either before or after the operator, but not both." :type 'boolean :group 'c) +(defcustom c-cpp-indent-to-body-directives '("pragma") + "Preprocessor directives which will be indented as statements. + +A list of Preprocessor directives which when reindented, or newly +typed in, will cause the \"#\" introducing the directive to be +indented as a statement." + :type '(repeat string) + :group 'c) + ;; Initialize the next two to a regexp which never matches. (defvar c-noise-macro-with-parens-name-re regexp-unmatchable) (make-variable-buffer-local 'c-noise-macro-with-parens-name-re) @@ -1660,7 +1671,8 @@ white space either before or after the operator, but not both." like \"INLINE\" which are syntactic noise. Such a macro/extension is complete in itself, never having parentheses. All these names must be syntactically valid identifiers. Alternatively, this variable may be a regular expression -which matches the names of such macros. +which matches the names of such macros, in which case it must have a submatch +1 which matches the actual noise macro name. If you change this variable's value, call the function `c-make-noise-macro-regexps' to set the necessary internal variables (or do @@ -1676,7 +1688,8 @@ this implicitly by reinitializing C/C++/Objc Mode on any buffer)." which optionally have arguments in parentheses, and which expand to nothing. All these names must be syntactically valid identifiers. These are recognized by CC Mode only in declarations. Alternatively, this variable may be a -regular expression which matches the names of such macros. +regular expression which matches the names of such macros, in which case it +must have a submatch 1 which matches the actual noise macro name. If you change this variable's value, call the function `c-make-noise-macro-regexps' to set the necessary internal variables (or do
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor