From: Gerd Moellmann Date: Wed, 21 Mar 2001 12:59:36 +0000 (+0000) Subject: Update to version 5.28. X-Git-Tag: emacs-pretest-21.0.101~223 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=130c507e58dc58cd41a01288565902922d87409a;p=emacs.git Update to version 5.28. --- diff --git a/lisp/ChangeLog b/lisp/ChangeLog index e094f5cc0b2..5473ab98fd7 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -6,6 +6,372 @@ * mail/sendmail.el (sendmail-send-it): Don't parse Resent-* headers. Always invoke sendmail with option -t. +2000-03-21 Martin Stjernholm + + * Release of cc-mode 5.28. + +2000-03-21 Martin Stjernholm + + * cc-mode.el, cc-vars.el (c-common-init, c-default-style): + Removed the hardcoded switch to "java" style in Java mode. + It's instead taken care of by the default value for + c-default-style. + + * cc-mode.texi: Updated the mentions of the "java" style + special case for Java mode. + +2000-03-21 Martin Stjernholm + + * cc-align.el (c-lineup-math): Fix bug where lineup was + triggered by equal signs in string literals. + +2000-03-21 Martin Stjernholm + + * cc-cmds.el (c-fill-paragraph): Fixed bug in the paragraph + limit detection when at the ends of the buffer. + + * cc-engine.el (c-guess-basic-syntax): Removed bogus check for + "for" statement clause in case 7F; a better one is done + earlier in case 7D anyway. + +2000-03-21 Martin Stjernholm + + * cc-cmds.el (c-guess-fill-prefix): Improved the heuristics + somewhat more and did a small optimization. + +2000-03-21 Martin Stjernholm + + * cc-cmds.el (c-beginning-of-statement, c-end-of-statement): + Use the limit argument only to limit the syntactic context + search, not to limit the actual movement. + + * cc-cmds.el (c-beginning-of-statement): Move by sentence + inside multiline strings, just like in comments. Also various + fixes to the paragraph and comment prefix recognition, block + comment ender handling etc. + +2000-03-21 Martin Stjernholm + + * cc-cmds.el (c-fill-paragraph): Take more care to preserve + the relative position of the point. + + * cc-cmds.el (c-electric-continued-statement): New function to + use as abbrev hook to reindent for keywords such as "else" + that continues an earlier statement. + + * cc-menus.el (cc-imenu-c++-generic-expression): Treat structs + like classes. + + * cc-mode.el (c-mode, c++-mode, java-mode, objc-mode) + (pike-mode): Populate the default abbrev tables to reindent for + keywords such as "else" that can continue earlier statements. + Abbrev mode is therefore turned on by default now. (Note that + this doesn't apply to idl-mode, since IDL afaik doesn't have + statements at all.) + +2000-03-21 Martin Stjernholm + + * cc-engine.el (c-inside-bracelist-p): Fix for handling + bracelists where the declaration contains template arguments. + +2000-03-21 Martin Stjernholm + + * cc-cmds.el (c-comment-indent): Use + `c-get-syntactic-indentation' to correctly calculate the + syntactic indentation. Fixes bug with lineup functions that + return vectors. + + * cc-engine.el (c-get-syntactic-indentation): Split the + indentation sum calculation from `c-indent-line' to a separate + function. + +2000-03-21 Martin Stjernholm + + * cc-cmds.el (c-beginning-of-statement, c-comment-indent): + Fixed places where it was assumed that preprocessor directives + have to start in column zero. + + * cc-engine.el (c-beginning-of-member-init-list): Handle C++ + template arguments after a class identifier properly. + + * cc-engine.el (c-guess-basic-syntax): Treat initializer brace + lists for `new Foo[]' constructs in Java as expressions and + not top level definition brace lists on the top level, so that + they'll get indented consistently with the same type of + expression in a normal block. + +2000-03-21 Martin Stjernholm + + * cc-cmds.el (c-fill-paragraph): The kludge that checks + whether the adaptive filling package fails to keep the comment + prefix is now kludged further to check for filladapt-mode + which doesn't have that problem. This is really icky, but it's + the only way that works with the current misfeatures/bugs in + both adaptive-fill-mode and filladapt-mode. + + * cc-cmds.el (c-fill-paragraph): Made the way the paragraph + around point is recognized more robust. + +2000-03-21 Martin Stjernholm + + * cc-cmds.el, cc-engine.el, cc-lobotomy.el (c-state-cache) + (c-in-literal-cache, c-auto-fill-prefix, c-lit-limits) + (c-lit-type): Fixed all internal variables used dynamically so + that they are always bound. + + * cc-cmds.el, cc-engine.el: Improved recovery of syntactic + errors: + + (c-indent-region): Fixed reporting of syntactic errors so that + the region is fully reindented even when an error occurs. The + last syntactic error is printed afterwards. Also cleanup up a + whole lot of code that tried to optimize indentation of whole + sexps but in reality accomplishes nothing. + + (c-indent-sexp): Use c-indent-region. + + (c-parsing-error): Changed this variable to hold the message + for any syntactic error that is discovered. + + (c-parse-state): Search backward from point instead of the bod + position when the latter is invalid. This makes CC Mode + recover faster when there are unbalanced close braces. + + (c-backward-to-start-of-if): Use c-parsing-error to report + dangling "else" clauses instead of throwing an error, and fall + back to a reasonable position. + + (c-indent-line): Added argument to avoid reporting syntactic + errors. + + (c-show-syntactic-information): Don't report any syntactic + errors. + +2000-03-21 Martin Stjernholm + + * cc-cmds.el (c-beginning-of-statement): Fixed bugs with + paragraph recognition when moving by sentence in literals. + + * cc-langs.el (c-Java-javadoc-paragraph-start): Modified + paragraph start regexp for javadoc to recognize javadoc markup + in general instead of a specific set of keywords, to be more + future-safe. + + (c-Pike-pikedoc-paragraph-start) + (c-Pike-pikedoc-paragraph-separate): New regexps to recognize + pikedoc markup. + + * cc-mode.el: Fixed initialization and use of + c-current-comment-prefix. + + (pike-mode): Initialize paragraph settings pikedoc + recognition. + + * cc-vars.el (c-default-style): Made a nicer Customize widget. + + (c-comment-prefix-regexp): Made it possible to use an + association list on this to specify mode specific regexps. + The default value now use a special regexp in Pike mode to + recognize pikedoc markup. + + (c-current-comment-prefix): New variable containing the actual + regexp from c-comment-prefix-regexp for the current buffer. + +2000-03-21 Martin Stjernholm + + * cc-cmds.el (c-electric-brace): Fixed check for special brace + lists: We can't look at the syntax, since a brace list can get + recognized as a plain statement-cont. + + * cc-engine.el (c-guess-basic-syntax): Fixed bug where a + special brace list opener broken over two lines got recognized + as a statement on the second line. Case 9A changed. + +2000-03-21 Martin Stjernholm + + * cc-cmds.el (c-electric-brace): Fixed bug in c-state-cache + adjustment after line is reindented. + +2000-03-21 Martin Stjernholm + + * cc-defs.el (c-point): Added optional argument for position + to use instead of the current point. + + * cc-defs.el, cc-engine.el (c-add-class-syntax): Do not add + the in-expression block symbols when the construct starts at + boi, to avoid the extra level of indentation in that case. + Cases 4, 16A and 17E affected. + +2000-03-21 Martin Stjernholm + + * cc-cmds.el: Use `indent-according-to-mode' instead of direct + calls to `c-indent-line', to adhere better to Emacs + conventions. + + * cc-engine.el (c-indent-line): Use the syntax already bound + to `c-syntactic-context', if there is any. + +2000-03-21 Martin Stjernholm + + * cc-engine.el (c-get-offset): Fixed bug where the indentation + wasn't added up correctly when a lineup function returned nil. + +2000-03-21 Martin Stjernholm + + * cc-engine.el (c-collect-line-comments): Fixed bug where + empty lines were ignored when collecting line comments + backwards. + +2000-03-21 Martin Stjernholm + + * cc-align.el (c-lineup-dont-change): Return an absolute + indentation column to work correctly in the case when several + syntactic elements are processed for the same line. + + * cc-engine.el, cc-styles.el, cc-vars.el (c-evaluate-offset) + (c-get-offset, c-indent-line, c-valid-offset, c-read-offset) + (c-set-offset): Added absolute indentation column settings by + using the vector type. + + * cc-mode.texi: Documented the new vector setting for offsets. + +2000-03-21 Martin Stjernholm + + * cc-cmds.el, cc-vars.el (c-electric-paren, c-cleanup-list): + Implemented two new cleanups `space-before-funcall' and + `compact-empty-funcall'. + + * cc-mode.texi: Documented the two new cleanups + space-before-funcall and compact-empty-funcall on + c-cleanup-list. + +2000-03-21 Martin Stjernholm + + * cc-defs.el (c-paren-re, c-identifier-re): Two new macros for + helping building regexps. + + * cc-engine.el (c-on-identifier): New function for detecting + identifiers. It takes keywords into account. + + * cc-langs.el, cc-mode.el: Added regexps for complete keyword + lists. `c-keywords' is set to a regexp matching all keywords + in the current language. + +2000-03-21 Martin Stjernholm + + * cc-engine.el (c-beginning-of-statement-1): Added '#' to the + list of characters to skip backwards over at the beginning of + a statement, since it can precede string literals in Pike. + +2000-03-21 Martin Stjernholm + + * cc-cmds.el (c-guess-fill-prefix): Fixed bug with prefix + recognition when standing on the last line in a C++ comment + with nothing but whitespace after the prefix. + + * cc-engine.el (c-backward-to-start-of-if): Fixed bug when + given no limit argument. + +2000-03-21 Martin Stjernholm + + * cc-engine.el (c-inside-bracelist-p): Fixed brace list + recognition for the `[]= operator symbol in Pike. + +2000-03-21 Martin Stjernholm + + * cc-bytecomp.el (cc-eval-when-compile): New macro that works + around a bug in `eval-when-compile' in the byte compiler. + + * cc-engine.el (c-forward-token-1): Fixed bug with return + value when count is zero and there's no token start within the + limit. + + (c-guess-basic-syntax): Don't add 'comment-intro to lines with + "prefix comments", i.e. comments which are followed by code on + the same line. + + * cc-mode-19.el: Fixes so that checks that must be done at + compile time also are done then. + +2000-03-21 Martin Stjernholm + + * cc-defs.el: Make sure cc-mode-19 is loaded both at compile + time and at runtime, and only when it's needed. + +2000-03-21 Martin Stjernholm + + Major cleanup for less error prone and more warning free + compilation, including some fixes for bugs due to different + compilation orders. Thanks to Martin Buchholz for providing + the basis for all this. + + * cc-bytecomp.el: New file that provides some byte compilation + features: It ensures that files always are loaded from the + current source directory during compilation, and it provides a + set of macros to turn off specific compiler warnings for + specific symbols. (It's not CC Mode specific in any way.) + + Fixed a nearly acyclic dependency tree (both runtime and + compile-time) between all files. + + * cc-defs.el: Separated all macros before the inline functions, + to ensure correct compilation. + + * cc-defs.el, cc-engine.el: Moved c-beginning-of-macro to from + cc-defs.el to cc-engine.el and made it a function instead. + + * cc-mode-19.el: Patch the byte compiler in Emacs 19 not to warn + about char-after. + + * cc-vars.el: Cope even when there isn't a custom package + containing defcustom available. + + * cc-make.el: Removed since it's no longer necessary. + + README: Updated installation instructions. + +2000-03-21 Martin Stjernholm + + * cc-cmds.el, cc-langs.el, cc-mode.el: Moved around things to + improve the modularity: Moved all mode init stuff from + cc-langs.el to cc-mode.el, including the keymap + initialization; cc-langs now only contains the various + variables for configuring the language syntax. + + * cc-engine.el, cc-styles.el (c-evaluate-offset, + c-get-offset): Moved from cc-styles to cc-engine since file + dependency analysis suggests they belong there (which also + makes more sense). Thanks to Martin Buchholz for doing the + analysis. + +2000-03-21 Martin Stjernholm + + * cc-cmds.el (c-fn-region-is-active-p): New function that + wraps the corresponding macro, for use in places that aren't + compiled. Thanks to Martin Buchholz for pointing out this. + + * cc-langs.el (c-mode-menu): Use c-fn-region-is-active-p. + + * cc-mode.el (c-prepare-bug-report-hooks): Hook variable to + add things to the bug report. + +2000-03-21 Martin Stjernholm + + * cc-cmds.el (c-guess-fill-prefix): Fixed bug where the + returned prefix could contain a newline when the search for a + good prefix line failed. + +2000-03-21 Martin Stjernholm + + * cc-cmds.el (c-toggle-auto-state, c-toggle-hungry-state) + (c-toggle-auto-hungry-state): Made the argument optional, as + the documentation says it is. + +2000-03-21 Martin Stjernholm + + * cc-engine.el (c-guess-basic-syntax): Don't treat the Pike + multiline string syntax, #"...", as a cpp macro. + 2001-03-21 Paul Eggert * international/mule-cmds.el (set-locale-environment): Set diff --git a/lisp/progmodes/cc-align.el b/lisp/progmodes/cc-align.el index 8bb69e387c8..c5c8786085c 100644 --- a/lisp/progmodes/cc-align.el +++ b/lisp/progmodes/cc-align.el @@ -1,6 +1,6 @@ ;;; cc-align.el --- custom indentation functions for CC Mode -;; Copyright (C) 1985,87,92,93,94,95,96,97,98,99,2000 Free Software Foundation, Inc. +;; Copyright (C) 1985,1987,1992-2001 Free Software Foundation, Inc. ;; Authors: 2000- Martin Stjernholm ;; 1998-1999 Barry A. Warsaw and Martin Stjernholm @@ -25,19 +25,22 @@ ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs; see the file COPYING. If not, write to the -;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; along with this program; see the file COPYING. If not, write to +;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, ;; Boston, MA 02111-1307, USA. (eval-when-compile (let ((load-path - (if (and (boundp 'byte-compile-current-file) - (stringp byte-compile-current-file)) - (cons (file-name-directory byte-compile-current-file) - load-path) + (if (and (boundp 'byte-compile-dest-file) + (stringp byte-compile-dest-file)) + (cons (file-name-directory byte-compile-dest-file) load-path) load-path))) - (load "cc-defs" nil t))) -(require 'cc-engine) + (require 'cc-bytecomp))) + +(cc-require 'cc-defs) +(cc-require 'cc-vars) +(cc-require 'cc-langs) +(cc-require 'cc-engine) ;; Standard indentation line-ups @@ -254,9 +257,9 @@ if (n > 0) if (n > 0) <--> c-basic-offset m+=n; n=0; } -The block may be surrounded by any kind of parenthesis characters. -nil is returned if the line doesn't start with a one line block, which -makes the function usable in list expressions. +The block may use any kind of parenthesis character. nil is returned +if the line doesn't start with a one line block, which makes the +function usable in list expressions. Work with: Almost all syntactic symbols, but most useful on *-open." (save-excursion @@ -279,9 +282,9 @@ int *foo[] = { int *foo[] = { } <--> c-basic-offset -The block may be surrounded by any kind of parenthesis characters. -nil is returned if the line doesn't start with a multi line block, -which makes the function usable in list expressions. +The block may use any kind of parenthesis character. nil is returned +if the line doesn't start with a multi line block, which makes the +function usable in list expressions. Work with: Almost all syntactic symbols, but most useful on *-open." (save-excursion @@ -295,7 +298,7 @@ Work with: Almost all syntactic symbols, but most useful on *-open." (defun c-lineup-C-comments (langelem) "Line up C block comment continuation lines. -Various heuristics are used to handle most of the common comment +Various heuristics are used to handle many of the common comment styles. Some examples: /* /** /* /* text /* /** @@ -322,7 +325,7 @@ Works with: The `c' syntactic symbol." (save-excursion (let* ((here (point)) (prefixlen (progn (back-to-indentation) - (if (looking-at c-comment-prefix-regexp) + (if (looking-at c-current-comment-prefix) (- (match-end 0) (point)) 0))) (starterlen (save-excursion @@ -369,11 +372,11 @@ Works with: The `c' syntactic symbol." ;; line has a nonempty comment prefix, align with it. ;; Otherwise, align with the previous nonempty line, but ;; align the comment ender with the starter. - (when (or (not (looking-at c-comment-prefix-regexp)) + (when (or (not (looking-at c-current-comment-prefix)) (eq (match-beginning 0) (match-end 0))) (goto-char here) (back-to-indentation) - (if (looking-at (concat "\\(" c-comment-prefix-regexp "\\)\\*/")) + (if (looking-at (concat "\\(" c-current-comment-prefix "\\)\\*/")) (goto-char (cdr langelem)) (while (and (zerop (forward-line -1)) (looking-at "^[ \t]*$"))) @@ -392,19 +395,13 @@ line, that alignment is preserved. Works with: comment-intro." (save-excursion (back-to-indentation) - ;; this highly kludgiforous flag prevents the mapcar over - ;; c-syntactic-context from entering an infinite loop - (let ((recurse-prevention-flag (boundp 'recurse-prevention-flag)) - (col (current-column))) + (let ((col (current-column))) (cond - (recurse-prevention-flag 0) ;; CASE 1: preserve aligned comments ((save-excursion (and (c-forward-comment -1) (= col (current-column)))) - ;; we have to subtract out all other indentation - (- col (apply '+ (mapcar 'c-get-offset - c-syntactic-context)))) + (vector col)) ; Return an absolute column. ;; indent as specified by c-comment-only-line-offset ((not (bolp)) (or (car-safe c-comment-only-line-offset) @@ -446,7 +443,10 @@ Works with: statement-cont." (save-excursion (let ((equalp (save-excursion (goto-char (c-point 'boi)) - (skip-chars-forward "^=" (c-point 'eol)) + (let ((eol (c-point 'eol))) + (c-forward-token-1 0 t eol) + (while (and (not (eq (char-after) ?=)) + (= (c-forward-token-1 1 t eol) 0)))) (and (eq (char-after) ?=) (- (point) (c-point 'boi))))) (langelem-col (c-langelem-col langelem)) @@ -616,7 +616,7 @@ inextern-lang, innamespace." Works with: Any syntactic symbol." (save-excursion (back-to-indentation) - (- (current-column) (c-langelem-col langelem)))) + (vector (current-column)))) (defun c-snug-do-while (syntax pos) @@ -718,5 +718,5 @@ For other semicolon contexts, no determination is made." nil))) -(provide 'cc-align) +(cc-provide 'cc-align) ;;; cc-align.el ends here diff --git a/lisp/progmodes/cc-bytecomp.el b/lisp/progmodes/cc-bytecomp.el new file mode 100644 index 00000000000..1d2e44edad1 --- /dev/null +++ b/lisp/progmodes/cc-bytecomp.el @@ -0,0 +1,290 @@ +;;; cc-bytecomp.el --- Compile time setup for proper compilation + +;; Copyright (C) 2000, 01 Free Software Foundation, Inc. + +;; Author: Martin Stjernholm +;; Maintainer: bug-cc-mode@gnu.org +;; Created: 15-Jul-2000 +;; Version: See cc-mode.el +;; Keywords: c languages oop + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program; see the file COPYING. If not, write to +;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; This file is used to ensure that the CC Mode files are correctly +;; compiled regardless the environment (e.g. if an older CC Mode with +;; outdated macros are loaded during compilation). It also provides +;; features to defeat the compiler warnings for selected symbols. + + +(defvar cc-bytecomp-unbound-variables nil) +(defvar cc-bytecomp-original-functions nil) +(defvar cc-bytecomp-original-properties nil) +(defvar cc-bytecomp-load-depth 0) +(defvar cc-bytecomp-loaded-files nil) +(defvar cc-bytecomp-environment-set nil) + +(put 'cc-eval-when-compile 'lisp-indent-hook 0) +(defmacro cc-eval-when-compile (&rest body) + "Like `progn', but evaluates the body at compile time. +The result of the body appears to the compiler as a quoted constant. + +This variant works around what looks like a bug in +`eval-when-compile': During byte compilation it byte compiles its +contents before evaluating it. That can cause forms to be compiled in +situations they aren't intended to be compiled. See cc-bytecomp.el +for further discussion." + ;; + ;; Example: It's not possible to defsubst a primitive, e.g. the + ;; following will produce an error (in any emacs flavor), since + ;; `nthcdr' is a primitive function that's handled specially by the + ;; byte compiler and thus can't be redefined: + ;; + ;; (defsubst nthcdr (val) val) + ;; + ;; `defsubst', like `defmacro', needs to be evaluated at compile + ;; time, so this will produce an error during byte compilation. + ;; + ;; CC Mode occasionally needs to do things like this for cross-emacs + ;; compatibility (although we try to avoid it since it results in + ;; byte code that isn't compatible between emacsen). It therefore + ;; uses the following to conditionally do a `defsubst': + ;; + ;; (eval-when-compile + ;; (if (not (fboundp 'foo)) + ;; (defsubst foo ...))) + ;; + ;; But `eval-when-compile' byte compiles its contents and _then_ + ;; evaluates it (in all current emacs versions, up to and including + ;; Emacs 20.6 and XEmacs 21.1 as of this writing). So this will + ;; still produce an error, since the byte compiler will get to the + ;; defsubst anyway. That's arguably a bug because the point with + ;; `eval-when-compile' is that it should evaluate rather than + ;; compile its contents. + `(eval-when-compile (eval '(progn ,@body)))) + +(defun cc-bytecomp-setup-environment () + ;; Eval'ed during compilation to setup variables, functions etc + ;; declared with `cc-bytecomp-defvar' et al. + (if (= cc-bytecomp-load-depth 0) + (let (p) + (if cc-bytecomp-environment-set + (error "Byte compilation environment already set - \ +perhaps a `cc-bytecomp-restore-environment' is forgotten somewhere")) + (setq p cc-bytecomp-unbound-variables) + (while p + (if (not (boundp (car p))) + (progn + (eval `(defvar ,(car p))) + (set (car p) 'cc-bytecomp-ignore))) + (setq p (cdr p))) + (setq p cc-bytecomp-original-functions) + (while p + (let ((fun (car (car p))) + (temp-macro (car (cdr (car p))))) + (if temp-macro + (eval `(defmacro ,fun ,@temp-macro)) + (fset fun 'cc-bytecomp-ignore))) + (setq p (cdr p))) + (setq p cc-bytecomp-original-properties) + (while p + (let ((sym (car (car (car p)))) + (prop (cdr (car (car p)))) + (tempdef (car (cdr (car p))))) + (put sym prop tempdef)) + (setq p (cdr p))) + (setq cc-bytecomp-environment-set t)))) + +(defun cc-bytecomp-restore-environment () + ;; Eval'ed during compilation to restore variables, functions etc + ;; declared with `cc-bytecomp-defvar' et al. + (if (= cc-bytecomp-load-depth 0) + (let (p) + (setq p cc-bytecomp-unbound-variables) + (while p + (let ((var (car p))) + (if (and (boundp var) + (eq var 'cc-bytecomp-ignore)) + (makunbound var))) + (setq p (cdr p))) + (setq p cc-bytecomp-original-functions) + (while p + (let ((fun (car (car p))) + (def (car (cdr (cdr (car p)))))) + (if (and (fboundp fun) + (eq (symbol-function fun) 'cc-bytecomp-ignore)) + (if (eq def 'unbound) + (fmakunbound fun) + (fset fun def)))) + (setq p (cdr p))) + (setq p cc-bytecomp-original-properties) + (while p + (let ((sym (car (car (car p)))) + (prop (cdr (car (car p)))) + (tempdef (car (cdr (car p)))) + (origdef (cdr (cdr (car p))))) + (if (eq (get sym prop) tempdef) + (put sym prop origdef))) + (setq p (cdr p))) + (setq cc-bytecomp-environment-set nil)))) + +(defun cc-bytecomp-load (cc-part) + ;; Eval'ed during compilation to load a CC Mode file from the source + ;; directory (assuming it's the same as the compiled file + ;; destination dir). + (if (and (boundp 'byte-compile-dest-file) + (stringp byte-compile-dest-file)) + (progn + (cc-bytecomp-restore-environment) + (let ((cc-bytecomp-load-depth (1+ cc-bytecomp-load-depth)) + (load-path + (cons (file-name-directory byte-compile-dest-file) + load-path)) + (cc-file (concat cc-part ".el"))) + (if (member cc-file cc-bytecomp-loaded-files) + () + (setq cc-bytecomp-loaded-files + (cons cc-file cc-bytecomp-loaded-files)) + (load cc-file nil t t))) + (cc-bytecomp-setup-environment) + t))) + +(defmacro cc-require (cc-part) + "Force loading of the corresponding .el file in the current +directory during compilation, but compile in a `require'. Don't use +within `eval-when-compile'. + +Having cyclic cc-require's will result in infinite recursion. That's +somewhat intentional." + `(progn + (cc-eval-when-compile (cc-bytecomp-load (symbol-name ,cc-part))) + (require ,cc-part))) + +(defmacro cc-provide (feature) + "A replacement for the `provide' form that restores the environment +after the compilation. Don't use within `eval-when-compile'." + `(progn + (eval-when-compile (cc-bytecomp-restore-environment)) + (provide ,feature))) + +(defmacro cc-load (cc-part) + "Force loading of the corresponding .el file in the current +directory during compilation. Don't use outside `eval-when-compile' +or `eval-and-compile'. + +Having cyclic cc-load's will result in infinite recursion. That's +somewhat intentional." + `(or (and (featurep 'cc-bytecomp) + (cc-bytecomp-load ,cc-part)) + (load ,cc-part nil t nil))) + +(defun cc-bytecomp-is-compiling () + "Return non-nil if eval'ed during compilation. Don't use outside +`eval-when-compile'." + (and (boundp 'byte-compile-dest-file) + (stringp byte-compile-dest-file))) + +(defmacro cc-bytecomp-defvar (var) + "Binds the symbol as a variable during compilation of the file, +to silence the byte compiler. Don't use within `eval-when-compile'." + `(eval-when-compile + (if (boundp ',var) + nil + (if (not (memq ',var cc-bytecomp-unbound-variables)) + (setq cc-bytecomp-unbound-variables + (cons ',var cc-bytecomp-unbound-variables))) + (if (and (cc-bytecomp-is-compiling) + (= cc-bytecomp-load-depth 0)) + (progn + (defvar ,var) + (set ',var 'cc-bytecomp-ignore)))))) + +(defmacro cc-bytecomp-defun (fun) + "Bind the symbol as a function during compilation of the file, +to silence the byte compiler. Don't use within `eval-when-compile'." + `(eval-when-compile + (if (not (assq ',fun cc-bytecomp-original-functions)) + (setq cc-bytecomp-original-functions + (cons (list ',fun + nil + (if (fboundp ',fun) + (symbol-function ',fun) + 'unbound)) + cc-bytecomp-original-functions))) + (if (and (cc-bytecomp-is-compiling) + (= cc-bytecomp-load-depth 0) + (not (fboundp ',fun))) + (fset ',fun 'cc-bytecomp-ignore)))) + +(put 'cc-bytecomp-defmacro 'lisp-indent-function 'defun) +(defmacro cc-bytecomp-defmacro (fun &rest temp-macro) + "Bind the symbol as a macro during compilation (and evaluation) of the +file. Don't use outside `eval-when-compile'." + `(progn + (if (not (assq ',fun cc-bytecomp-original-functions)) + (setq cc-bytecomp-original-functions + (cons (list ',fun + ',temp-macro + (if (fboundp ',fun) + (symbol-function ',fun) + 'unbound)) + cc-bytecomp-original-functions))) + (defmacro ,fun ,@temp-macro))) + +(defmacro cc-bytecomp-put (symbol propname value) + "Set a property on a symbol during compilation (and evaluation) of +the file. Don't use outside `eval-when-compile'." + `(cc-eval-when-compile + (if (not (assoc (cons ,symbol ,propname) cc-bytecomp-original-properties)) + (setq cc-bytecomp-original-properties + (cons (cons (cons ,symbol ,propname) + (cons ,value (get ,symbol ,propname))) + cc-bytecomp-original-properties))) + (put ,symbol ,propname ,value))) + +(defmacro cc-bytecomp-obsolete-var (symbol) + "Suppress warnings about that the given symbol is an obsolete variable. +Don't use within `eval-when-compile'." + `(eval-when-compile + (if (get ',symbol 'byte-obsolete-variable) + (cc-bytecomp-put ',symbol 'byte-obsolete-variable nil)))) + +(defun cc-bytecomp-ignore-obsolete (form) + ;; Wraps a call to `byte-compile-obsolete' that suppresses the warning. + (let ((byte-compile-warnings + (delq 'obsolete (append byte-compile-warnings nil)))) + (byte-compile-obsolete form))) + +(defmacro cc-bytecomp-obsolete-fun (symbol) + "Suppress warnings about that the given symbol is an obsolete function. +Don't use within `eval-when-compile'." + `(eval-when-compile + (if (eq (get ',symbol 'byte-compile) 'byte-compile-obsolete) + (cc-bytecomp-put ',symbol 'byte-compile + 'cc-bytecomp-ignore-obsolete)))) + +;; Override ourselves with a version loaded from source if we're +;; compiling, like cc-require does for all the other files. +(if (and (cc-bytecomp-is-compiling) + (= cc-bytecomp-load-depth 0)) + (let ((load-path + (cons (file-name-directory byte-compile-dest-file) load-path)) + (cc-bytecomp-load-depth 1)) + (load "cc-bytecomp.el" nil t t))) + + +(provide 'cc-bytecomp) diff --git a/lisp/progmodes/cc-cmds.el b/lisp/progmodes/cc-cmds.el index cc5c3b9f9ce..ae905c08d86 100644 --- a/lisp/progmodes/cc-cmds.el +++ b/lisp/progmodes/cc-cmds.el @@ -1,6 +1,6 @@ ;;; cc-cmds.el --- user level commands for CC Mode -;; Copyright (C) 1985,87,92,93,94,95,96,97,98,99,2000 Free Software Foundation, Inc. +;; Copyright (C) 1985,1987,1992-2001 Free Software Foundation, Inc. ;; Authors: 2000- Martin Stjernholm ;; 1998-1999 Barry A. Warsaw and Martin Stjernholm @@ -25,19 +25,29 @@ ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs; see the file COPYING. If not, write to the -;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; along with this program; see the file COPYING. If not, write to +;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, ;; Boston, MA 02111-1307, USA. (eval-when-compile (let ((load-path - (if (and (boundp 'byte-compile-current-file) - (stringp byte-compile-current-file)) - (cons (file-name-directory byte-compile-current-file) - load-path) + (if (and (boundp 'byte-compile-dest-file) + (stringp byte-compile-dest-file)) + (cons (file-name-directory byte-compile-dest-file) load-path) load-path))) - (load "cc-defs" nil t))) -(require 'cc-engine) + (require 'cc-bytecomp))) + +(cc-require 'cc-defs) +(cc-require 'cc-vars) +(cc-require 'cc-langs) +(cc-require 'cc-engine) + +;; Silence the compiler. +(cc-bytecomp-defvar delete-key-deletes-forward) ; XEmacs 20+ +(cc-bytecomp-defun delete-forward-p) ; XEmacs 21+ +(cc-bytecomp-obsolete-fun insert-and-inherit) ; Marked obsolete in XEmacs 19 +(cc-bytecomp-defvar filladapt-mode) ; c-fill-paragraph contains a kludge + ; which looks at this. (defun c-calculate-state (arg prevstate) @@ -50,10 +60,11 @@ (> arg 0))) ;; Auto-newline and hungry-delete -(defun c-toggle-auto-state (arg) +(defun c-toggle-auto-state (&optional arg) "Toggle auto-newline feature. -Optional numeric ARG, if supplied turns on auto-newline when positive, -turns it off when negative, and just toggles it when zero. +Optional numeric ARG, if supplied, turns on auto-newline when +positive, turns it off when negative, and just toggles it when zero or +left out. When the auto-newline feature is enabled (as evidenced by the `/a' or `/ah' on the modeline after the mode name) newlines are automatically @@ -64,10 +75,11 @@ and colon." (c-update-modeline) (c-keep-region-active)) -(defun c-toggle-hungry-state (arg) +(defun c-toggle-hungry-state (&optional arg) "Toggle hungry-delete-key feature. -Optional numeric ARG, if supplied turns on hungry-delete when positive, -turns it off when negative, and just toggles it when zero. +Optional numeric ARG, if supplied, turns on hungry-delete when +positive, turns it off when negative, and just toggles it when zero or +left out. When the hungry-delete-key feature is enabled (as evidenced by the `/h' or `/ah' on the modeline after the mode name) the delete key @@ -77,11 +89,11 @@ gobbles all preceding whitespace in one fell swoop." (c-update-modeline) (c-keep-region-active)) -(defun c-toggle-auto-hungry-state (arg) +(defun c-toggle-auto-hungry-state (&optional arg) "Toggle auto-newline and hungry-delete-key features. -Optional numeric ARG, if supplied turns on auto-newline and +Optional numeric ARG, if supplied, turns on auto-newline and hungry-delete when positive, turns them off when negative, and just -toggles them when zero. +toggles them when zero or left out. See `c-toggle-auto-state' and `c-toggle-hungry-state' for details." (interactive "P") @@ -258,9 +270,6 @@ This function does various newline cleanups based on the value of ;; Do not try to insert newlines around a special (Pike-style) ;; brace list. (if (and c-special-brace-lists - (c-intersect-lists '(brace-list-open brace-list-close - brace-list-intro brace-entry-open) - syntax) (save-excursion (c-safe (if (= (char-before) ?{) (forward-char -1) @@ -278,9 +287,12 @@ This function does various newline cleanups based on the value of (if (memq 'before newlines) ;; we leave the newline we've put in there before, ;; but we need to re-indent the line above - (let ((pos (- (point-max) (point))) + (let (old-ind + (old-point-max (point-max)) + (pos (- (point-max) (point))) (here (point))) (forward-line -1) + (setq old-ind (c-point 'boi)) (let ((c-state-cache (c-whack-state (point) c-state-cache))) ;; we may need to update the cache. this should ;; still be faster than recalculating the state @@ -296,9 +308,9 @@ This function does various newline cleanups based on the value of (setq c-state-cache (c-hack-state (point) 'open c-state-cache))))) (if c-syntactic-indentation - (c-indent-line))) - (setq c-state-cache (c-adjust-state (c-point 'bol) here - (- (point) (c-point 'bol)) + (indent-according-to-mode))) + (setq c-state-cache (c-adjust-state (c-point 'bol) old-point-max + (- (c-point 'boi) old-ind) c-state-cache)) (goto-char (- (point-max) pos)) ;; if the buffer has changed due to the indentation, we @@ -327,17 +339,19 @@ This function does various newline cleanups based on the value of (setq syntax (c-guess-basic-syntax)) ;; gotta punt. this requires some horrible kludgery (beginning-of-line) - (makunbound 'c-state-cache) - (setq c-state-cache (c-parse-state) + (setq c-state-cache nil + c-state-cache (c-parse-state) syntax nil)))) ) - ;; now adjust the line's indentation. don't update the state - ;; cache since c-guess-basic-syntax isn't called when the - ;; syntax is passed to c-indent-line - (let* ((here (point))) - (c-indent-line syntax) - (setq c-state-cache (c-adjust-state (c-point 'bol) here - (- (c-point 'boi) (c-point 'bol)) + ;; Now adjust the line's indentation. Don't update the state + ;; cache since c-guess-basic-syntax isn't called when + ;; c-syntactic-context is set. + (let* ((old-ind (c-point 'boi)) + (old-point-max (point-max)) + (c-syntactic-context syntax)) + (indent-according-to-mode) + (setq c-state-cache (c-adjust-state (c-point 'bol) old-point-max + (- (c-point 'boi) old-ind) c-state-cache))) ;; Do all appropriate clean ups (let ((here (point)) @@ -396,7 +410,7 @@ This function does various newline cleanups based on the value of (let* ((bufpos (- (point) 2)) (which (if (eq (char-after bufpos) ?{) 'open 'close)) (c-state-cache (c-hack-state bufpos which c-state-cache))) - (c-indent-line)))) + (indent-according-to-mode)))) ;; blink the paren (and (eq last-command-char ?\}) old-blink-paren @@ -432,7 +446,7 @@ If a numeric ARG is supplied, point is inside a literal, or (c-echo-syntactic-information-p nil)) (self-insert-command (prefix-numeric-value arg)) (if indentp - (c-indent-line)))) + (indent-according-to-mode)))) (defun c-electric-star (arg) "Insert a star character. @@ -455,9 +469,8 @@ If a numeric ARG is supplied, point is inside a literal, or (forward-char -1)) (skip-chars-backward " \t") (bolp))) - ;; shut this up - (let (c-echo-syntactic-information-p) - (c-indent-line)) + (let (c-echo-syntactic-information-p) ; shut this up + (indent-according-to-mode)) )) (defun c-electric-semi&comma (arg) @@ -490,7 +503,7 @@ following brace lists and semicolons following defuns." ;; turned on (if (not c-auto-newline) (if c-syntactic-indentation - (c-indent-line)) + (indent-according-to-mode)) ;; clean ups (let ((pos (- (point-max) (point)))) (if (and (or (and @@ -509,7 +522,7 @@ following brace lists and semicolons following defuns." (goto-char (- (point-max) pos))) ;; re-indent line (if c-syntactic-indentation - (c-indent-line)) + (indent-according-to-mode)) ;; check to see if a newline should be added (let ((criteria c-hanging-semi&comma-criteria) answer add-newline-p) @@ -524,7 +537,7 @@ following brace lists and semicolons following defuns." )) (if add-newline-p (progn (newline) - (c-indent-line))) + (indent-according-to-mode))) ))))) (defun c-electric-colon (arg) @@ -587,7 +600,8 @@ value of `c-cleanup-list'." c-hanging-colons-alist)))) ;; indent the current line if it's done syntactically. (if c-syntactic-indentation - (c-indent-line syntax)) + (let ((c-syntactic-context syntax)) + (indent-according-to-mode))) ;; does a newline go before the colon? Watch out for already ;; non-hung colons. However, we don't unhang them because that ;; would be a cleanup (and anti-social). @@ -599,14 +613,14 @@ value of `c-cleanup-list'." (let ((pos (- (point-max) (point)))) (forward-char -1) (newline) - (c-indent-line) + (indent-according-to-mode) (goto-char (- (point-max) pos)))) ;; does a newline go after the colon? (if (and (memq 'after (cdr-safe newlines)) (not is-scope-op)) (progn (newline) - (c-indent-line))) + (indent-according-to-mode))) ))) (defun c-electric-lt-gt (arg) @@ -625,14 +639,13 @@ will not be re-indented." (c-echo-syntactic-information-p nil)) (self-insert-command (prefix-numeric-value arg)) (if indentp - (c-indent-line)))) + (indent-according-to-mode)))) (defun c-electric-paren (arg) "Insert a parenthesis. -If the auto-newline feature is turned on, as evidenced by the \"/a\" -or \"/ah\" string on the mode line, some newline cleanups are done if -appropriate; see the variable `c-cleanup-list'. +Some newline cleanups are done if appropriate; see the variable +`c-cleanup-list'. Also, the line is re-indented unless a numeric ARG is supplied, there are non-whitespace characters present on the line after the @@ -642,7 +655,6 @@ parenthesis, the parenthesis is inserted inside a literal, or (let (;; shut this up (c-echo-syntactic-information-p nil)) (if (or arg - (not (looking-at "[ \t]*$")) (c-in-literal (c-point 'bod))) (self-insert-command (prefix-numeric-value arg)) ;; do some special stuff with the character @@ -652,43 +664,86 @@ parenthesis, the parenthesis is inserted inside a literal, or (old-blink-paren blink-paren-function) blink-paren-function) (self-insert-command (prefix-numeric-value arg)) - (if c-syntactic-indentation - (c-indent-line)) - (when c-auto-newline - ;; Do all appropriate clean ups - (let ((here (point)) - (pos (- (point-max) (point))) - mbeg mend) - ;; clean up brace-elseif-brace - (if (and (memq 'brace-elseif-brace c-cleanup-list) - (eq last-command-char ?\() - (re-search-backward "}[ \t\n]*else[ \t\n]+if[ \t\n]*(" - nil t) - (save-excursion - (setq mbeg (match-beginning 0) - mend (match-end 0)) - (= mend here)) - (not (c-in-literal))) - (progn - (delete-region mbeg mend) - (insert "} else if ("))) - ;; clean up brace-catch-brace - (if (and (memq 'brace-catch-brace c-cleanup-list) - (eq last-command-char ?\() - (re-search-backward "}[ \t\n]*catch[ \t\n]*(" nil t) - (save-excursion - (setq mbeg (match-beginning 0) - mend (match-end 0)) - (= mend here)) - (not (c-in-literal))) - (progn - (delete-region mbeg mend) - (insert "} catch ("))) - (goto-char (- (point-max) pos)) - )) + (when (looking-at "[ \t]*$") + (if c-syntactic-indentation + (indent-according-to-mode)) + (when c-auto-newline + ;; Do all appropriate clean ups + (let ((here (point)) + (pos (- (point-max) (point))) + mbeg mend) + ;; clean up brace-elseif-brace + (if (and (memq 'brace-elseif-brace c-cleanup-list) + (eq last-command-char ?\() + (re-search-backward "}[ \t\n]*else[ \t\n]+if[ \t\n]*(" + nil t) + (save-excursion + (setq mbeg (match-beginning 0) + mend (match-end 0)) + (= mend here)) + (not (c-in-literal))) + (progn + (delete-region mbeg mend) + (insert "} else if ("))) + ;; clean up brace-catch-brace + (if (and (memq 'brace-catch-brace c-cleanup-list) + (eq last-command-char ?\() + (re-search-backward "}[ \t\n]*catch[ \t\n]*(" nil t) + (save-excursion + (setq mbeg (match-beginning 0) + mend (match-end 0)) + (= mend here)) + (not (c-in-literal))) + (progn + (delete-region mbeg mend) + (insert "} catch ("))) + (goto-char (- (point-max) pos)) + ))) + (let (beg (end (1- (point)))) + (cond ((and (memq 'space-before-funcall c-cleanup-list) + (eq last-command-char ?\() + (save-excursion + (backward-char) + (skip-chars-backward " \t") + (setq beg (point)) + (c-on-identifier))) + (save-excursion + (delete-region beg end) + (goto-char beg) + (insert " "))) + ((and (memq 'compact-empty-funcall c-cleanup-list) + (eq last-command-char ?\)) + (save-excursion + (c-safe (backward-char 2)) + (when (looking-at "()") + (setq end (point)) + (skip-chars-backward " \t") + (setq beg (point)) + (c-on-identifier)))) + (delete-region beg end)))) (if old-blink-paren (funcall old-blink-paren)))))) +(defun c-electric-continued-statement () + "Reindent the current line if appropriate. + +This function is used to reindent the line after a keyword which +continues an earlier statement is typed, e.g. an \"else\" or the +\"while\" in a do-while block. + +The line is reindented if there is nothing but whitespace before the +keyword on the line, the keyword is not inserted inside a literal, and +`c-syntactic-indentation' is non-nil." + (let (;; shut this up + (c-echo-syntactic-information-p nil)) + (when (and c-syntactic-indentation + (not (eq last-command-char ?_)) + (= (save-excursion + (skip-syntax-backward "w") + (point)) + (c-point 'boi)) + (not (c-in-literal (c-point 'bod)))) + (indent-according-to-mode)))) ;; better movement routines for ThisStyleOfVariablesCommonInCPlusPlus @@ -792,14 +847,13 @@ the open-parenthesis that starts a defun; see `beginning-of-defun'." With prefix arg, go back N - 1 statements. If already at the beginning of a statement then go to the beginning of the closest preceding one, moving into nested blocks if necessary (use -\\[backward-sexp] to skip over a block). If within a comment, or next -to a comment (only whitespace between), move by sentences instead of -statements. +\\[backward-sexp] to skip over a block). If within or next to a +comment or multiline string, move by sentences instead of statements. When called from a program, this function takes 3 optional args: the repetition count, a buffer position limit which is the farthest back -to search, and a flag saying whether to do sentence motion when in a -comment." +to search for the syntactic context, and a flag saying whether to do +sentence motion in or near comments and multiline strings." (interactive (list (prefix-numeric-value current-prefix-arg) nil t)) (let* ((count (or count 1)) @@ -812,48 +866,85 @@ comment." (save-excursion ;; Find the comment next to point if we're not in one. (if (> count 0) - (setq range (if (c-forward-comment -1) - (cons (point) - (progn (c-forward-comment 1) (point))))) - (skip-chars-forward " \t\n") - (setq range (point)) - (setq range (if (c-forward-comment 1) - (cons range (point)) - nil))) + (if (c-forward-comment -1) + (setq range (cons (point) + (progn (c-forward-comment 1) (point)))) + (skip-chars-backward " \t\n\r\f") + (setq range (point)) + (setq range + (if (eq (char-before) ?\") + (c-safe (c-backward-sexp 1) + (cons (point) range))))) + ;; skip-syntax-* doesn't count \n as whitespace.. + (skip-chars-forward " \t\n\r\f") + (if (eq (char-after) ?\") + (setq range (cons (point) + (progn + (c-forward-sexp 1) + (point)))) + (setq range (point)) + (setq range (if (c-forward-comment 1) + (cons range (point)) + nil)))) (setq range (c-collect-line-comments range)))) (if (and (< count 0) (= here (point-max))) ;; Special case because eob might be in a literal. (setq range nil)) (if range (if (and sentence-flag - (/= (char-syntax (char-after (car range))) ?\")) + (or (/= (char-syntax (char-after (car range))) ?\") + ;; Only visit a string if it spans more than one line. + (save-excursion + (goto-char (car range)) + (skip-chars-forward "^\n" (cdr range)) + (< (point) (cdr range))))) (let* ((lit-type (c-literal-type range)) - (beg (save-excursion - (goto-char (car range)) - (looking-at (if (eq lit-type 'c) - comment-start-skip - (concat "\\(" - c-comment-prefix-regexp - "\\)[ \t]*"))) - (goto-char (match-end 0)) - (point))) - (end (save-excursion - (goto-char (- (cdr range) - (if (eq lit-type 'c) 2 1))) - (point)))) - ;; move by sentence, but not past the limit of the literal + (line-prefix (concat "[ \t]*\\(" + c-current-comment-prefix + "\\)[ \t]*")) + (beg (if (eq lit-type 'string) + (1+ (car range)) + (save-excursion + (goto-char (car range)) + (max (progn + (looking-at comment-start-skip) + (match-end 0)) + (progn + (looking-at line-prefix) + (match-end 0)))))) + (end (- (cdr range) (if (eq lit-type 'c) 2 1))) + (beg-of-para (if (eq lit-type 'string) + (lambda ()) + (lambda () + (beginning-of-line) + (if (looking-at line-prefix) + (goto-char (match-end 0))))))) (save-restriction - (narrow-to-region beg end) + ;; Move by sentence, but not past the limit of the + ;; literal, narrowed to the appropriate + ;; paragraph(s). + (narrow-to-region (save-excursion + (let ((pos (min here end))) + (goto-char pos) + (forward-paragraph -1) + (if (looking-at paragraph-separate) + (forward-line)) + (when (> (point) beg) + (funcall beg-of-para) + (when (>= (point) pos) + (forward-paragraph -2) + (funcall beg-of-para))) + (max (point) beg))) + end) (c-safe (forward-sentence (if (< count 0) 1 -1))) (if (and (memq lit-type '(c c++)) ;; Check if we stopped due to a comment ;; prefix and not a sentence end. - (/= (point) beg) + (/= (point) (point-min)) + (/= (point) (point-max)) (save-excursion (beginning-of-line) - (looking-at (concat "[ \t]*\\(" - c-comment-prefix-regexp - "\\)[ \t]*"))) + (looking-at line-prefix)) (>= (point) (match-beginning 0)) (/= (match-beginning 1) (match-end 1)) (or (< (point) (match-end 0)) @@ -883,16 +974,22 @@ comment." ;; comment ender, stop before it. Stop after ;; the ender if there's either nothing or ;; newlines between. - (when (and (eq lit-type 'c) (eq (point) end)) + (when (and (eq lit-type 'c) + (eq (point) (point-max))) (widen) - (skip-chars-backward " \t") - (when (or (eq (point) end) (bolp)) + (when (or (= (skip-chars-backward " \t") 0) + (eq (point) (point-max)) + (bolp)) (goto-char (cdr range))))) - (when (and (eq (point) beg) (looking-at "[ \t]*$")) + (when (and (eq (point) (point-min)) + (looking-at "[ \t]*$")) ;; Stop before instead of after the comment ;; starter if nothing follows it. (widen) - (goto-char (car range)))))) + (goto-char (car range)) + (if (and (eq lit-type 'string) (/= (point) here)) + (setq count (1+ count) + range nil)))))) ;; See if we should escape the literal. (if (> count 0) (if (< (point) here) @@ -915,15 +1012,19 @@ comment." ;; Stop before `{' and after `;', `{', `}' and `};' ;; when not followed by `}' or `)', but on the other ;; side of the syntactic ws. Move by sexps and move - ;; into parens. Also stop before `#' when it's first + ;; into parens. Also stop before `#' when it's at boi ;; on a line. - (let ((comment-pos (not sentence-flag)) + (let ((literal-pos (not sentence-flag)) (large-enough (- (point-max))) last last-below-line) (catch 'done (while t (setq last (point)) - (when (and (looking-at "{\\|^#") (/= here last)) + (when (and (or (eq (char-after) ?\{) + (and (eq (char-after) ?#) + (eq (point) (c-point 'boi))) + ) + (/= here last)) (unless (and c-special-brace-lists (eq (char-after) ?{) (c-looking-at-special-brace-list)) @@ -932,13 +1033,13 @@ comment." (not (eq last-below-line here))) (goto-char last-below-line)) (throw 'done t))) - (if comment-pos + (if literal-pos (c-forward-comment large-enough) (when (c-forward-comment -1) ;; Record position of first comment. (save-excursion (c-forward-comment 1) - (setq comment-pos (point))) + (setq literal-pos (point))) (c-forward-comment large-enough))) (unless last-below-line (if (save-excursion @@ -963,40 +1064,48 @@ comment." (goto-char last) (throw 'done t)))) ((= (char-syntax (char-after)) ?\") - (forward-char) - (c-backward-sexp)) + (let ((end (point))) + (forward-char) + (c-backward-sexp) + (save-excursion + (skip-chars-forward "^\n" end) + (when (< (point) end) + ;; Break at multiline string. + (setq literal-pos (1+ end)) + (throw 'done t))))) (t (skip-syntax-backward "w_")) ; Speedup only. ))) - (if (and (numberp comment-pos) - (< (point) comment-pos)) - ;; We jumped over a comment that should be investigated. - (goto-char comment-pos) + (if (and (numberp literal-pos) + (< (point) literal-pos)) + ;; We jumped over a comment or string that + ;; should be investigated. + (goto-char literal-pos) (setq count (1- count)))) (error (goto-char (point-min)) (setq count 0))) (condition-case nil - ;; Stop before `{', `}', and `#' when it's first on a + ;; Stop before `{', `}', and `#' when it's at boi on a ;; line, but on the other side of the syntactic ws, and ;; after `;', `}' and `};'. Only stop before `{' if at ;; top level or inside braces, though. Move by sexps ;; and move into parens. Also stop at eol of lines - ;; starting with `#'. - (let ((comment-pos (not sentence-flag)) + ;; with `#' at the boi. + (let ((literal-pos (not sentence-flag)) (large-enough (point-max)) last) (catch 'done (while t (setq last (point)) - (if comment-pos + (if literal-pos (c-forward-comment large-enough) (if (progn (skip-chars-forward " \t\n\r\f") ;; Record position of first comment. - (setq comment-pos (point)) + (setq literal-pos (point)) (c-forward-comment 1)) (c-forward-comment large-enough) - (setq comment-pos nil))) + (setq literal-pos nil))) (cond ((and (eq (char-after) ?{) (not (and c-special-brace-lists (c-looking-at-special-brace-list))) @@ -1017,7 +1126,8 @@ comment." (/= here last)) (goto-char last) (throw 'done t)) - ((looking-at "^#") + ((and (eq (char-after) ?#) + (= (point) (c-point 'boi))) (if (= here last) (or (re-search-forward "\\(^\\|[^\\]\\)$" nil t) (goto-char (point-max))) @@ -1027,15 +1137,22 @@ comment." (goto-char (match-end 0)) (throw 'done t)) ((= (char-syntax (char-after)) ?\") - (c-forward-sexp)) + (let ((beg (point))) + (c-forward-sexp) + (save-excursion + (skip-chars-backward "^\n" beg) + (when (> (point) beg) + ;; Break at multiline string. + (setq literal-pos beg) + (throw 'done t))))) (t (forward-char 1) (skip-syntax-forward "w_")) ; Speedup only. ))) - (if (and (numberp comment-pos) - (> (point) comment-pos)) + (if (and (numberp literal-pos) + (> (point) literal-pos)) ;; We jumped over a comment that should be investigated. - (goto-char comment-pos) + (goto-char literal-pos) (setq count (1+ count)))) (error (goto-char (point-max)) @@ -1044,23 +1161,20 @@ comment." ;; If we haven't moved we're near a buffer limit. (when (and (not (zerop count)) (= (point) here)) (goto-char (if (> count 0) (point-min) (point-max))) - (setq count 0))) - ;; its possible we've been left up-buf of lim - (if lim (goto-char (max (point) lim)))) + (setq count 0)))) (c-keep-region-active)) (defun c-end-of-statement (&optional count lim sentence-flag) "Go to the end of the innermost C statement. With prefix arg, go forward N - 1 statements. Move forward to the end of the next statement if already at end, and move into nested blocks -\(use \\[forward-sexp] to skip over a block). If within a comment, or -next to a comment (only whitespace between), move by sentences instead -of statements. +\(use \\[forward-sexp] to skip over a block). If within or next to a +comment or multiline string, move by sentences instead of statements. When called from a program, this function takes 3 optional args: the repetition count, a buffer position limit which is the farthest back -to search, and a flag saying whether to do sentence motion when in a -comment." +to search for the syntactic context, and a flag saying whether to do +sentence motion in or near comments and multiline strings." (interactive (list (prefix-numeric-value current-prefix-arg) nil t)) (c-beginning-of-statement (- (or count 1)) lim sentence-flag) @@ -1107,8 +1221,8 @@ comment." (search-forward "}") (1+ (current-column))) ;; CASE 2: 2 spaces after #endif - ((or (looking-at "^#[ \t]*endif[ \t]*") - (looking-at "^#[ \t]*else[ \t]*")) + ((or (looking-at "[ \t]*#[ \t]*endif[ \t]*") + (looking-at "[ \t]*#[ \t]*else[ \t]*")) 7) ;; CASE 3: when c-indent-comments-syntactically-p is t, ;; calculate the offset according to c-offsets-alist. @@ -1127,8 +1241,7 @@ comment." ;; to ignore any anchoring as specified by ;; c-comment-only-line-offset since it doesn't apply here. (if (save-excursion - (beginning-of-line) - (skip-chars-forward " \t") + (back-to-indentation) (eolp)) (c-add-syntax 'comment-intro)) (let ((c-comment-only-line-offset @@ -1136,7 +1249,7 @@ comment." c-comment-only-line-offset (cons c-comment-only-line-offset c-comment-only-line-offset)))) - (apply '+ (mapcar 'c-get-offset syntax))))) + (c-get-syntactic-indentation syntax)))) ;; CASE 4: If previous line is a comment-only line, use its ;; indentation if it's greater than comment-column. Leave at ;; least one space between the comment and the last nonblank @@ -1346,7 +1459,7 @@ relative indentation among the lines of the expression is preserved. (let ((bod (c-point 'bod)) (indent-function (if c-syntactic-indentation - (symbol-function 'c-indent-line) + (symbol-function 'indent-according-to-mode) (lambda () (let ((steps (cond ((not current-prefix-arg) 1) ((equal current-prefix-arg '(4)) -1) @@ -1357,8 +1470,15 @@ relative indentation among the lines of the expression is preserved. ;; If c-syntactic-indentation and got arg, always indent this ;; line as C and shift remaining lines of expression the same ;; amount. - (let ((shift-amt (c-indent-line)) + (let ((shift-amt (save-excursion + (back-to-indentation) + (current-column))) beg end) + (c-indent-line) + (setq shift-amt (- (save-excursion + (back-to-indentation) + (current-column)) + shift-amt)) (save-excursion (if (eq c-tab-always-indent t) (beginning-of-line)) @@ -1369,7 +1489,7 @@ relative indentation among the lines of the expression is preserved. (forward-line 1) (setq beg (point))) (if (> end beg) - (indent-code-rigidly beg end (- shift-amt) "#"))) + (indent-code-rigidly beg end shift-amt "#"))) ;; Else use c-tab-always-indent to determine behavior. (cond ;; CASE 1: indent when at column zero or in lines indentation, @@ -1392,57 +1512,39 @@ relative indentation among the lines of the expression is preserved. ))))) (defun c-indent-exp (&optional shutup-p) - "Indent each line in balanced expression following point syntactically. -Optional SHUTUP-P if non-nil, inhibits message printing and error checking." + "Indent each line in the balanced expression following point syntactically. +If optional SHUTUP-P is non-nil, no errors are signalled if no +balanced expression is found." (interactive "*P") (let ((here (point-marker)) - end progress-p) + end) (set-marker-insertion-type here t) (unwind-protect - (let ((c-echo-syntactic-information-p nil) ;keep quiet for speed - (start (progn + (let ((start (progn ;; try to be smarter about finding the range of ;; lines to indent. skip all following - ;; whitespace. failing that, try to find any - ;; opening brace on the current line + ;; whitespace, then try to find any + ;; opening paren on the current line (skip-chars-forward " \t\n") - (if (memq (char-after) '(?\( ?\[ ?\{)) - (point) - (let ((state (parse-partial-sexp (point) - (c-point 'eol)))) - (and (nth 1 state) - (goto-char (nth 1 state)) - (memq (char-after) '(?\( ?\[ ?\{)) - (point))))))) + (save-restriction + (narrow-to-region (point-min) (c-point 'eol)) + (c-safe (1- (scan-lists (point) 1 -1))))))) ;; find balanced expression end (setq end (and (c-safe (progn (c-forward-sexp 1) t)) - (point-marker))) + (point))) ;; sanity check - (and (not start) - (not shutup-p) - (error "Cannot find start of balanced expression to indent.")) - (and (not end) - (not shutup-p) - (error "Cannot find end of balanced expression to indent.")) - (c-progress-init start end 'c-indent-exp) - (setq progress-p t) - (goto-char start) - (beginning-of-line) - (while (< (point) end) - (if (not (looking-at "[ \t]*$")) - (c-indent-line)) - (c-progress-update) - (forward-line 1))) - ;; make sure marker is deleted - (and end - (set-marker end nil)) - (and progress-p - (c-progress-fini 'c-indent-exp)) + (if (not start) + (unless shutup-p + (error "Cannot find start of balanced expression to indent")) + (if (not end) + (unless shutup-p + (error "Cannot find end of balanced expression to indent")) + (c-indent-region start end)))) (goto-char here) (set-marker here nil)))) (defun c-indent-defun () - "Re-indents the current top-level function def, struct or class declaration + "Indent the current top-level function def, struct or class declaration syntactically." (interactive "*") (let ((here (point-marker)) @@ -1467,96 +1569,37 @@ syntactically." (goto-char here) (set-marker here nil)))) -(defun c-indent-region (start end) - ;; Indent every line whose first char is between START and END inclusive. +(defun c-indent-region (start end &optional quiet) + "Indent every line whose first char is between START and END inclusive. +Be silent about syntactic errors if the optional argument QUIET is non-nil." (save-excursion (goto-char start) ;; Advance to first nonblank line. (skip-chars-forward " \t\n") (beginning-of-line) - (let (endmark) - (unwind-protect - (let ((c-tab-always-indent t) - ;; shut up any echo msgs on indiv lines - (c-echo-syntactic-information-p nil) - fence) - (c-progress-init start end 'c-indent-region) - (setq endmark (copy-marker end)) - (while (and (bolp) - (not (eobp)) - (< (point) endmark)) - ;; update progress - (c-progress-update) - ;; Indent one line as with TAB. - (let (nextline sexpend sexpbeg) - ;; skip blank lines - (skip-chars-forward " \t\n") - (beginning-of-line) - ;; indent the current line - (c-indent-line) - (setq fence (point)) - (if (save-excursion - (beginning-of-line) - (looking-at "[ \t]*#")) - (forward-line 1) - (save-excursion - ;; Find beginning of following line. - (setq nextline (c-point 'bonl)) - ;; Find first beginning-of-sexp for sexp extending past - ;; this line. - (beginning-of-line) - (while (< (point) nextline) - (condition-case nil - (progn - (c-forward-sexp 1) - (setq sexpend (point))) - (error (setq sexpend nil) - (goto-char nextline))) - (c-forward-syntactic-ws)) - (if sexpend - (progn - ;; make sure the sexp we found really starts on the - ;; current line and extends past it - (goto-char sexpend) - (setq sexpend (point-marker)) - (c-safe (c-backward-sexp 1)) - (setq sexpbeg (point)))) - (if (and sexpbeg (< sexpbeg fence)) - (setq sexpbeg fence))) - ;; Since we move by sexps we might have missed - ;; comment-only lines. - (if sexpbeg - (save-excursion - (while (progn - (forward-line 1) - (skip-chars-forward " \t") - (< (point) sexpbeg)) - (if (looking-at c-comment-start-regexp) - (setq sexpbeg (c-point 'bol)))))) - ;; If that sexp ends within the region, indent it all at - ;; once, fast. - (condition-case nil - (if (and sexpend - (> sexpend nextline) - (<= sexpend endmark)) - (progn - (goto-char sexpbeg) - (c-indent-exp 'shutup) - (c-progress-update) - (goto-char sexpend))) - (error - (goto-char sexpbeg) - (c-indent-line))) - ;; Move to following line and try again. - (and sexpend - (markerp sexpend) - (set-marker sexpend nil)) - (forward-line 1) - (setq fence (point)))))) - (set-marker endmark nil) - (c-progress-fini 'c-indent-region) - (c-echo-parsing-error) - )))) + (setq c-parsing-error + (or (let ((endmark (copy-marker end)) + (c-parsing-error nil) + ;; shut up any echo msgs on indiv lines + (c-echo-syntactic-information-p nil)) + (unwind-protect + (progn + (c-progress-init start end 'c-indent-region) + (while (and (bolp) + (not (eobp)) + (< (point) endmark)) + ;; update progress + (c-progress-update) + ;; skip blank lines + (skip-chars-forward " \t\n") + (beginning-of-line) + ;; indent the current line + (c-indent-line nil t) + (forward-line))) + (set-marker endmark nil) + (c-progress-fini 'c-indent-region)) + (c-echo-parsing-error quiet)) + c-parsing-error)))) (defun c-mark-function () "Put mark at end of current top-level defun, point at beginning." @@ -1582,10 +1625,10 @@ syntactically." (c-backward-syntactic-ws) (skip-chars-backward ";") (point)) - (cdar state))) + (cdr (car state)))) (progn (setq eod (point)) - (goto-char (caar state)) + (goto-char (car (car state))) (c-beginning-of-statement-1)) (if (= ?{ (save-excursion (c-end-of-statement-1) @@ -1613,13 +1656,18 @@ syntactically." (push-mark here) (push-mark eod nil t))) +(defun c-fn-region-is-active-p () + ;; Function version of the macro for use in places that aren't + ;; compiled, e.g. in the menus. + (c-region-is-active-p)) + (defun c-indent-line-or-region () "When the region is active, indent it. Otherwise indent the current line." ;; Emacs has a variable called mark-active, XEmacs uses region-active-p (interactive) (if (c-region-is-active-p) (c-indent-region (region-beginning) (region-end)) - (c-indent-command))) + (indent-according-to-mode))) ;; for progress reporting @@ -1632,7 +1680,7 @@ syntactically." ;; Start the progress update messages. If this Emacs doesn't have ;; a built-in timer, just be dumb about it. ((not (fboundp 'current-time)) - (message "indenting region... (this may take a while)")) + (message "Indenting region... (this may take a while)")) ;; If progress has already been initialized, do nothing. otherwise ;; initialize the counter with a vector of: ;; [start end lastsec context] @@ -1643,7 +1691,7 @@ syntactically." (point-marker)) (nth 1 (current-time)) context)) - (message "indenting region...")) + (message "Indenting region...")) )) (defun c-progress-update () @@ -1658,7 +1706,7 @@ syntactically." ;; what's the right value? (if (< c-progress-interval (- now lastsecs)) (progn - (message "indenting region... (%d%% complete)" + (message "Indenting region... (%d%% complete)" (/ (* 100 (- (point) start)) (- end start))) (aset c-progress-info 2 now))) ))) @@ -1672,7 +1720,7 @@ syntactically." (progn (set-marker (aref c-progress-info 1) nil) (setq c-progress-info nil) - (message "indenting region...done"))))) + (message "Indenting region... done"))))) @@ -1748,6 +1796,10 @@ command to conveniently insert and align the necessary backslashes." ;;; Line breaking and paragraph filling. +(defvar c-auto-fill-prefix t) +(defvar c-lit-limits nil) +(defvar c-lit-type nil) + ;; The filling code is based on a simple theory; leave the intricacies ;; of the text handling to the currently active mode for that ;; (e.g. adaptive-fill-mode or filladapt-mode) and do as little as @@ -1772,12 +1824,12 @@ command to conveniently insert and align the necessary backslashes." ;; function also uses the value of point in some heuristics. (let* ((here (point)) (prefix-regexp (concat "[ \t]*\\(" - c-comment-prefix-regexp + c-current-comment-prefix "\\)[ \t]*")) (comment-start-regexp (if (eq lit-type 'c++) prefix-regexp comment-start-skip)) - prefix-line comment-prefix res) + prefix-line comment-prefix res comment-text-end) (cond (fill-prefix (setq res (cons fill-prefix @@ -1796,7 +1848,8 @@ command to conveniently insert and align the necessary backslashes." ((eq lit-type 'c++) (save-excursion ;; Set fallback for comment-prefix if none is found. - (setq comment-prefix "// ") + (setq comment-prefix "// " + comment-text-end (cdr lit-limits)) (beginning-of-line) (if (> (point) (car lit-limits)) ;; The current line is not the comment starter, so the @@ -1847,6 +1900,7 @@ command to conveniently insert and align the necessary backslashes." ))))) (t (save-excursion + (setq comment-text-end (- (cdr lit-limits) 2)) (beginning-of-line) (if (and (> (point) (car lit-limits)) (not (and (looking-at "[ \t]*\\*/") @@ -1868,7 +1922,7 @@ command to conveniently insert and align the necessary backslashes." ;; The comment is either one line or the next line ;; contains just the comment ender. Also, if point is ;; on the comment opener line and the following line is - ;; empty or doesn't match c-comment-prefix-regexp we + ;; empty or doesn't match c-current-comment-prefix we ;; assume that this is in fact a not yet closed one line ;; comment, so we shouldn't look for the comment prefix ;; on the next line. In these cases we have no @@ -1910,7 +1964,7 @@ command to conveniently insert and align the necessary backslashes." ;; "" or ends with whitespace. (insert "x\n" comment-prefix ?x) (setq tmp-post (point-marker)) - (c-indent-line) + (indent-according-to-mode) (goto-char (1- tmp-post)) (cons (buffer-substring-no-properties (c-point 'bol) (point)) @@ -1931,37 +1985,56 @@ command to conveniently insert and align the necessary backslashes." (test-line (lambda () (when (and (looking-at prefix-regexp) - (< (match-end 0) (1- (cdr lit-limits)))) + (<= (match-end 0) comment-text-end)) + (unless (eq (match-end 0) (c-point 'eol)) + ;; The match is fine if there's text after it. + (throw 'found (cons (buffer-substring-no-properties + (match-beginning 0) (match-end 0)) + (progn (goto-char (match-end 0)) + (current-column))))) (unless fb-string + ;; This match is better than nothing, so let's + ;; remember it in case nothing better is found + ;; on another line. (setq fb-string (buffer-substring-no-properties (match-beginning 0) (match-end 0)) fb-endpos (match-end 0))) - (unless (eq (match-end 0) (c-point 'eol)) - (throw 'found t)) t)))) - (if (catch 'found + (or (catch 'found ;; Search for a line which has text after the prefix ;; so that we get the proper amount of whitespace ;; after it. We start with the current line, then ;; search backwards, then forwards. (goto-char prefix-line) (when (and (funcall test-line) - (/= (match-end 1) (match-end 0))) + (or (/= (match-end 1) (match-end 0)) + ;; The whitespace is sucked up by the + ;; first [ \t]* glob if the prefix is empty. + (and (= (match-beginning 1) (match-end 1)) + (/= (match-beginning 0) (match-end 0))))) ;; If the current line doesn't have text but do ;; have whitespace after the prefix, we'll use it. - (throw 'found t)) - (while (and (zerop (forward-line -1)) - (> (point) (car lit-limits))) - (funcall test-line)) + (throw 'found (cons fb-string + (progn (goto-char fb-endpos) + (current-column))))) + (if (eq lit-type 'c++) + ;; For line comments we can search up to and + ;; including the first line. + (while (and (zerop (forward-line -1)) + (>= (point) (car lit-limits))) + (funcall test-line)) + ;; For block comments we must stop before the + ;; block starter. + (while (and (zerop (forward-line -1)) + (> (point) (car lit-limits))) + (funcall test-line))) (goto-char prefix-line) (while (and (zerop (forward-line 1)) (< (point) (cdr lit-limits))) (funcall test-line)) + (goto-char prefix-line) nil) - ;; A good line with text after the prefix was found. - (cons (buffer-substring-no-properties (point) (match-end 0)) - (progn (goto-char (match-end 0)) (current-column))) - (if fb-string + (when fb-string ;; A good line wasn't found, but at least we have a ;; fallback that matches the comment prefix regexp. (cond ((string-match "\\s \\'" fb-string) @@ -1997,13 +2070,14 @@ command to conveniently insert and align the necessary backslashes." (c-point 'bol) (point)) (current-column))) - (delete-region tmp (point))))) + (delete-region tmp (point)) + (set-buffer-modified-p buffer-modified)))) (t ;; Last resort: Just add a single space after ;; the prefix. (cons (concat fb-string " ") (progn (goto-char fb-endpos) - (1+ (current-column)))))) + (1+ (current-column))))))) ;; The line doesn't match the comment prefix regexp. (if comment-prefix ;; We have a fallback for line comments that we must use. @@ -2016,7 +2090,7 @@ command to conveniently insert and align the necessary backslashes." ;; comment where the lines doesn't have any comment ;; prefix at all and we should just fill it as ;; normal text. - '("" . 0))))))) + '("" . 0)))))) )) (defun c-fill-paragraph (&optional arg) @@ -2043,193 +2117,240 @@ Optional prefix ARG means justify paragraph as well." (let (lit-limits lit-type fill ;; beg and end limits the region to be filled. end is a marker. beg end - ;; tmp-pre and tmp-post marks strings that are temporarily + ;; tmp-pre and tmp-post mark strings that are temporarily ;; inserted at the start and end of the region. tmp-pre is a ;; cons of the positions of the prepended string. tmp-post is ;; a marker pointing to the single character of the appended ;; string. tmp-pre tmp-post - hang-ender-stuck) + ;; If hang-ender-stuck isn't nil, the comment ender is + ;; hanging. In that case it's set to the number of spaces + ;; that should be between the text and the ender. + hang-ender-stuck + (here (point))) ;; Restore point on undo. It's necessary since we do a lot of ;; hidden inserts and deletes below that should be as transparent ;; as possible. (if (and buffer-undo-list (not (eq buffer-undo-list t))) (setq buffer-undo-list (cons (point) buffer-undo-list))) + (save-restriction + ;; Widen to catch comment limits correctly. + (widen) + (setq lit-limits (c-collect-line-comments (c-literal-limits nil t)) + lit-type (c-literal-type lit-limits))) (save-excursion - (save-restriction - ;; Widen to catch comment limits correctly. - (widen) - (setq lit-limits (c-collect-line-comments (c-literal-limits nil t)) - lit-type (c-literal-type lit-limits))) - (forward-paragraph) - (setq end (point-marker)) - (backward-paragraph) + (unless (c-safe (backward-char) + (forward-paragraph) + (>= (point) here)) + (goto-char here) + (forward-paragraph)) + (setq end (point-marker))) + (save-excursion + (unless (c-safe (forward-char) + (backward-paragraph) + (<= (point) here)) + (goto-char here) + (backward-paragraph)) (setq beg (point))) - (when (and (>= (point) beg) (<= (point) end)) - (unwind-protect - (progn - (cond - ((eq lit-type 'c++) ; Line comment. - (save-excursion - ;; Fill to the comment or paragraph end, whichever - ;; comes first. - (set-marker end (min end (cdr lit-limits))) - (when (<= beg (car lit-limits)) - ;; The region to be filled includes the comment - ;; starter, so we must check it. - (goto-char (car lit-limits)) - (back-to-indentation) - (if (eq (point) (car lit-limits)) - ;; Include the first line in the fill. - (setq beg (c-point 'bol)) - ;; The first line contains code before the - ;; comment. We must fake a line that doesn't. - (setq tmp-pre t))) - )) - ((eq lit-type 'c) ; Block comment. - (save-excursion - (when (>= end (cdr lit-limits)) - ;; The region to be filled includes the comment ender. - (goto-char (cdr lit-limits)) - (beginning-of-line) - (if (and (looking-at (concat "[ \t]*\\(" - c-comment-prefix-regexp - "\\)\\*/")) - (eq (cdr lit-limits) (match-end 0))) - ;; Leave the comment ender on its own line. - (set-marker end (point)) - ;; The comment ender should hang. Replace all - ;; cruft between it and the last word with a 'x' - ;; and include it in the fill. We'll change it - ;; back to a space afterwards. - (let ((ender-start (progn - (goto-char (cdr lit-limits)) - (skip-syntax-backward "^w ") - (point))) - spaces) - (goto-char (cdr lit-limits)) - (setq tmp-post (point-marker)) - (insert ?\n) - (set-marker end (point)) - (forward-line -1) - (if (and (looking-at (concat "[ \t]*\\(\\(" - c-comment-prefix-regexp - "\\)[ \t]*\\)")) - (eq ender-start (match-end 0))) - ;; The comment ender is prefixed by nothing - ;; but a comment line prefix. Remove it - ;; along with surrounding ws. - (setq spaces (- (match-end 1) (match-end 2))) - (goto-char ender-start)) - (skip-chars-backward " \t\r\n") - (when (/= (point) ender-start) - ;; Keep one or two spaces between the text and - ;; the ender, depending on how many there are now. - (unless spaces (setq spaces (- ender-start (point)))) - (setq spaces (max (min spaces 2) 1)) - ; Insert the filler first to keep marks right. - (insert (make-string spaces ?x)) - (delete-region (point) (+ ender-start spaces)) - (setq hang-ender-stuck spaces))))) - (when (<= beg (car lit-limits)) - ;; The region to be filled includes the comment starter. - (goto-char (car lit-limits)) - (if (looking-at (concat "\\(" comment-start-skip "\\)$")) - ;; Begin filling with the next line. - (setq beg (c-point 'bonl)) - ;; Fake the fill prefix in the first line. - (setq tmp-pre t))) - )) - ((eq lit-type 'string) ; String. - (save-excursion - (when (>= end (cdr lit-limits)) - (goto-char (1- (cdr lit-limits))) - (setq tmp-post (point-marker)) - (insert ?\n) - (set-marker end (point))) - (when (<= beg (car lit-limits)) - (goto-char (1+ (car lit-limits))) - (setq beg (if (looking-at "\\\\$") - ;; Leave the start line if it's - ;; nothing but an escaped newline. - (1+ (match-end 0)) - (point)))))) - (t (setq beg nil))) - (when tmp-pre - ;; Temporarily insert the fill prefix after the comment - ;; starter so that the first line looks like any other - ;; comment line in the narrowed region. - (setq fill (c-guess-fill-prefix lit-limits lit-type)) - (unless (string-match (concat "\\`[ \t]*\\(" - c-comment-prefix-regexp - "\\)[ \t]*\\'") - (car fill)) - ;; Oops, the prefix doesn't match the comment prefix - ;; regexp. This could produce very confusing - ;; results with adaptive fill packages together with - ;; the insert prefix magic below, since the prefix - ;; often doesn't appear at all. So let's warn about - ;; it. - (message "\ -Warning: `c-comment-prefix-regexp' doesn't match the comment prefix %S" - (car fill))) - ;; Find the right spot on the line, break it, insert - ;; the fill prefix and make sure we're back in the - ;; same column by temporarily prefixing the first word - ;; with a number of 'x'. + (unwind-protect + (progn + (cond + ((eq lit-type 'c++) ; Line comment. + (save-excursion + ;; Fill to the comment or paragraph end, whichever + ;; comes first. + (set-marker end (min end (cdr lit-limits))) + (when (<= beg (car lit-limits)) + ;; The region to be filled includes the comment + ;; starter, so we must check it. + (goto-char (car lit-limits)) + (back-to-indentation) + (if (eq (point) (car lit-limits)) + ;; Include the first line in the fill. + (setq beg (c-point 'bol)) + ;; The first line contains code before the + ;; comment. We must fake a line that doesn't. + (setq tmp-pre t))) + )) + ((eq lit-type 'c) ; Block comment. + (when (>= end (cdr lit-limits)) + ;; The region to be filled includes the comment ender. + (unless (save-excursion + (goto-char (cdr lit-limits)) + (beginning-of-line) + (and (looking-at (concat "[ \t]*\\(" + c-current-comment-prefix + "\\)\\*/")) + (eq (cdr lit-limits) (match-end 0)) + ;; Leave the comment ender on its own line. + (set-marker end (point)))) + ;; The comment ender should hang. Replace all cruft + ;; between it and the last word with one or two 'x' + ;; and include it in the fill. We'll change them back + ;; spaces afterwards. + (let* ((ender-start (save-excursion + (goto-char (cdr lit-limits)) + (skip-syntax-backward "^w ") + (point))) + (point-rel (- ender-start here)) + spaces) + (save-excursion + (goto-char (cdr lit-limits)) + (setq tmp-post (point-marker)) + (insert ?\n) + (set-marker end (point)) + (forward-line -1) + (if (and (looking-at (concat "[ \t]*\\(\\(" + c-current-comment-prefix + "\\)[ \t]*\\)")) + (eq ender-start (match-end 0))) + ;; The comment ender is prefixed by nothing + ;; but a comment line prefix. Remove it + ;; along with surrounding ws. + (setq spaces (- (match-end 1) (match-end 2))) + (goto-char ender-start)) + (skip-chars-backward " \t\r\n") + (if (/= (point) ender-start) + (progn + (if (<= here (point)) + ;; Don't adjust point below if it's + ;; before the string we replace. + (setq point-rel -1)) + ;; Keep one or two spaces between the text and + ;; the ender, depending on how many there are now. + (unless spaces (setq spaces (- ender-start (point)))) + (setq spaces (max (min spaces 2) 1)) + ;; Insert the filler first to keep marks right. + (insert (make-string spaces ?x)) + (delete-region (point) (+ ender-start spaces)) + (setq hang-ender-stuck spaces) + (setq point-rel + (and (>= point-rel 0) + (- (point) (min point-rel spaces))))) + (setq point-rel nil))) + (if point-rel + ;; Point was in the middle of the string we + ;; replaced above, so put it back in the same + ;; relative position, counting from the end. + (goto-char point-rel)) + ))) + (when (<= beg (car lit-limits)) + ;; The region to be filled includes the comment starter. (save-excursion (goto-char (car lit-limits)) - (if (looking-at (if (eq lit-type 'c++) - c-comment-prefix-regexp - comment-start-skip)) - (goto-char (match-end 0)) - (forward-char 2) - (skip-chars-forward " \t")) - (while (< (current-column) (cdr fill)) (forward-char 1)) - (let ((col (current-column))) - (setq beg (1+ (point)) - tmp-pre (list (point))) - (unwind-protect - (progn - (insert ?\n (car fill)) - (insert (make-string (- col (current-column)) ?x))) - (setcdr tmp-pre (point)))))) - (when beg - (let ((fill-paragraph-function - ;; Avoid infinite recursion. - (if (not (eq fill-paragraph-function 'c-fill-paragraph)) - fill-paragraph-function)) - (fill-prefix - (or fill-prefix - (when (and (eq lit-type 'c++) - (not (string-match - "\\`[ \t]*//" - (or (fill-context-prefix beg end) - "")))) - ;; Kludge: If the function that adapts the - ;; fill prefix doesn't produce the required - ;; comment starter for line comments, then - ;; force it by setting fill-prefix. - (car (or fill (c-guess-fill-prefix - lit-limits lit-type))))))) - ;; Preparations finally done! Now we can call the - ;; real fill function. - (save-restriction - (narrow-to-region beg end) - (fill-paragraph arg))))) - (when (consp tmp-pre) - (delete-region (car tmp-pre) (cdr tmp-pre))) - (when tmp-post - (save-excursion - (goto-char tmp-post) - (delete-char 1) - (when hang-ender-stuck - (skip-syntax-backward "^w ") - (forward-char (- hang-ender-stuck)) - (insert (make-string hang-ender-stuck ?\ )) - (delete-char hang-ender-stuck)) - (set-marker tmp-post nil))))) - (set-marker end nil)) + (if (looking-at (concat "\\(" comment-start-skip "\\)$")) + ;; Begin filling with the next line. + (setq beg (c-point 'bonl)) + ;; Fake the fill prefix in the first line. + (setq tmp-pre t))))) + ((eq lit-type 'string) ; String. + (save-excursion + (when (>= end (cdr lit-limits)) + (goto-char (1- (cdr lit-limits))) + (setq tmp-post (point-marker)) + (insert ?\n) + (set-marker end (point))) + (when (<= beg (car lit-limits)) + (goto-char (1+ (car lit-limits))) + (setq beg (if (looking-at "\\\\$") + ;; Leave the start line if it's + ;; nothing but an escaped newline. + (1+ (match-end 0)) + (point)))))) + (t (setq beg nil))) + (when tmp-pre + ;; Temporarily insert the fill prefix after the comment + ;; starter so that the first line looks like any other + ;; comment line in the narrowed region. + (setq fill (c-guess-fill-prefix lit-limits lit-type)) + (unless (string-match (concat "\\`[ \t]*\\(" + c-current-comment-prefix + "\\)[ \t]*\\'") + (car fill)) + ;; Oops, the prefix doesn't match the comment prefix + ;; regexp. This could produce very confusing + ;; results with adaptive fill packages together with + ;; the insert prefix magic below, since the prefix + ;; often doesn't appear at all. So let's warn about + ;; it. + (message "\ +Warning: Regexp from `c-comment-prefix-regexp' doesn't match the comment prefix %S" + (car fill))) + ;; Find the right spot on the line, break it, insert + ;; the fill prefix and make sure we're back in the + ;; same column by temporarily prefixing the first word + ;; with a number of 'x'. + (save-excursion + (goto-char (car lit-limits)) + (if (looking-at (if (eq lit-type 'c++) + c-comment-prefix-regexp + comment-start-skip)) + (goto-char (match-end 0)) + (forward-char 2) + (skip-chars-forward " \t")) + (while (< (current-column) (cdr fill)) (forward-char 1)) + (let ((col (current-column))) + (setq beg (1+ (point)) + tmp-pre (list (point))) + (unwind-protect + (progn + (insert ?\n (car fill)) + (insert (make-string (- col (current-column)) ?x))) + (setcdr tmp-pre (point)))))) + (when beg + (let ((fill-paragraph-function + ;; Avoid infinite recursion. + (if (not (eq fill-paragraph-function 'c-fill-paragraph)) + fill-paragraph-function)) + (fill-prefix + (or fill-prefix + ;; Kludge: If the function that adapts the fill prefix + ;; doesn't produce the required comment starter for line + ;; comments, then force it by setting fill-prefix. + (when (and (eq lit-type 'c++) + ;; Kludge the kludge: filladapt-mode doesn't + ;; have this problem, but it doesn't override + ;; fill-context-prefix currently (version + ;; 2.12). + (not (and (boundp 'filladapt-mode) + filladapt-mode)) + (not (string-match + "\\`[ \t]*//" + (or (fill-context-prefix beg end) + "")))) + (car (or fill (c-guess-fill-prefix + lit-limits lit-type)))))) + (point-rel (cond ((< here beg) (- here beg)) + ((> here end) (- here end))))) + ;; Preparations finally done! Now we can call the + ;; real fill function. + (save-restriction + (narrow-to-region beg end) + (fill-paragraph arg)) + (if point-rel + ;; Restore point if it was outside the region. + (if (< point-rel 0) + (goto-char (+ beg point-rel)) + (goto-char (+ end point-rel)))) + ))) + (when (consp tmp-pre) + (delete-region (car tmp-pre) (cdr tmp-pre))) + (when tmp-post + (save-excursion + (goto-char tmp-post) + (delete-char 1)) + (when hang-ender-stuck + ;; Preserve point even if it's in the middle of the string + ;; we replace; save-excursion doesn't work in that case. + (setq here (point)) + (goto-char tmp-post) + (skip-syntax-backward "^w ") + (forward-char (- hang-ender-stuck)) + (insert (make-string hang-ender-stuck ?\ )) + (delete-char hang-ender-stuck) + (goto-char here)) + (set-marker tmp-post nil)) + (set-marker end nil))) ;; Always return t. This has the effect that if filling isn't done ;; above, it isn't done at all, and it's therefore effectively ;; disabled in normal code. @@ -2267,9 +2388,9 @@ If a fill prefix is specified, it overrides all the above." (if soft (insert-and-inherit ?\n) (newline 1)))) ;; Already know the literal type and limits when called from ;; c-context-line-break. - (c-lit-limits (if (boundp 'c-lit-limits) c-lit-limits)) - (c-lit-type (if (boundp 'c-lit-type) c-lit-type))) - (when (boundp 'c-auto-fill-prefix) + (c-lit-limits c-lit-limits) + (c-lit-type c-lit-type)) + (when (not (eq c-auto-fill-prefix t)) ;; Called from do-auto-fill. (unless c-lit-limits (setq c-lit-limits (c-literal-limits nil nil t))) @@ -2325,7 +2446,7 @@ If a fill prefix is specified, it overrides all the above." (if (save-excursion (back-to-indentation) (> (point) (car c-lit-limits)) - (looking-at c-comment-prefix-regexp)) + (looking-at c-current-comment-prefix)) (progn ;; Skip forward past the fill prefix in case ;; we're standing in it. @@ -2390,13 +2511,14 @@ If a fill prefix is specified, it overrides all the above." ;; advice for indent-new-comment-line for older Emacsen (unless (boundp 'comment-line-break-function) + (defvar c-inside-line-break-advice nil) (defadvice indent-new-comment-line (around c-line-break-advice activate preactivate) "Call `c-indent-new-comment-line' if in CC Mode." - (if (or (boundp 'c-inside-line-break-advice) + (if (or c-inside-line-break-advice (not c-buffer-is-cc-mode)) ad-do-it - (let (c-inside-line-break-advice) + (let ((c-inside-line-break-advice t)) (c-indent-new-comment-line (ad-get-arg 0)))))) (defun c-context-line-break () @@ -2431,8 +2553,8 @@ C++-style line comment doesn't count as inside the comment, though." (= (forward-line -1) 0)))) (current-column)))) (indent-to col)) - (c-indent-line)))) + (indent-according-to-mode)))) -(provide 'cc-cmds) +(cc-provide 'cc-cmds) ;;; cc-cmds.el ends here diff --git a/lisp/progmodes/cc-compat.el b/lisp/progmodes/cc-compat.el index 98ba4bea3f6..887cf4bfc11 100644 --- a/lisp/progmodes/cc-compat.el +++ b/lisp/progmodes/cc-compat.el @@ -1,6 +1,6 @@ ;;; cc-compat.el --- cc-mode compatibility with c-mode.el confusion -;; Copyright (C) 1985,87,92,93,94,95,96,97,98,99,2000 Free Software Foundation, Inc. +;; Copyright (C) 1985,1987,1992-2001 Free Software Foundation, Inc. ;; Authors: 2000- Martin Stjernholm ;; 1998-1999 Barry A. Warsaw and Martin Stjernholm @@ -23,8 +23,8 @@ ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs; see the file COPYING. If not, write to the -;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; along with this program; see the file COPYING. If not, write to +;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, ;; Boston, MA 02111-1307, USA. ;;; Commentary: @@ -38,19 +38,25 @@ ;; ;; (require 'cc-compat) ;; (c-set-style "BOCM") +;; +;; This file is completely unsupported! Although it has been patched +;; superficially to keep pace with the rest of CC Mode, it hasn't been +;; tested for a long time. ;;; Code: (eval-when-compile (let ((load-path - (if (and (boundp 'byte-compile-current-file) - (stringp byte-compile-current-file)) - (cons (file-name-directory byte-compile-current-file) - load-path) + (if (and (boundp 'byte-compile-dest-file) + (stringp byte-compile-dest-file)) + (cons (file-name-directory byte-compile-dest-file) load-path) load-path))) - (load "cc-defs" nil t))) -(require 'cc-styles) -(require 'cc-engine) + (require 'cc-bytecomp))) + +(cc-require 'cc-defs) +(cc-require 'cc-vars) +(cc-require 'cc-styles) +(cc-require 'cc-engine) ;; In case c-mode.el isn't loaded @@ -154,5 +160,5 @@ This is in addition to c-continued-statement-offset.") (+ c-continued-statement-offset c-continued-brace-offset)) -(provide 'cc-compat) +(cc-provide 'cc-compat) ;;; cc-compat.el ends here diff --git a/lisp/progmodes/cc-defs.el b/lisp/progmodes/cc-defs.el index d7213d03469..b17cbdd5900 100644 --- a/lisp/progmodes/cc-defs.el +++ b/lisp/progmodes/cc-defs.el @@ -1,6 +1,6 @@ ;;; cc-defs.el --- compile time definitions for CC Mode -;; Copyright (C) 1985,87,92,93,94,95,96,97,98,99,2000 Free Software Foundation, Inc. +;; Copyright (C) 1985,1987,1992-2001 Free Software Foundation, Inc. ;; Authors: 2000- Martin Stjernholm ;; 1998-1999 Barry A. Warsaw and Martin Stjernholm @@ -25,31 +25,55 @@ ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs; see the file COPYING. If not, write to the -;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; along with this program; see the file COPYING. If not, write to +;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, ;; Boston, MA 02111-1307, USA. -;; Get all the necessary compile time definitions. -(require 'custom) -(require 'derived) ;only necessary in Emacs 20 +(eval-when-compile + (let ((load-path + (if (and (boundp 'byte-compile-dest-file) + (stringp byte-compile-dest-file)) + (cons (file-name-directory byte-compile-dest-file) load-path) + load-path))) + (require 'cc-bytecomp))) -;; cc-mode-19.el contains compatibility macros that should be compiled -;; in if needed. -(if (or (not (fboundp 'functionp)) - (not (condition-case nil - (progn (char-before) t) - (error nil))) - (not (condition-case nil - (progn (char-after) t) - (error nil))) - (not (fboundp 'when)) - (not (fboundp 'unless))) - (require 'cc-mode-19)) +;; cc-mode-19.el contains compatibility macros that should be used if +;; needed. +(eval-and-compile + (if (or (not (fboundp 'functionp)) + (not (condition-case nil + (progn (eval '(char-before)) t) + (error nil))) + (not (condition-case nil + (progn (eval '(char-after)) t) + (error nil))) + (not (fboundp 'when)) + (not (fboundp 'unless))) + (cc-load "cc-mode-19"))) + +;; Silence the compiler. +(cc-bytecomp-defvar c-enable-xemacs-performance-kludge-p) ; In cc-vars.el +(cc-bytecomp-defun buffer-syntactic-context-depth) ; XEmacs +(cc-bytecomp-defun region-active-p) ; XEmacs +(cc-bytecomp-defvar zmacs-region-stays) ; XEmacs +(cc-bytecomp-defvar zmacs-regions) ; XEmacs +(cc-bytecomp-defvar mark-active) ; Emacs +(cc-bytecomp-defun scan-lists) ; 5 args in XEmacs, 3 in Emacs +(require 'derived) ; Only necessary in Emacs -(defmacro c-point (position) - ;; Returns the value of point at certain commonly referenced POSITIONs. - ;; POSITION can be one of the following symbols: +;;; Macros. + +;;; Helpers for building regexps. +(defmacro c-paren-re (re) + `(concat "\\(" ,re "\\)")) +(defmacro c-identifier-re (re) + `(concat "\\<\\(" ,re "\\)\\>[^_]")) + +(defmacro c-point (position &optional point) + ;; Returns the value of certain commonly referenced POSITIONs + ;; relative to POINT. The current point is used if POINT isn't + ;; specified. POSITION can be one of the following symbols: ;; ;; bol -- beginning of line ;; eol -- end of line @@ -63,6 +87,7 @@ ;; ;; This function does not modify point or mark. `(save-excursion + ,(if point `(goto-char ,point)) ,(if (and (eq (car-safe position) 'quote) (symbolp (eval position))) (let ((position (eval position))) @@ -100,13 +125,81 @@ (t (error "unknown buffer position requested: %s" position))))) (point))) - (defmacro c-safe (&rest body) ;; safely execute BODY, return nil if an error occurred `(condition-case nil (progn ,@body) (error nil))) +(defmacro c-forward-sexp (&optional arg) + ;; like forward-sexp except + ;; 1. this is much stripped down from the XEmacs version + ;; 2. this cannot be used as a command, so we're insulated from + ;; XEmacs' losing efforts to make forward-sexp more user + ;; friendly + ;; 3. Preserves the semantics most of CC Mode is based on + (or arg (setq arg 1)) + `(goto-char (or (scan-sexps (point) ,arg) + ,(if (numberp arg) + (if (> arg 0) `(point-max) `(point-min)) + `(if (> ,arg 0) (point-max) (point-min)))))) + +(defmacro c-backward-sexp (&optional arg) + ;; See c-forward-sexp and reverse directions + (or arg (setq arg 1)) + `(c-forward-sexp ,(if (numberp arg) (- arg) `(- ,arg)))) + +(defmacro c-add-syntax (symbol &optional relpos) + ;; a simple macro to append the syntax in symbol to the syntax list. + ;; try to increase performance by using this macro + `(setq syntax (cons (cons ,symbol ,relpos) syntax))) + +(defmacro c-add-class-syntax (symbol classkey) + ;; 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. This is a macro mostly because + ;; c-add-syntax doesn't work otherwise. + `(save-restriction + (widen) + (let ((symbol ,symbol) + (classkey ,classkey) + inexpr) + (goto-char (aref classkey 1)) + (if (and (eq symbol 'inclass) (= (point) (c-point 'boi))) + (c-add-syntax symbol (point)) + (c-add-syntax symbol (aref classkey 0)) + (if (and c-inexpr-class-key + (setq inexpr (c-looking-at-inexpr-block)) + (/= (cdr inexpr) (c-point 'boi (cdr inexpr)))) + (c-add-syntax 'inexpr-class)))))) + +(defmacro c-update-modeline () + ;; set the c-auto-hungry-string for the correct designation on the modeline + `(progn + (setq c-auto-hungry-string + (if c-auto-newline + (if c-hungry-delete-key "/ah" "/a") + (if c-hungry-delete-key "/h" nil))) + (force-mode-line-update))) + +(defmacro c-with-syntax-table (table &rest code) + ;; Temporarily switches to the specified syntax table in a failsafe + ;; way to execute code. + `(let ((c-with-syntax-table-orig-table (syntax-table))) + (unwind-protect + (progn + (set-syntax-table ,table) + ,@code) + (set-syntax-table c-with-syntax-table-orig-table)))) +(put 'c-with-syntax-table 'lisp-indent-function 1) + +;;; Inline functions. + +;; Note: All these after the macros, to be on safe side in avoiding +;; bugs where macros are defined too late. These bugs often only show +;; when the files are compiled in a certain order within the same +;; session. + (defsubst c-beginning-of-defun-1 () ;; Wrapper around beginning-of-defun. ;; @@ -165,52 +258,25 @@ (if (< (point) start) (goto-char (point-max))))) -(defmacro c-forward-sexp (&optional arg) - ;; like forward-sexp except - ;; 1. this is much stripped down from the XEmacs version - ;; 2. this cannot be used as a command, so we're insulated from - ;; XEmacs' losing efforts to make forward-sexp more user - ;; friendly - ;; 3. Preserves the semantics most of CC Mode is based on - (or arg (setq arg 1)) - `(goto-char (or (scan-sexps (point) ,arg) - ,(if (numberp arg) - (if (> arg 0) `(point-max) `(point-min)) - `(if (> ,arg 0) (point-max) (point-min)))))) - -(defmacro c-backward-sexp (&optional arg) - ;; See c-forward-sexp and reverse directions - (or arg (setq arg 1)) - `(c-forward-sexp ,(if (numberp arg) (- arg) `(- ,arg)))) - -(defsubst c-beginning-of-macro (&optional lim) - ;; Go to the beginning of a cpp macro definition. Leaves point at - ;; the beginning of the macro and returns t if in a cpp macro - ;; definition, otherwise returns nil and leaves point unchanged. - ;; `lim' is currently ignored, but the interface requires it. - (let ((here (point))) - (beginning-of-line) - (while (eq (char-before (1- (point))) ?\\) - (forward-line -1)) - (back-to-indentation) - (if (and (<= (point) here) - (eq (char-after) ?#)) - t - (goto-char here) - nil))) - (defsubst c-forward-comment (count) ;; Insulation from various idiosyncrasies in implementations of - ;; `forward-comment'. Note: Some emacsen considers incorrectly that - ;; any line comment ending with a backslash continues to the next - ;; line. I can't think of any way to work around that in a reliable - ;; way without changing the buffer though. Suggestions welcome. ;) + ;; `forward-comment'. + ;; + ;; Note: Some emacsen considers incorrectly that any line comment + ;; ending with a backslash continues to the next line. I can't + ;; think of any way to work around that in a reliable way without + ;; changing the buffer though. Suggestions welcome. ;) + ;; + ;; Another note: When moving backwards over a block comment, there's + ;; a bug in forward-comment that can make it stop at "/*" inside a + ;; line comment. Haven't yet found a reasonably cheap way to kludge + ;; around that one either. :\ (let ((here (point))) (if (>= count 0) (when (forward-comment count) - ;; Emacs includes the ending newline in a b-style - ;; (c++) comment, but XEmacs don't. We depend on the - ;; Emacs behavior (which also is symmetric). + ;; Emacs includes the ending newline in a b-style (c++) + ;; comment, but XEmacs doesn't. We depend on the Emacs + ;; behavior (which also is symmetric). (if (and (eolp) (nth 7 (parse-partial-sexp here (point)))) (condition-case nil (forward-char 1))) t) @@ -229,26 +295,6 @@ (if (forward-comment count) (if (eolp) (forward-comment -1) t)))))) -(defmacro c-add-syntax (symbol &optional relpos) - ;; a simple macro to append the syntax in symbol to the syntax list. - ;; try to increase performance by using this macro - `(setq syntax (cons (cons ,symbol ,relpos) syntax))) - -(defmacro c-add-class-syntax (symbol classkey) - ;; 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. - `(save-restriction - (widen) - (let ((symbol ,symbol) - (classkey ,classkey)) - (goto-char (aref classkey 1)) - (if (and (eq symbol 'inclass) (= (point) (c-point 'boi))) - (c-add-syntax symbol (point)) - (c-add-syntax symbol (aref classkey 0)) - (if (and c-inexpr-class-key (c-looking-at-inexpr-block)) - (c-add-syntax 'inexpr-class)))))) - (defsubst c-intersect-lists (list alist) ;; return the element of ALIST that matches the first element found ;; in LIST. Uses assq. @@ -275,19 +321,9 @@ )) 0)) -(defmacro c-update-modeline () - ;; set the c-auto-hungry-string for the correct designation on the modeline - `(progn - (setq c-auto-hungry-string - (if c-auto-newline - (if c-hungry-delete-key "/ah" "/a") - (if c-hungry-delete-key "/h" nil))) - (force-mode-line-update))) - (defsubst c-keep-region-active () ;; Do whatever is necessary to keep the region active in XEmacs. - ;; Ignore byte-compiler warnings you might see. This is not needed - ;; for Emacs. + ;; This is not needed for Emacs. (and (boundp 'zmacs-region-stays) (setq zmacs-region-stays t))) @@ -308,17 +344,6 @@ (defsubst c-major-mode-is (mode) (eq (derived-mode-class major-mode) mode)) -(defmacro c-with-syntax-table (table &rest code) - ;; Temporarily switches to the specified syntax table in a failsafe - ;; way to execute code. - `(let ((c-with-syntax-table-orig-table (syntax-table))) - (unwind-protect - (progn - (set-syntax-table ,table) - ,@code) - (set-syntax-table c-with-syntax-table-orig-table)))) -(put 'c-with-syntax-table 'lisp-indent-function 1) - -(provide 'cc-defs) +(cc-provide 'cc-defs) ;;; cc-defs.el ends here diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el index a2ed75e1520..50613a21ad4 100644 --- a/lisp/progmodes/cc-engine.el +++ b/lisp/progmodes/cc-engine.el @@ -1,6 +1,6 @@ ;;; cc-engine.el --- core syntax guessing engine for CC mode -;; Copyright (C) 1985,87,92,93,94,95,96,97,98,99,2000 Free Software Foundation, Inc. +;; Copyright (C) 1985,1987,1992-2001 Free Software Foundation, Inc. ;; Authors: 2000- Martin Stjernholm ;; 1998-1999 Barry A. Warsaw and Martin Stjernholm @@ -25,21 +25,29 @@ ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs; see the file COPYING. If not, write to the -;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; along with this program; see the file COPYING. If not, write to +;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, ;; Boston, MA 02111-1307, USA. (eval-when-compile (let ((load-path - (if (and (boundp 'byte-compile-current-file) - (stringp byte-compile-current-file)) - (cons (file-name-directory byte-compile-current-file) - load-path) + (if (and (boundp 'byte-compile-dest-file) + (stringp byte-compile-dest-file)) + (cons (file-name-directory byte-compile-dest-file) load-path) load-path))) - (load "cc-defs" nil t))) -(require 'cc-langs) + (require 'cc-bytecomp))) + +(cc-require 'cc-defs) +(cc-require 'cc-vars) +(cc-require 'cc-langs) + +;; Silence the compiler. +(cc-bytecomp-defun buffer-syntactic-context) ; XEmacs +(defvar c-state-cache nil) +(defvar c-in-literal-cache t) + ;; KLUDGE ALERT: c-maybe-labelp is used to pass information between ;; c-crosses-statement-barrier-p and c-beginning-of-statement-1. A ;; better way should be implemented, but this will at least shut up @@ -203,7 +211,7 @@ ;; We always want to skip over the non-whitespace modifier ;; characters that can start a statement. (let ((lim (point))) - (skip-chars-backward "-+!*&~@` \t\n" (c-point 'boi)) + (skip-chars-backward "-+!*&~@`# \t\n" (c-point 'boi)) (skip-chars-forward " \t\n" lim)))) (defun c-end-of-statement-1 () @@ -258,6 +266,22 @@ crossedp)) +(defun c-beginning-of-macro (&optional lim) + ;; Go to the beginning of a cpp macro definition. Leaves point at + ;; the beginning of the macro and returns t if in a cpp macro + ;; definition, otherwise returns nil and leaves point unchanged. + ;; `lim' is currently ignored, but the interface requires it. + (let ((here (point))) + (beginning-of-line) + (while (eq (char-before (1- (point))) ?\\) + (forward-line -1)) + (back-to-indentation) + (if (and (<= (point) here) + (eq (char-after) ?#)) + t + (goto-char here) + nil))) + ;; Skipping of "syntactic whitespace", defined as lexical whitespace, ;; C and C++ style comments, and preprocessor directives. Search no ;; farther back or forward than optional LIM. If LIM is omitted, @@ -317,26 +341,25 @@ '(?w ?_ ?\" ?\\ ?/ ?'))) (last (point)) (prev (point))) - (if (/= (point) - (progn (c-forward-syntactic-ws) (point))) - ;; Skip whitespace. Count this as a move if we did in fact - ;; move and aren't out of bounds. - (or (eobp) - (and lim (> (point) lim)) - (setq count (max (1- count) 0)))) - (if (and (= count 0) - (or (and (memq (char-syntax (or (char-after) ? )) '(?w ?_)) - (memq (char-syntax (or (char-before) ? )) '(?w ?_))) - (eobp))) - ;; If count is zero we should jump if in the middle of a - ;; token or if there is whitespace between point and the - ;; following token beginning. - (setq count 1)) - ;; Avoid having the limit tests inside the loop. (save-restriction (if lim (narrow-to-region (point-min) lim)) + (if (/= (point) + (progn (c-forward-syntactic-ws) (point))) + ;; Skip whitespace. Count this as a move if we did in fact + ;; move and aren't out of bounds. + (or (eobp) + (setq count (max (1- count) 0)))) + (if (and (= count 0) + (or (and (memq (char-syntax (or (char-after) ? )) '(?w ?_)) + (memq (char-syntax (or (char-before) ? )) '(?w ?_))) + (eobp))) + ;; If count is zero we should jump if in the middle of a + ;; token or if there is whitespace between point and the + ;; following token beginning. + (setq count 1)) (if (eobp) (goto-char last) + ;; Avoid having the limit tests inside the loop. (condition-case nil (while (> count 0) (setq prev last @@ -370,11 +393,11 @@ ;; token or if there is whitespace between point and the ;; following token beginning. (setq count 1)) - ;; Avoid having the limit tests inside the loop. (save-restriction (if lim (narrow-to-region lim (point-max))) (or (bobp) (progn + ;; Avoid having the limit tests inside the loop. (condition-case nil (while (progn (setq last (point)) @@ -398,8 +421,7 @@ (defun c-in-literal (&optional lim) ;; Determine if point is in a C++ literal. we cache the last point ;; calculated if the cache is enabled - (if (and (boundp 'c-in-literal-cache) - c-in-literal-cache + (if (and (vectorp c-in-literal-cache) (= (point) (aref c-in-literal-cache 0))) (aref c-in-literal-cache 1) (let ((rtn (save-excursion @@ -411,8 +433,8 @@ ((c-beginning-of-macro lim) 'pound) (t nil)))))) ;; cache this result if the cache is enabled - (and (boundp 'c-in-literal-cache) - (setq c-in-literal-cache (vector (point) rtn))) + (if (not c-in-literal-cache) + (setq c-in-literal-cache (vector (point) rtn))) rtn))) ;; XEmacs has a built-in function that should make this much quicker. @@ -573,11 +595,16 @@ (looking-at "//"))) (let ((col (current-column)) (beg (point)) + (bopl (c-point 'bopl)) (end (cdr range))) + ;; Got to take care in the backward direction to handle + ;; comments which are preceded by code. (while (and (c-forward-comment -1) + (>= (point) bopl) (looking-at "//") (= col (current-column))) - (setq beg (point))) + (setq beg (point) + bopl (c-point 'bopl))) (goto-char end) (while (and (progn (skip-chars-forward " \t") (looking-at "//")) @@ -611,8 +638,7 @@ ;; earlier in the file and point. ;; ;; if there's a state cache, return it - (setq c-parsing-error nil) - (if (boundp 'c-state-cache) c-state-cache + (if c-state-cache c-state-cache (let* (at-bob (pos (save-excursion ;; go back 2 bods, but ignore any bogus positions @@ -641,7 +667,7 @@ (here (save-excursion ;;(skip-chars-forward " \t}") (point))) - (last-bod pos) (last-pos pos) + (last-bod here) (last-pos pos) placeholder state sexp-end) ;; cache last bod position (while (catch 'backup-bod @@ -680,9 +706,13 @@ (while t (setq last-bod (c-safe (scan-lists last-bod -1 1))) (if (not last-bod) - (progn + (save-excursion ;; bogus, but what can we do here? - (setq c-parsing-error (1- placeholder)) + (goto-char placeholder) + (beginning-of-line) + (setq c-parsing-error + (format "\ +Unbalanced close brace at line %d" (1+ (count-lines 1 (point))))) (throw 'backup-bod nil)) (setq at-bob (= last-bod (point-min)) pos last-bod) @@ -910,13 +940,11 @@ brace." (defun c-backward-to-start-of-if (&optional lim) ;; Move to the start of the last "unbalanced" if and return t. If ;; none is found, and we are looking at an if clause, nil is - ;; returned. If none is found and we are looking at an else clause, - ;; an error is thrown. + ;; returned. (let ((if-level 1) (here (c-point 'bol)) (case-fold-search nil) - (lim (or (and (>= (point) lim) - lim) + (lim (or (and lim (>= (point) lim) lim) (c-point 'bod))) (at-if (looking-at "if\\b[^_]"))) (catch 'orphan-if @@ -926,10 +954,13 @@ brace." (condition-case nil (c-backward-sexp 1) (error - (if at-if - (throw 'orphan-if nil) - (error "No matching `if' found for `else' on line %d." - (1+ (count-lines 1 here)))))) + (unless at-if + (goto-char here) + (c-beginning-of-statement-1) + (setq c-parsing-error + (format "No matching `if' found for `else' on line %d" + (1+ (count-lines 1 here)))) + (throw 'orphan-if nil)))) (cond ((looking-at "else\\b[^_]") (setq if-level (1+ if-level))) @@ -937,7 +968,7 @@ brace." ;; check for else if... skip over (let ((here (point))) (c-safe (c-forward-sexp -1)) - (if (looking-at "\\[ \t]+\\") + (if (looking-at "\\[ \t]+\\[^_]") nil (setq if-level (1- if-level)) (goto-char here)))) @@ -952,9 +983,11 @@ brace." ;; statements in parentheses. No error checking is performed. (c-forward-sexp (cond ;; else if() - ((looking-at "\\[ \t]+\\") 3) + ((looking-at "\\[ \t]+\\\\([^_]\\|$\\)") 3) ;; do, else, try, finally - ((looking-at "\\<\\(do\\|else\\|try\\|finally\\)\\>") 1) + ((looking-at + "\\<\\(do\\|else\\|try\\|finally\\)\\>\\([^_]\\|$\\)") + 1) ;; for, if, while, switch, catch, synchronized, foreach (t 2)))) @@ -991,25 +1024,31 @@ brace." (if (eq (char-after) ?,) (forward-char 1) (c-backward-syntactic-ws limit)) - (while (and (< limit (point)) - (eq (char-before) ?,)) - ;; this will catch member inits with multiple - ;; line arglists - (forward-char -1) - (c-backward-syntactic-ws) - (if (eq (char-before) ?\)) - (c-backward-sexp 2) - (c-backward-sexp 1)) - ;; Skip backwards over a fully::qualified::name. - (c-backward-syntactic-ws limit) - (while (and (eq (char-before) ?:) - (save-excursion - (forward-char -1) - (eq (char-before) ?:))) - (backward-char 2) - (c-backward-sexp 1)) - ;; now continue checking - (c-backward-syntactic-ws limit)) + (c-with-syntax-table (if (c-major-mode-is 'c++-mode) + c++-template-syntax-table + (syntax-table)) + (while (and (< limit (point)) + (eq (char-before) ?,)) + ;; this will catch member inits with multiple + ;; line arglists + (forward-char -1) + (c-backward-syntactic-ws) + (if (eq (char-before) ?\)) + (c-backward-sexp 2) + (c-backward-sexp 1)) + ;; Skip over any template arg to the class. + (if (eq (char-after) ?<) + (c-backward-sexp 1)) + ;; Skip backwards over a fully::qualified::name. + (c-backward-syntactic-ws limit) + (while (and (eq (char-before) ?:) + (save-excursion + (forward-char -1) + (eq (char-before) ?:))) + (backward-char 2) + (c-backward-sexp 1)) + ;; now continue checking + (c-backward-syntactic-ws limit))) (and (< limit (point)) (eq (char-before) ?:))) @@ -1160,7 +1199,8 @@ brace." ;; return the buffer position of the beginning of the brace list ;; statement if we're inside a brace list, otherwise return nil. ;; CONTAINING-SEXP is the buffer pos of the innermost containing - ;; paren. BRACE-STATE is the remainder of the state of enclosing braces + ;; paren. BRACE-STATE is the remainder of the state of enclosing + ;; braces ;; ;; N.B.: This algorithm can potentially get confused by cpp macros ;; places in inconvenient locations. Its a trade-off we make for @@ -1213,7 +1253,7 @@ brace." (while (eq braceassignp 'dontknow) (setq braceassignp (cond ((/= (c-backward-token-1 1 t lim) 0) nil) - ((looking-at "new\\>") t) + ((looking-at "new\\>[^_]") t) ((looking-at "\\sw\\|\\s_\\|[.[]") ;; Carry on looking if this is an ;; identifier (may contain "." in Java) @@ -1238,22 +1278,29 @@ brace." (cond ;; Check for operator = ((looking-at "operator\\>") nil) - ;; Check for `= (Pike) - ((eq (char-after) ?`) nil) + ;; Check for `= 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 - ((save-excursion - (let ((here (point)) - (pos< (progn - (skip-chars-backward "^<") - (point)))) - (and (c-major-mode-is 'c++-mode) - (eq (char-before) ?<) - (not (c-crosses-statement-barrier-p - pos< here)) - (not (c-in-literal)) - ))) + ((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)))))) (if (and (eq braceassignp 'dontknow) @@ -1394,6 +1441,28 @@ brace." (if (>= (point) lim) (c-looking-at-inexpr-block lim)))))))) +(defun c-on-identifier () + ;; Returns non-nil if we're on or directly after an identifier. + (if (or (memq (char-syntax (or (char-after) ? )) '(?w ?_)) + (memq (char-syntax (or (char-before) ? )) '(?w ?_))) + (save-excursion + (skip-syntax-backward "w_") + (not (looking-at c-keywords))) + (if (c-major-mode-is 'pike-mode) + ;; Handle the ` syntax in Pike. + (save-excursion + (if (eq (char-after) ?\`) (forward-char)) + (skip-chars-backward "!%&*+\\-/<=>^|~") + (let ((pos (point))) + (cond ((memq (char-before) '(?\) ?\])) + (c-safe (backward-char 2))) + ((memq (char-before) '(?\( ?\[)) + (c-safe (backward-char 1)))) + (if (not (looking-at "()\\|\\[]")) + (goto-char pos))) + (and (eq (char-before) ?\`) + (looking-at "[-!%&*+/<=>^|~]\\|()\\|\\[]")))))) + (defun c-most-enclosing-brace (state) ;; return the bufpos of the most enclosing brace that hasn't been @@ -1562,8 +1631,10 @@ brace." 'inline-open 'lambda-intro-cont))) (goto-char (cdr placeholder)) - (c-add-syntax tmpsymbol (c-point 'boi)) - (c-add-syntax (car placeholder))) + (back-to-indentation) + (c-add-syntax tmpsymbol (point)) + (unless (eq (point) (cdr placeholder)) + (c-add-syntax (car placeholder)))) ;; CASE 5: Line is at top level. ((null containing-sexp) (cond @@ -1602,12 +1673,7 @@ brace." ;; to go through much chicanery to ignore the cache. ;; But of course, there may not be! BLECH! BOGUS! (let ((decl - (if (boundp 'c-state-cache) - (let ((old-cache c-state-cache)) - (prog2 - (makunbound 'c-state-cache) - (c-search-uplist-for-classkey (c-parse-state)) - (setq c-state-cache old-cache))) + (let ((c-state-cache nil)) (c-search-uplist-for-classkey (c-parse-state)) ))) (and decl @@ -1625,20 +1691,38 @@ brace." (c-forward-syntactic-ws indent-point))) (setq placeholder (c-point 'boi)) (or (consp special-brace-list) - (and (or (looking-at "enum[ \t\n]+") - (save-excursion + (and (or (save-excursion (goto-char indent-point) + (setq tmpsymbol nil) (while (and (> (point) placeholder) (= (c-backward-token-1 1 t) 0) - (/= (char-after) ?=))) - (eq (char-after) ?=))) + (/= (char-after) ?=)) + (if (and (not tmpsymbol) + (looking-at "new\\>[^_]")) + (setq tmpsymbol 'topmost-intro-cont))) + (eq (char-after) ?=)) + (looking-at "enum[ \t\n]+")) (save-excursion (while (and (< (point) indent-point) (= (c-forward-token-1 1 t) 0) (not (memq (char-after) '(?\; ?\())))) (not (memq (char-after) '(?\; ?\())) )))) - (c-add-syntax 'brace-list-open placeholder)) + (if (and (c-major-mode-is 'java-mode) + (eq tmpsymbol 'topmost-intro-cont)) + ;; We're in Java and have found that the open brace + ;; belongs to a "new Foo[]" initialization list, + ;; which means the brace list is part of an + ;; expression and not a top level definition. We + ;; therefore treat it as any topmost continuation + ;; even though the semantically correct symbol still + ;; is brace-list-open, on the same grounds as in + ;; case 10B.2. + (progn + (c-beginning-of-statement-1 lim) + (c-forward-syntactic-ws) + (c-add-syntax 'topmost-intro-cont (c-point 'boi))) + (c-add-syntax 'brace-list-open placeholder))) ;; CASE 5A.4: inline defun open ((and inclass-p (not inenclosing-p)) (c-add-syntax 'inline-open) @@ -2042,14 +2126,10 @@ brace." ;; opening paren. This case includes multi-line ;; mathematical paren groupings, but we could be on a ;; for-list continuation line - ((and (save-excursion - (goto-char (1+ containing-sexp)) - (skip-chars-forward " \t") - (not (eolp))) - (save-excursion - (c-beginning-of-statement-1 lim) - (skip-chars-backward " \t([") - (<= (point) containing-sexp))) + ((save-excursion + (goto-char (1+ containing-sexp)) + (skip-chars-forward " \t") + (not (eolp))) (goto-char containing-sexp) (setq placeholder (c-point 'boi)) (when (and (c-safe (backward-up-list 1) t) @@ -2102,8 +2182,10 @@ brace." (eq char-after-ip (car (cdr special-brace-list)))) (goto-char (car (car special-brace-list))) (skip-chars-backward " \t") - (if (bolp) - (setq syntax (c-guess-basic-syntax)) + (if (and (bolp) + (assoc 'statement-cont + (setq placeholder (c-guess-basic-syntax)))) + (setq syntax placeholder) (c-beginning-of-statement-1 lim) (c-forward-token-1 0) (if (looking-at "typedef\\>") (c-forward-token-1 1)) @@ -2151,7 +2233,7 @@ brace." (c-add-syntax 'brace-list-intro (c-point 'boi)) ) ; end CASE 9C ;; CASE 9D: this is just a later brace-list-entry or - ;; brace-entry-open + ;; brace-entry-open (t (if (or (eq char-after-ip ?{) (and c-special-brace-lists (save-excursion @@ -2346,8 +2428,10 @@ brace." (if (= containing-sexp (point)) (c-add-syntax tmpsymbol (point)) (goto-char (cdr placeholder)) - (c-add-syntax tmpsymbol (c-point 'boi)) - (c-add-syntax (car placeholder)))) + (back-to-indentation) + (c-add-syntax tmpsymbol (point)) + (if (/= (point) (cdr placeholder)) + (c-add-syntax (car placeholder))))) ;; CASE 16B: does this close an inline or a function in ;; an extern block or namespace? ((progn @@ -2480,8 +2564,10 @@ brace." (if (= containing-sexp (point)) (c-add-syntax block-intro (point)) (goto-char (cdr placeholder)) - (c-add-syntax block-intro (c-point 'boi)) - (c-add-syntax (car placeholder)))) + (back-to-indentation) + (c-add-syntax block-intro (point)) + (if (/= (point) (cdr placeholder)) + (c-add-syntax (car placeholder))))) (if (eq char-after-ip ?{) (c-add-syntax 'block-open))) ;; CASE 17F: first statement in an inline, or first @@ -2533,7 +2619,8 @@ brace." (skip-chars-forward " \t") (cond ;; are we looking at a comment only line? - ((looking-at c-comment-start-regexp) + ((and (looking-at c-comment-start-regexp) + (/= (c-forward-token-1 0 nil (c-point 'eol)) 0)) (c-add-syntax 'comment-intro)) ;; we might want to give additional offset to friends (in C++). ((and (c-major-mode-is 'c++-mode) @@ -2544,17 +2631,17 @@ brace." (= (save-excursion (c-beginning-of-macro lim) (setq placeholder (point))) - (c-point 'boi))) + (c-point 'boi)) + (not (and (c-major-mode-is 'pike-mode) + (eq (char-after (1+ placeholder)) ?\")))) (c-add-syntax 'cpp-macro))) ;; return the syntax syntax)))) -(defun c-echo-parsing-error () - (if (not c-parsing-error) - nil - (message "unbalanced close brace at bufpos %d -- INDENTATION IS SUSPECT!" - c-parsing-error) +(defun c-echo-parsing-error (&optional quiet) + (when (and c-parsing-error (not quiet)) + (message "%s" c-parsing-error) (ding)) c-parsing-error) @@ -2573,21 +2660,99 @@ brace." (if (> (- (point-max) pos) (point)) (goto-char (- (point-max) pos)))))) -(defun c-indent-line (&optional syntax) - ;; Indent the current line as C/C++/ObjC code, if +(defun c-evaluate-offset (offset langelem symbol) + ;; offset can be a number, a function, a variable, a list, or one of + ;; the symbols + or - + (cond + ((eq offset '+) c-basic-offset) + ((eq offset '-) (- c-basic-offset)) + ((eq offset '++) (* 2 c-basic-offset)) + ((eq offset '--) (* 2 (- c-basic-offset))) + ((eq offset '*) (/ c-basic-offset 2)) + ((eq offset '/) (/ (- c-basic-offset) 2)) + ((numberp offset) offset) + ((functionp offset) (c-evaluate-offset + (funcall offset langelem) langelem symbol)) + ((vectorp offset) offset) + ((null offset) nil) + ((listp offset) + (let (done) + (while (and (not done) offset) + (setq done (c-evaluate-offset (car offset) langelem symbol) + offset (cdr offset))) + (if (not done) + (if c-strict-syntax-p + (error "No offset found for syntactic symbol %s" symbol)) + done))) + (t (symbol-value offset)) + )) + +(defun c-get-offset (langelem) + ;; Get offset from LANGELEM which is a cons cell of the form: + ;; (SYMBOL . RELPOS). The symbol is matched against + ;; c-offsets-alist and the offset found there is either returned, + ;; or added to the indentation at RELPOS. If RELPOS is nil, then + ;; the offset is simply returned. + (let* ((symbol (car langelem)) + (relpos (cdr langelem)) + (match (assq symbol c-offsets-alist)) + (offset (cdr-safe match))) + (if (not match) + (if c-strict-syntax-p + (error "No offset found for syntactic symbol %s" symbol) + (setq offset 0 + relpos 0)) + (setq offset (c-evaluate-offset offset langelem symbol))) + (if (vectorp offset) + offset + (+ (if (and relpos + (< relpos (c-point 'bol))) + (save-excursion + (goto-char relpos) + (current-column)) + 0) + (or (and (numberp offset) offset) + (and (symbolp offset) (symbol-value offset)) + 0))) + )) + +(defun c-get-syntactic-indentation (langelems) + ;; Apply c-get-offset to a list of langelem cells to get the total + ;; syntactic indentation. Special treatment is needed for vectors + ;; containing absolute columns. + (let ((indent 0)) + (catch 'done + (while langelems + (let ((res (c-get-offset (car langelems)))) + (if (vectorp res) + (throw 'done (elt res 0)) + (setq indent (+ indent res) + langelems (cdr langelems))))) + indent))) + +(defun c-indent-line (&optional syntax quiet) + ;; Indent the current line according to the syntactic context, if ;; c-syntactic-indentation is non-nil. Optional SYNTAX is the - ;; syntactic information for the current line. Returns the amount - ;; of indentation change (in columns). + ;; syntactic information for the current line. Be silent about + ;; syntactic errors if the optional argument QUIET is non-nil. + ;; Returns the amount of indentation change (in columns). (let (shift-amt) (if c-syntactic-indentation - (let* ((c-syntactic-context (or syntax (c-guess-basic-syntax))) - (indent (apply '+ (mapcar 'c-get-offset c-syntactic-context)))) - (and c-echo-syntactic-information-p - (not (c-echo-parsing-error)) - (message "syntax: %s, indent= %d" c-syntactic-context indent)) - (setq shift-amt (- indent (current-indentation))) - (c-shift-line-indentation shift-amt) - (run-hooks 'c-special-indent-hook)) + (setq c-parsing-error + (or (let* ((c-parsing-error nil) + (c-syntactic-context (or syntax + c-syntactic-context + (c-guess-basic-syntax))) + (indent (c-get-syntactic-indentation c-syntactic-context))) + (and (not (c-echo-parsing-error quiet)) + c-echo-syntactic-information-p + (message "syntax: %s, indent: %d" + c-syntactic-context indent)) + (setq shift-amt (- indent (current-indentation))) + (c-shift-line-indentation shift-amt) + (run-hooks 'c-special-indent-hook) + c-parsing-error) + c-parsing-error)) (let ((indent 0)) (save-excursion (while (and (= (forward-line -1) 0) @@ -2606,8 +2771,7 @@ With universal argument, inserts the analysis as a comment on that line." (interactive "P") (let ((syntax (c-guess-basic-syntax))) (if (not (consp arg)) - (if (not (c-echo-parsing-error)) - (message "syntactic analysis: %s" syntax)) + (message "syntactic analysis: %s" syntax) (indent-for-comment) (insert (format "%s" syntax)) )) @@ -2625,5 +2789,5 @@ With universal argument, inserts the analysis as a comment on that line." (forward-line))))) -(provide 'cc-engine) +(cc-provide 'cc-engine) ;;; cc-engine.el ends here diff --git a/lisp/progmodes/cc-langs.el b/lisp/progmodes/cc-langs.el index 98620b73317..8bd60ff8d4a 100644 --- a/lisp/progmodes/cc-langs.el +++ b/lisp/progmodes/cc-langs.el @@ -1,7 +1,6 @@ -;;; cc-langs.el --- specific language support for CC Mode +;;; cc-langs.el --- language specific settings for CC Mode -;; Copyright (C) 1985,1987,1992,1993,1994,1995,1996,1997,1998,2000 -;; Free Software Foundation, Inc. +;; Copyright (C) 1985,1987,1992-2001 Free Software Foundation, Inc. ;; Authors: 2000- Martin Stjernholm ;; 1998-1999 Barry A. Warsaw and Martin Stjernholm @@ -26,30 +25,20 @@ ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs; see the file COPYING. If not, write to the -;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; along with this program; see the file COPYING. If not, write to +;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, ;; Boston, MA 02111-1307, USA. (eval-when-compile (let ((load-path - (if (and (boundp 'byte-compile-current-file) - (stringp byte-compile-current-file)) - (cons (file-name-directory byte-compile-current-file) - load-path) + (if (and (boundp 'byte-compile-dest-file) + (stringp byte-compile-dest-file)) + (cons (file-name-directory byte-compile-dest-file) load-path) load-path))) - (load "cc-defs" nil t))) -(require 'cc-styles) + (require 'cc-bytecomp))) -;; Pull in some other packages. -(eval-when-compile - (condition-case nil - ;; Not required and only needed during compilation to shut up - ;; the compiler. - (require 'outline) - (error nil))) -;; menu support for both XEmacs and Emacs. If you don't have easymenu -;; with your version of Emacs, you are incompatible! -(require 'easymenu) +(cc-require 'cc-defs) +(cc-require 'cc-vars) (defvar c-buffer-is-cc-mode nil @@ -65,9 +54,6 @@ Otherwise, this variable is nil. I.e. this variable is non-nil for ;; Regular expressions and other values which must be parameterized on ;; a per-language basis. -;; Keywords defining protection levels -(defconst c-protection-key "\\<\\(public\\|protected\\|private\\)\\>") - ;; Regex describing a `symbol' in all languages. We cannot use just ;; `word' syntax class since `_' cannot be in word class. Putting ;; underscore in word class breaks forward word movement behavior that @@ -78,40 +64,219 @@ Otherwise, this variable is nil. I.e. this variable is non-nil for ;; definition of a symbol as being Unicode. I know so little about ;; I18N (except how to sound cool and say I18N :-) that I'm willing to ;; punt on this for now. - (defconst c-symbol-key "[_a-zA-Z]\\(\\w\\|\\s_\\)*") - -;; keywords introducing class definitions. language specific -(defconst c-C-class-key "\\(struct\\|union\\)") -(defconst c-C++-class-key "\\(class\\|struct\\|union\\)") -(defconst c-IDL-class-key "\\(interface\\|struct\\|union\\|valuetype\\)") -(defconst c-C-extra-toplevel-key "\\(extern\\)") -(defconst c-C++-extra-toplevel-key "\\(extern\\|namespace\\)") -(defconst c-IDL-extra-toplevel-key "\\(module\\)") +;; HELPME: Many of the following keyword lists are more or less bogus +;; for some languages (notably ObjC and IDL). The effects of the +;; erroneous values in the language handling is miniscule since these +;; constants are not used very much (yet, anyway) in the actual syntax +;; detection code, but I'd still appreciate help to get them correct. + +;; Primitive type keywords. +(defconst c-C-primitive-type-kwds + "char\\|double\\|float\\|int\\|long\\|short\\|signed\\|unsigned\\|void") +(defconst c-C++-primitive-type-kwds c-C-primitive-type-kwds) +(defconst c-ObjC-primitive-type-kwds c-C-primitive-type-kwds) +(defconst c-Java-primitive-type-kwds + "boolean\\|byte\\|char\\|double\\|float\\|int\\|long\\|short\\|void") +(defconst c-IDL-primitive-type-kwds c-C-primitive-type-kwds) +(defconst c-Pike-primitive-type-kwds + (concat "constant\\|float\\|int\\|mapping\\|multiset\\|object\\|" + "program\\|string\\|void")) + +;; Declaration specifier keywords. +(defconst c-C-specifier-kwds + "auto\\|const\\|extern\\|register\\|static\\|volatile") +(defconst c-C++-specifier-kwds + (concat c-C-specifier-kwds "\\|friend\\|inline\\|virtual")) +(defconst c-ObjC-specifier-kwds c-C++-specifier-kwds) +(defconst c-Java-specifier-kwds + ;; Note: `const' is not used, but it's still a reserved keyword. + (concat "abstract\\|const\\|final\\|native\\|private\\|protected\\|" + "public\\|static\\|synchronized\\|transient\\|volatile")) +(defconst c-IDL-specifier-kwds c-C++-specifier-kwds) +(defconst c-Pike-specifier-kwds + (concat "final\\|inline\\|local\\|nomask\\|optional\\|private\\|" + "protected\\|static\\|variant")) + +;; Class/struct declaration keywords. +(defconst c-C-class-kwds "struct\\|union") +(defconst c-C++-class-kwds (concat c-C-class-kwds "\\|class")) +(defconst c-ObjC-class-kwds "interface\\|implementation") +(defconst c-Java-class-kwds "class\\|interface") +(defconst c-IDL-class-kwds + (concat c-C++-class-kwds "\\|interface\\|valuetype")) +(defconst c-Pike-class-kwds "class") + +;; Keywords introducing other declaration-level blocks. +(defconst c-C-extra-toplevel-kwds "extern") +(defconst c-C++-extra-toplevel-kwds + (concat c-C-extra-toplevel-kwds "\\|namespace")) +;;(defconst c-ObjC-extra-toplevel-kwds nil) +;;(defconst c-Java-extra-toplevel-kwds nil) +(defconst c-IDL-extra-toplevel-kwds "module") +;;(defconst c-Pike-extra-toplevel-kwds nil) + +;; Keywords introducing other declaration-level constructs. +(defconst c-C-other-decl-kwds "enum\\|typedef") +(defconst c-C++-other-decl-kwds (concat c-C-other-decl-kwds "\\|template")) +;;(defconst c-ObjC-other-decl-kwds nil) +(defconst c-Java-other-decl-kwds "import\\|package") +;;(defconst c-IDL-other-decl-kwds nil) +(defconst c-Pike-other-decl-kwds "import\\|inherit") + +;; Keywords that occur in declaration-level constructs. +;;(defconst c-C-decl-level-kwds nil) +;;(defconst c-C++-decl-level-kwds nil) +;;(defconst c-ObjC-decl-level-kwds nil) +(defconst c-Java-decl-level-kwds "extends\\|implements\\|throws") +;;(defconst c-IDL-decl-level-kwds nil) +;;(defconst c-Pike-decl-level-kwds nil) + +;; Protection label keywords in classes. +;;(defconst c-C-protection-kwds nil) +(defconst c-C++-protection-kwds "private\\|protected\\|public") +(defconst c-ObjC-protection-kwds c-C++-protection-kwds) +;;(defconst c-Java-protection-kwds nil) +;;(defconst c-IDL-protection-kwds nil) +;;(defconst c-Pike-protection-kwds nil) + +;; Statement keywords followed directly by a block. +(defconst c-C-block-stmt-1-kwds "do\\|else") +(defconst c-C++-block-stmt-1-kwds + (concat c-C-block-stmt-1-kwds "\\|asm\\|try")) +(defconst c-ObjC-block-stmt-1-kwds c-C++-block-stmt-1-kwds) +(defconst c-Java-block-stmt-1-kwds + (concat c-C-block-stmt-1-kwds "\\|finally\\|try")) +;;(defconst c-IDL-block-stmt-1-kwds nil) +(defconst c-Pike-block-stmt-1-kwds c-C-block-stmt-1-kwds) + +;; Statement keywords followed by a paren sexp and then by a block. +(defconst c-C-block-stmt-2-kwds "for\\|if\\|switch\\|while") +(defconst c-C++-block-stmt-2-kwds (concat c-C-block-stmt-2-kwds "\\|catch")) +(defconst c-ObjC-block-stmt-2-kwds c-C++-block-stmt-2-kwds) +(defconst c-Java-block-stmt-2-kwds + (concat c-C++-block-stmt-2-kwds "\\|synchronized")) +;;(defconst c-IDL-block-stmt-2-kwds nil) +(defconst c-Pike-block-stmt-2-kwds c-C-block-stmt-2-kwds) + +;; Statement keywords followed by an expression or nothing. +(defconst c-C-simple-stmt-kwds "break\\|continue\\|goto\\|return") +(defconst c-C++-simple-stmt-kwds c-C-simple-stmt-kwds) +(defconst c-ObjC-simple-stmt-kwds c-C-simple-stmt-kwds) +(defconst c-Java-simple-stmt-kwds + ;; Note: `goto' is not a valid statement, but the keyword is still reserved. + (concat c-C-simple-stmt-kwds "\\|throw")) +;;(defconst c-IDL-simple-stmt-kwds nil) +(defconst c-Pike-simple-stmt-kwds "break\\|continue\\|return") + +;; Keywords introducing labels in blocks. +(defconst c-C-label-kwds "case\\|default") +(defconst c-C++-label-kwds c-C-label-kwds) +(defconst c-ObjC-label-kwds c-C-label-kwds) +(defconst c-Java-label-kwds c-C-label-kwds) +;;(defconst c-IDL-label-kwds nil) +(defconst c-Pike-label-kwds c-C-label-kwds) + +;; Keywords that can occur anywhere in expressions. +(defconst c-C-expr-kwds "sizeof") +(defconst c-C++-expr-kwds + (concat c-C-expr-kwds "\\|delete\\|new\\|operator\\|this\\|throw")) +(defconst c-ObjC-expr-kwds c-C-expr-kwds) +(defconst c-Java-expr-kwds "instanceof\\|new\\|super\\|this") +;;(defconst c-IDL-expr-kwds nil) +(defconst c-Pike-expr-kwds + (concat c-C-expr-kwds "\\|catch\\|class\\|gauge\\|lambda\\|predef")) + +;; All keywords. +(defconst c-C-keywords + (concat c-C-primitive-type-kwds "\\|" c-C-specifier-kwds + "\\|" c-C-class-kwds "\\|" c-C-extra-toplevel-kwds + "\\|" c-C-other-decl-kwds + ;; "\\|" c-C-decl-level-kwds "\\|" c-C-protection-kwds + "\\|" c-C-block-stmt-1-kwds "\\|" c-C-block-stmt-2-kwds + "\\|" c-C-simple-stmt-kwds "\\|" c-C-label-kwds + "\\|" c-C-expr-kwds)) +(defconst c-C++-keywords + (concat c-C++-primitive-type-kwds "\\|" c-C++-specifier-kwds + "\\|" c-C++-class-kwds "\\|" c-C++-extra-toplevel-kwds + "\\|" c-C++-other-decl-kwds + ;; "\\|" c-C++-decl-level-kwds + "\\|" c-C++-protection-kwds + "\\|" c-C++-block-stmt-1-kwds "\\|" c-C++-block-stmt-2-kwds + "\\|" c-C++-simple-stmt-kwds "\\|" c-C++-label-kwds + "\\|" c-C++-expr-kwds)) +(defconst c-ObjC-keywords + (concat c-ObjC-primitive-type-kwds "\\|" c-ObjC-specifier-kwds + "\\|" c-ObjC-class-kwds + ;; "\\|" c-ObjC-extra-toplevel-kwds + ;; "\\|" c-ObjC-other-decl-kwds "\\|" c-ObjC-decl-level-kwds + "\\|" c-ObjC-protection-kwds + "\\|" c-ObjC-block-stmt-1-kwds "\\|" c-ObjC-block-stmt-2-kwds + "\\|" c-ObjC-simple-stmt-kwds "\\|" c-ObjC-label-kwds + "\\|" c-ObjC-expr-kwds)) +(defconst c-Java-keywords + (concat c-Java-primitive-type-kwds "\\|" c-Java-specifier-kwds + "\\|" c-Java-class-kwds + ;; "\\|" c-Java-extra-toplevel-kwds + "\\|" c-Java-other-decl-kwds "\\|" c-Java-decl-level-kwds + ;; "\\|" c-Java-protection-kwds + "\\|" c-Java-block-stmt-1-kwds "\\|" c-Java-block-stmt-2-kwds + "\\|" c-Java-simple-stmt-kwds "\\|" c-Java-label-kwds + "\\|" c-Java-expr-kwds)) +(defconst c-IDL-keywords + (concat c-IDL-primitive-type-kwds "\\|" c-IDL-specifier-kwds + "\\|" c-IDL-class-kwds "\\|" c-IDL-extra-toplevel-kwds + ;; "\\|" c-IDL-other-decl-kwds "\\|" c-IDL-decl-level-kwds + ;; "\\|" c-IDL-protection-kwds + ;; "\\|" c-IDL-block-stmt-1-kwds "\\|" c-IDL-block-stmt-2-kwds + ;; "\\|" c-IDL-simple-stmt-kwds "\\|" c-IDL-label-kwds + ;; "\\|" c-IDL-expr-kwds) + )) +(defconst c-Pike-keywords + (concat c-Pike-primitive-type-kwds "\\|" c-Pike-specifier-kwds + "\\|" c-Pike-class-kwds + ;; "\\|" c-Pike-extra-toplevel-kwds + "\\|" c-Pike-other-decl-kwds + ;; "\\|" c-Pike-decl-level-kwds "\\|" c-Pike-protection-kwds + "\\|" c-Pike-block-stmt-1-kwds "\\|" c-Pike-block-stmt-2-kwds + "\\|" c-Pike-simple-stmt-kwds "\\|" c-Pike-label-kwds + "\\|" c-Pike-expr-kwds)) + +(defvar c-keywords nil) +(make-variable-buffer-local 'c-keywords) + +;; Keywords defining protection levels +(defconst c-protection-key "\\<\\(public\\|protected\\|private\\)\\>") +;; Regexps introducing class definitions. +(defconst c-C-class-key (c-paren-re c-C-class-kwds)) +(defconst c-C++-class-key (c-paren-re c-C++-class-kwds)) +(defconst c-IDL-class-key (c-paren-re c-IDL-class-kwds)) (defconst c-ObjC-class-key (concat - "@\\(interface\\|implementation\\)\\s +" + "@\\(" c-ObjC-class-kwds "\\)\\s +" c-symbol-key ;name of the class "\\(\\s *:\\s *" c-symbol-key "\\)?" ;maybe followed by the superclass "\\(\\s *<[^>]+>\\)?" ;and maybe the adopted protocols list )) - (defconst c-Java-class-key (concat "\\(" c-protection-key "\\s +\\)?" - "\\(interface\\|class\\)\\s +" + "\\(" c-Java-class-kwds "\\)\\s +" c-symbol-key ;name of the class "\\(\\s *extends\\s *" c-symbol-key "\\)?" ;maybe followed by superclass ;;"\\(\\s *implements *[^{]+{\\)?" ;maybe the adopted protocols list )) - -(defconst c-Pike-class-key "class") +(defconst c-Pike-class-key (c-paren-re c-Pike-class-kwds)) (defvar c-class-key c-C-class-key) (make-variable-buffer-local 'c-class-key) +(defconst c-C-extra-toplevel-key (c-paren-re c-C-extra-toplevel-kwds)) +(defconst c-C++-extra-toplevel-key (c-paren-re c-C++-extra-toplevel-kwds)) +(defconst c-IDL-extra-toplevel-key (c-paren-re c-IDL-extra-toplevel-kwds)) + (defvar c-extra-toplevel-key c-C-extra-toplevel-key) (make-variable-buffer-local 'c-extra-toplevel-key) @@ -121,17 +286,16 @@ Otherwise, this variable is nil. I.e. this variable is non-nil for (defvar c-bitfield-key nil) (make-variable-buffer-local 'c-bitfield-key) - ;; regexp describing access protection clauses. language specific (defvar c-access-key nil) (make-variable-buffer-local 'c-access-key) -(defconst c-C++-access-key (concat c-protection-key "[ \t]*:")) -(defconst c-IDL-access-key nil) +(defconst c-C++-access-key + (concat "\\<\\(" c-C++-protection-kwds "\\)\\>[ \t]*:")) +;;(defconst c-IDL-access-key nil) (defconst c-ObjC-access-key (concat "@" c-protection-key)) -(defconst c-Java-access-key nil) -(defconst c-Pike-access-key nil) +;;(defconst c-Java-access-key nil) +;;(defconst c-Pike-access-key nil) - ;; keywords introducing conditional blocks (defconst c-C-conditional-key nil) (defconst c-C++-conditional-key nil) @@ -143,8 +307,8 @@ Otherwise, this variable is nil. I.e. this variable is non-nil for (let ((all-kws "for\\|if\\|do\\|else\\|while\\|switch") (exc-kws "\\|try\\|catch") (thr-kws "\\|finally\\|synchronized") - (front "\\b\\(") - (back "\\)\\b[^_]")) + (front "\\<\\(") + (back "\\)\\>[^_]")) (setq c-C-conditional-key (concat front all-kws back) c-C++-conditional-key (concat front all-kws exc-kws back) ;; c-IDL-conditional-key is nil. @@ -155,7 +319,6 @@ Otherwise, this variable is nil. I.e. this variable is non-nil for (defvar c-conditional-key c-C-conditional-key) (make-variable-buffer-local 'c-conditional-key) - ;; keywords describing method definition introductions (defvar c-method-key nil) (make-variable-buffer-local 'c-method-key) @@ -168,8 +331,6 @@ Otherwise, this variable is nil. I.e. this variable is non-nil for ;; since it is considered the end of //-comments. "[ \t\n]*" c-symbol-key)) - - ;; comment starter definitions for various languages. language specific (defconst c-C++-comment-start-regexp "/[/*]") (defconst c-C-comment-start-regexp c-C++-comment-start-regexp) @@ -182,8 +343,6 @@ Otherwise, this variable is nil. I.e. this variable is non-nil for (defvar c-comment-start-regexp c-C++-comment-start-regexp) (make-variable-buffer-local 'c-comment-start-regexp) - - ;; Regexp describing a switch's case or default label for all languages (defconst c-switch-label-key "\\(\\(case[( \t]+\\S .*\\)\\|default[ \t]*\\):") ;; Regexp describing any label. @@ -215,15 +374,18 @@ Otherwise, this variable is nil. I.e. this variable is non-nil for (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-*\\\\s-*\\(\\([_$a-zA-Z][_$.a-zA-Z0-9]*\\)[, \t\n\r\f]*\\)+\\)?\\s-*") -;; Regexp describing regexp to append to paragraph-start +;; Regexp to append to paragraph-start. (defvar c-append-paragraph-start "$") (make-variable-buffer-local 'c-append-paragraph-start) (defconst c-Java-javadoc-paragraph-start - (concat "\\(" - "@\\(author\\|deprecated\\|exception\\|param\\|return\\|" - "s\\(e\\(e\\|rial\\(\\|Data\\|Field\\)\\)\\|ince\\)\\|" - "throws\\|version\\)" - "\\|$\\)")) + "\\(@[a-zA-Z]+\\>\\|$\\)") +(defconst c-Pike-pikedoc-paragraph-start + "\\(@[a-zA-Z]+\\>\\([^{]\\|$\\)\\|$\\)") + +;; Regexp to append to paragraph-separate. +(defvar c-append-paragraph-separate "$") +(make-variable-buffer-local 'c-append-paragraph-separate) +(defconst c-Pike-pikedoc-paragraph-separate c-Pike-pikedoc-paragraph-start) ;; Regexp that starts lambda constructs. (defvar c-lambda-key nil) @@ -250,175 +412,8 @@ Otherwise, this variable is nil. I.e. this variable is non-nil for (?\[ . ?\]) (?< . ?>))) - - -;; internal state variables - -;; Internal state of hungry delete key feature -(defvar c-hungry-delete-key nil) -(make-variable-buffer-local 'c-hungry-delete-key) - -;; Internal state of auto newline feature. -(defvar c-auto-newline nil) -(make-variable-buffer-local 'c-auto-newline) - -;; Internal auto-newline/hungry-delete designation string for mode line. -(defvar c-auto-hungry-string nil) -(make-variable-buffer-local 'c-auto-hungry-string) - -;; Non-nil means K&R style argument declarations are valid. -(defvar c-recognize-knr-p t) -(make-variable-buffer-local 'c-recognize-knr-p) - - -(defun c-common-init () - ;; Common initializations for all modes. - ;; these variables should always be buffer local; they do not affect - ;; indentation style. - (make-local-variable 'require-final-newline) - (make-local-variable 'parse-sexp-ignore-comments) - (make-local-variable 'indent-line-function) - (make-local-variable 'indent-region-function) - (make-local-variable 'outline-regexp) - (make-local-variable 'outline-level) - (make-local-variable 'normal-auto-fill-function) - (make-local-variable 'comment-start) - (make-local-variable 'comment-end) - (make-local-variable 'comment-column) - (make-local-variable 'comment-start-skip) - (make-local-variable 'comment-multi-line) - (make-local-variable 'paragraph-start) - (make-local-variable 'paragraph-separate) - (make-local-variable 'paragraph-ignore-fill-prefix) - (make-local-variable 'adaptive-fill-mode) - (make-local-variable 'adaptive-fill-regexp) - (make-local-variable 'imenu-generic-expression) ;set in the mode functions - ;; X/Emacs 20 only - (and (boundp 'comment-line-break-function) - (progn - (make-local-variable 'comment-line-break-function) - (setq comment-line-break-function - 'c-indent-new-comment-line))) - ;; now set their values - (setq require-final-newline t - parse-sexp-ignore-comments t - indent-line-function 'c-indent-line - indent-region-function 'c-indent-region - outline-regexp "[^#\n\^M]" - outline-level 'c-outline-level - normal-auto-fill-function 'c-do-auto-fill - comment-column 32 - comment-start-skip "/\\*+ *\\|//+ *" - comment-multi-line t) - ;; now set the mode style based on c-default-style - (let ((style (if (stringp c-default-style) - (if (c-major-mode-is 'java-mode) - "java" - c-default-style) - (or (cdr (assq major-mode c-default-style)) - (cdr (assq 'other c-default-style)) - "gnu")))) - ;; Override style variables if `c-old-style-variable-behavior' is - ;; set. Also override if we are using global style variables, - ;; have already initialized a style once, and are switching to a - ;; different style. (It's doubtful whether this is desirable, but - ;; the whole situation with nonlocal style variables is a bit - ;; awkward. It's at least the most compatible way with the old - ;; style init procedure.) - (c-set-style style (not (or c-old-style-variable-behavior - (and (not c-style-variables-are-local-p) - c-indentation-style - (not (string-equal c-indentation-style - style))))))) - ;; Fix things up for paragraph recognition and filling inside - ;; comments by using c-comment-prefix-regexp in the relevant places. - ;; We use adaptive filling for this to make it possible to use - ;; filladapt or some other fancy package. - (let ((comment-line-prefix - (concat "[ \t]*\\(" c-comment-prefix-regexp "\\)?[ \t]*"))) - (setq paragraph-start (concat comment-line-prefix - c-append-paragraph-start - "\\|" - page-delimiter) - paragraph-separate (concat comment-line-prefix "$" - "\\|" - page-delimiter) - paragraph-ignore-fill-prefix t - adaptive-fill-mode t - adaptive-fill-regexp - (concat comment-line-prefix - (if adaptive-fill-regexp - (concat "\\(" adaptive-fill-regexp "\\)") - ""))) - (when (boundp 'adaptive-fill-first-line-regexp) - ;; XEmacs (20.x) adaptive fill mode doesn't have this. - (make-local-variable 'adaptive-fill-first-line-regexp) - (setq adaptive-fill-first-line-regexp - (concat "\\`" comment-line-prefix - ;; Maybe we should incorporate the old value here, - ;; but then we have to do all sorts of kludges to - ;; deal with the \` and \' it probably contains. - "\\'")))) - ;; we have to do something special for c-offsets-alist so that the - ;; buffer local value has its own alist structure. - (setq c-offsets-alist (copy-alist c-offsets-alist)) - ;; setup the comment indent variable in a Emacs version portable way - ;; ignore any byte compiler warnings you might get here - (make-local-variable 'comment-indent-function) - (setq comment-indent-function 'c-comment-indent) - ;; add menus to menubar - (easy-menu-add (c-mode-menu mode-name)) - ;; put auto-hungry designators onto minor-mode-alist, but only once - (or (assq 'c-auto-hungry-string minor-mode-alist) - (setq minor-mode-alist - (cons '(c-auto-hungry-string c-auto-hungry-string) - minor-mode-alist))) - ) - - -(defun c-postprocess-file-styles () - "Function that post processes relevant file local variables. -Currently, this function simply applies any style and offset settings -found in the file's Local Variable list. It first applies any style -setting found in `c-file-style', then it applies any offset settings -it finds in `c-file-offsets'. - -Note that the style variables are always made local to the buffer." - ;; apply file styles and offsets - (if (or c-file-style c-file-offsets) - (c-make-styles-buffer-local t)) - (and c-file-style - (c-set-style c-file-style)) - (and c-file-offsets - (mapcar - (function - (lambda (langentry) - (let ((langelem (car langentry)) - (offset (cdr langentry))) - (c-set-offset langelem offset) - ))) - c-file-offsets))) - -(add-hook 'hack-local-variables-hook 'c-postprocess-file-styles) - - -(defvar c-mode-base-map () - "Keymap shared by all CC Mode related modes.") - -;; Common routines -(defun c-make-inherited-keymap () - (let ((map (make-sparse-keymap))) - (cond - ;; XEmacs 19 & 20 - ((fboundp 'set-keymap-parents) - (set-keymap-parents map c-mode-base-map)) - ;; Emacs 19 - ((fboundp 'set-keymap-parent) - (set-keymap-parent map c-mode-base-map)) - ;; incompatible - (t (error "CC Mode is incompatible with this version of Emacs"))) - map)) +;; Syntax tables. (defun c-populate-syntax-table (table) ;; Populate the syntax TABLE @@ -453,132 +448,6 @@ Note that the style variables are always made local to the buffer." ;; Give CR the same syntax as newline, for selective-display (modify-syntax-entry ?\^m "> b" table)) - -(if c-mode-base-map - nil - ;; TBD: should we even worry about naming this keymap. My vote: no, - ;; because Emacs and XEmacs do it differently. - (setq c-mode-base-map (make-sparse-keymap)) - ;; put standard keybindings into MAP - ;; the following mappings correspond more or less directly to BOCM - (define-key c-mode-base-map "{" 'c-electric-brace) - (define-key c-mode-base-map "}" 'c-electric-brace) - (define-key c-mode-base-map ";" 'c-electric-semi&comma) - (define-key c-mode-base-map "#" 'c-electric-pound) - (define-key c-mode-base-map ":" 'c-electric-colon) - (define-key c-mode-base-map "(" 'c-electric-paren) - (define-key c-mode-base-map ")" 'c-electric-paren) - ;; Separate M-BS from C-M-h. The former should remain - ;; backward-kill-word. - (define-key c-mode-base-map [(control meta h)] 'c-mark-function) - (define-key c-mode-base-map "\e\C-q" 'c-indent-exp) - (substitute-key-definition 'backward-sentence - 'c-beginning-of-statement - c-mode-base-map global-map) - (substitute-key-definition 'forward-sentence - 'c-end-of-statement - c-mode-base-map global-map) - (substitute-key-definition 'indent-new-comment-line - 'c-indent-new-comment-line - c-mode-base-map global-map) - ;; RMS says don't make these the default. -;; (define-key c-mode-base-map "\e\C-a" 'c-beginning-of-defun) -;; (define-key c-mode-base-map "\e\C-e" 'c-end-of-defun) - (define-key c-mode-base-map "\C-c\C-n" 'c-forward-conditional) - (define-key c-mode-base-map "\C-c\C-p" 'c-backward-conditional) - (define-key c-mode-base-map "\C-c\C-u" 'c-up-conditional) - (substitute-key-definition 'indent-for-tab-command - 'c-indent-command - c-mode-base-map global-map) - ;; It doesn't suffice to put c-fill-paragraph on - ;; fill-paragraph-function due to the way it works. - (substitute-key-definition 'fill-paragraph 'c-fill-paragraph - c-mode-base-map global-map) - ;; In XEmacs the default fill function is called - ;; fill-paragraph-or-region. - (substitute-key-definition 'fill-paragraph-or-region 'c-fill-paragraph - c-mode-base-map global-map) - ;; Caution! Enter here at your own risk. We are trying to support - ;; several behaviors and it gets disgusting. :-( - ;; - (if (boundp 'delete-key-deletes-forward) - (progn - ;; In XEmacs 20 it is possible to sanely define both backward - ;; and forward deletion behavior under X separately (TTYs are - ;; forever beyond hope, but who cares? XEmacs 20 does the - ;; right thing with these too). - (define-key c-mode-base-map [delete] 'c-electric-delete) - (define-key c-mode-base-map [backspace] 'c-electric-backspace)) - ;; In XEmacs 19, Emacs 19, and Emacs 20, we use this to bind - ;; backwards deletion behavior to DEL, which both Delete and - ;; Backspace get translated to. There's no way to separate this - ;; behavior in a clean way, so deal with it! Besides, it's been - ;; this way since the dawn of BOCM. - (define-key c-mode-base-map "\177" 'c-electric-backspace)) - ;; these are new keybindings, with no counterpart to BOCM - (define-key c-mode-base-map "," 'c-electric-semi&comma) - (define-key c-mode-base-map "*" 'c-electric-star) - (define-key c-mode-base-map "/" 'c-electric-slash) - (define-key c-mode-base-map "\C-c\C-q" 'c-indent-defun) - (define-key c-mode-base-map "\C-c\C-\\" 'c-backslash-region) - ;; TBD: where if anywhere, to put c-backward|forward-into-nomenclature - (define-key c-mode-base-map "\C-c\C-a" 'c-toggle-auto-state) - (define-key c-mode-base-map "\C-c\C-b" 'c-submit-bug-report) - (define-key c-mode-base-map "\C-c\C-c" 'comment-region) - (define-key c-mode-base-map "\C-c\C-d" 'c-toggle-hungry-state) - (define-key c-mode-base-map "\C-c\C-o" 'c-set-offset) - (define-key c-mode-base-map "\C-c\C-s" 'c-show-syntactic-information) - (define-key c-mode-base-map "\C-c\C-t" 'c-toggle-auto-hungry-state) - (define-key c-mode-base-map "\C-c." 'c-set-style) - ;; conflicts with OOBR - ;;(define-key c-mode-base-map "\C-c\C-v" 'c-version) - ) - -(defvar c-c-menu nil) -(defvar c-c++-menu nil) -(defvar c-objc-menu nil) -(defvar c-java-menu nil) -(defvar c-pike-menu nil) - -(defun c-mode-menu (modestr) - (let ((m - '(["Comment Out Region" comment-region (c-region-is-active-p)] - ["Uncomment Region" - (comment-region (region-beginning) (region-end) '(4)) - (c-region-is-active-p)] - ["Fill Comment Paragraph" c-fill-paragraph t] - "---" - ["Indent Expression" c-indent-exp - (memq (char-after) '(?\( ?\[ ?\{))] - ["Indent Line or Region" c-indent-line-or-region t] - ["Up Conditional" c-up-conditional t] - ["Backward Conditional" c-backward-conditional t] - ["Forward Conditional" c-forward-conditional t] - ["Backward Statement" c-beginning-of-statement t] - ["Forward Statement" c-end-of-statement t] - "---" - ["Macro Expand Region" c-macro-expand (c-region-is-active-p)] - ["Backslashify" c-backslash-region (c-region-is-active-p)] - ))) - (cons modestr m))) - - - -;; Support for C - -(defvar c-mode-abbrev-table nil - "Abbreviation table used in c-mode buffers.") -(define-abbrev-table 'c-mode-abbrev-table ()) - -(defvar c-mode-map () - "Keymap used in c-mode buffers.") -(if c-mode-map - nil - (setq c-mode-map (c-make-inherited-keymap)) - ;; add bindings which are only useful for C - (define-key c-mode-map "\C-c\C-e" 'c-macro-expand) - ) - ;;;###autoload (defvar c-mode-syntax-table nil "Syntax table used in c-mode buffers.") @@ -587,27 +456,6 @@ Note that the style variables are always made local to the buffer." (setq c-mode-syntax-table (make-syntax-table)) (c-populate-syntax-table c-mode-syntax-table)) -(easy-menu-define c-c-menu c-mode-map "C Mode Commands" - (c-mode-menu "C")) - - -;; Support for C++ - -(defvar c++-mode-abbrev-table nil - "Abbreviation table used in c++-mode buffers.") -(define-abbrev-table 'c++-mode-abbrev-table ()) - -(defvar c++-mode-map () - "Keymap used in c++-mode buffers.") -(if c++-mode-map - nil - (setq c++-mode-map (c-make-inherited-keymap)) - ;; add bindings which are only useful for C++ - (define-key c++-mode-map "\C-c\C-e" 'c-macro-expand) - (define-key c++-mode-map "\C-c:" 'c-scope-operator) - (define-key c++-mode-map "<" 'c-electric-lt-gt) - (define-key c++-mode-map ">" 'c-electric-lt-gt)) - ;;;###autoload (defvar c++-mode-syntax-table nil "Syntax table used in c++-mode buffers.") @@ -635,24 +483,6 @@ are parsed.") (modify-syntax-entry ?< "(>" c++-template-syntax-table) (modify-syntax-entry ?> ")<" c++-template-syntax-table)) -(easy-menu-define c-c++-menu c++-mode-map "C++ Mode Commands" - (c-mode-menu "C++")) - - -;; Support for Objective-C - -(defvar objc-mode-abbrev-table nil - "Abbreviation table used in objc-mode buffers.") -(define-abbrev-table 'objc-mode-abbrev-table ()) - -(defvar objc-mode-map () - "Keymap used in objc-mode buffers.") -(if objc-mode-map - nil - (setq objc-mode-map (c-make-inherited-keymap)) - ;; add bindings which are only useful for Objective-C - (define-key objc-mode-map "\C-c\C-e" 'c-macro-expand)) - ;;;###autoload (defvar objc-mode-syntax-table nil "Syntax table used in objc-mode buffers.") @@ -663,24 +493,6 @@ are parsed.") ;; add extra Objective-C only syntax (modify-syntax-entry ?@ "_" objc-mode-syntax-table)) -(easy-menu-define c-objc-menu objc-mode-map "ObjC Mode Commands" - (c-mode-menu "ObjC")) - - -;; Support for Java - -(defvar java-mode-abbrev-table nil - "Abbreviation table used in java-mode buffers.") -(define-abbrev-table 'java-mode-abbrev-table ()) - -(defvar java-mode-map () - "Keymap used in java-mode buffers.") -(if java-mode-map - nil - (setq java-mode-map (c-make-inherited-keymap)) - ;; add bindings which are only useful for Java - ) - ;;;###autoload (defvar java-mode-syntax-table nil "Syntax table used in java-mode buffers.") @@ -689,24 +501,6 @@ are parsed.") (setq java-mode-syntax-table (make-syntax-table)) (c-populate-syntax-table java-mode-syntax-table)) -(easy-menu-define c-java-menu java-mode-map "Java Mode Commands" - (c-mode-menu "Java")) - - -;; Support for CORBA's IDL language - -(defvar idl-mode-abbrev-table nil - "Abbreviation table used in idl-mode buffers.") -(define-abbrev-table 'idl-mode-abbrev-table ()) - -(defvar idl-mode-map () - "Keymap used in idl-mode buffers.") -(if idl-mode-map - nil - (setq idl-mode-map (c-make-inherited-keymap)) - ;; add bindings which are only useful for IDL - ) - ;;;###autoload (defvar idl-mode-syntax-table nil "Syntax table used in idl-mode buffers.") @@ -715,24 +509,6 @@ are parsed.") (setq idl-mode-syntax-table (make-syntax-table)) (c-populate-syntax-table idl-mode-syntax-table)) -(easy-menu-define c-idl-menu idl-mode-map "IDL Mode Commands" - (c-mode-menu "IDL")) - - -;; Support for Pike - -(defvar pike-mode-abbrev-table nil - "Abbreviation table used in pike-mode buffers.") -(define-abbrev-table 'pike-mode-abbrev-table ()) - -(defvar pike-mode-map () - "Keymap used in pike-mode buffers.") -(if pike-mode-map - nil - (setq pike-mode-map (c-make-inherited-keymap)) - ;; additional bindings - (define-key pike-mode-map "\C-c\C-e" 'c-macro-expand)) - ;;;###autoload (defvar pike-mode-syntax-table nil "Syntax table used in pike-mode buffers.") @@ -742,10 +518,25 @@ are parsed.") (c-populate-syntax-table pike-mode-syntax-table) (modify-syntax-entry ?@ "." pike-mode-syntax-table)) -(easy-menu-define c-pike-menu pike-mode-map "Pike Mode Commands" - (c-mode-menu "Pike")) + +;; internal state variables + +;; Internal state of hungry delete key feature +(defvar c-hungry-delete-key nil) +(make-variable-buffer-local 'c-hungry-delete-key) + +;; Internal state of auto newline feature. +(defvar c-auto-newline nil) +(make-variable-buffer-local 'c-auto-newline) +;; Internal auto-newline/hungry-delete designation string for mode line. +(defvar c-auto-hungry-string nil) +(make-variable-buffer-local 'c-auto-hungry-string) + +;; Non-nil means K&R style argument declarations are valid. +(defvar c-recognize-knr-p t) +(make-variable-buffer-local 'c-recognize-knr-p) -(provide 'cc-langs) +(cc-provide 'cc-langs) ;;; cc-langs.el ends here diff --git a/lisp/progmodes/cc-menus.el b/lisp/progmodes/cc-menus.el index 3cd67c67bdb..5179f952530 100644 --- a/lisp/progmodes/cc-menus.el +++ b/lisp/progmodes/cc-menus.el @@ -1,6 +1,6 @@ ;;; cc-menus.el --- imenu support for CC Mode -;; Copyright (C) 1985,87,92,93,94,95,96,97,98,99,2000 Free Software Foundation, Inc. +;; Copyright (C) 1985,1987,1992-2001 Free Software Foundation, Inc. ;; Authors: 2000- Martin Stjernholm ;; 1998-1999 Barry A. Warsaw and Martin Stjernholm @@ -25,31 +25,27 @@ ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs; see the file COPYING. If not, write to the -;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; along with this program; see the file COPYING. If not, write to +;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, ;; Boston, MA 02111-1307, USA. (eval-when-compile (let ((load-path - (if (and (boundp 'byte-compile-current-file) - (stringp byte-compile-current-file)) - (cons (file-name-directory byte-compile-current-file) - load-path) + (if (and (boundp 'byte-compile-dest-file) + (stringp byte-compile-dest-file)) + (cons (file-name-directory byte-compile-dest-file) load-path) load-path))) - (load "cc-defs" nil t))) + (require 'cc-bytecomp))) -;; Dummy definitions to shut up the compiler in case imenu doesn't exist. -(eval-when-compile - (defvar imenu-generic-expression) - (defvar imenu-case-fold-search)) -(or (fboundp 'imenu-progress-message) - (defun imenu-progress-message (&rest args) nil)) +;; Try to pull in imenu if it exists. +(condition-case nil + (require 'imenu) + (error nil)) -;; Try to pull in imenu. -(eval-and-compile - (condition-case nil - (require 'imenu) - (error nil))) +;; The things referenced in imenu, which we don't require. +(cc-bytecomp-defvar imenu-case-fold-search) +(cc-bytecomp-defvar imenu-generic-expression) +(cc-bytecomp-defun imenu-progress-message) ;; imenu integration @@ -134,13 +130,13 @@ A sample value might look like: `\\(_P\\|_PROTO\\)'.") ,(concat "^" ; beginning of line is required "\\(template[ \t]*<[^>]+>[ \t]*\\)?" ; there may be a `template <...>' - "class[ \t]+" + "\\(class\\|struct\\)[ \t]+" "\\(" ; the string we want to get "[a-zA-Z0-9_]+" ; class name - "\\(<[^>]+>\\)?" ; possibly explicitely specialized + "\\(<[^>]+>\\)?" ; possibly explicitly specialized "\\)" "[ \t\n]*[:{]" - ) 2)) + ) 3)) "Imenu generic expression for C++ mode. See `imenu-generic-expression'.") (defvar cc-imenu-c-generic-expression @@ -414,5 +410,5 @@ Example: imenu-case-fold-search nil)) -(provide 'cc-menus) +(cc-provide 'cc-menus) ;;; cc-menus.el ends here diff --git a/lisp/progmodes/cc-mode.el b/lisp/progmodes/cc-mode.el index a3750bf082b..a7e35a9c185 100644 --- a/lisp/progmodes/cc-mode.el +++ b/lisp/progmodes/cc-mode.el @@ -1,6 +1,6 @@ ;;; cc-mode.el --- major mode for editing C, C++, Objective-C, and Java code -;; Copyright (C) 1985,87,92,93,94,95,96,97,98,99,2000 Free Software Foundation, Inc. +;; Copyright (C) 1985,1987,1992-2001 Free Software Foundation, Inc. ;; Authors: 2000- Martin Stjernholm ;; 1998-1999 Barry A. Warsaw and Martin Stjernholm @@ -11,12 +11,6 @@ ;; Created: a long, long, time ago. adapted from the original c-mode.el ;; Keywords: c languages oop -(defconst c-version "5.27" - "CC Mode version number.") - -;; NOTE: Read the commentary below for the right way to submit bug reports! -;; NOTE: See the accompanying texinfo manual for details on using this mode! - ;; This file is part of GNU Emacs. ;; GNU Emacs is free software; you can redistribute it and/or modify @@ -30,10 +24,16 @@ ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs; see the file COPYING. If not, write to the -;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; along with this program; see the file COPYING. If not, write to +;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, ;; Boston, MA 02111-1307, USA. +(defconst c-version "5.28" + "CC Mode version number.") + +;; NOTE: Read the commentary below for the right way to submit bug reports! +;; NOTE: See the accompanying texinfo manual for details on using this mode! + ;;; Commentary: ;; This package provides GNU Emacs major modes for editing C, C++, @@ -64,9 +64,8 @@ ;; gnu.emacs.bug) as well as bug-cc-mode@gnu.org, which directly ;; contacts the CC Mode maintainers. Questions can sent to ;; help-gnu-emacs@gnu.org (mirrored as gnu.emacs.help) and/or -;; bug-cc-mode@gnu.org. Please use bug-cc-mode@gnu.org instead. -;; Please do not send bugs or questions to our personal accounts; we -;; reserve the right to ignore such email! +;; bug-cc-mode@gnu.org. Please do not send bugs or questions to our +;; personal accounts; we reserve the right to ignore such email! ;; Many, many thanks go out to all the folks on the beta test list. ;; Without their patience, testing, insight, code contributions, and @@ -86,31 +85,29 @@ (eval-when-compile (let ((load-path - ;; Try to make sure the source directory is at the front of - ;; load-path when we load cc-defs. - (if (and (boundp 'byte-compile-current-file) - (stringp byte-compile-current-file)) - ;; byte-compile-current-file is set by the byte compiler - ;; to the full path to this file. - (cons (file-name-directory byte-compile-current-file) - load-path) + (if (and (boundp 'byte-compile-dest-file) + (stringp byte-compile-dest-file)) + (cons (file-name-directory byte-compile-dest-file) load-path) load-path))) - ;; Load our version of cc-defs unconditionally, since an older - ;; version might very well be dumped in or already loaded. This - ;; way we ensure that the code is compiled with the correct macros - ;; and defsubsts. The same problem affects the subpackages that's - ;; require'd below, but that doesn't harm the compiler; it can - ;; only cause some bogus warnings. - (load "cc-defs" nil t))) - -(require 'cc-defs) ; Not meaningless; this passes on require's from cc-defs. -(require 'cc-menus) -(require 'cc-vars) -(require 'cc-styles) -(require 'cc-langs) -(require 'cc-engine) -(require 'cc-align) -(require 'cc-cmds) + (require 'cc-bytecomp))) + +(cc-require 'cc-defs) +(cc-require 'cc-menus) +(cc-require 'cc-vars) +(cc-require 'cc-langs) +(cc-require 'cc-styles) +(cc-require 'cc-engine) +(cc-require 'cc-cmds) +(cc-require 'cc-align) + +;; Silence the compiler. +(cc-bytecomp-defvar comment-line-break-function) ; (X)Emacs 20+ +(cc-bytecomp-defvar adaptive-fill-first-line-regexp) ; Emacs 20+ +(cc-bytecomp-defun set-keymap-parents) ; XEmacs + +;; Menu support for both XEmacs and Emacs. If you don't have easymenu +;; with your version of Emacs, you are incompatible! +(require 'easymenu) ;; Other modes and packages which depend on CC Mode should do the @@ -140,6 +137,289 @@ )) +;; Common routines +(defvar c-mode-base-map () + "Keymap shared by all CC Mode related modes.") + +(defun c-make-inherited-keymap () + (let ((map (make-sparse-keymap))) + (cond + ;; XEmacs 19 & 20 + ((fboundp 'set-keymap-parents) + (set-keymap-parents map c-mode-base-map)) + ;; Emacs 19 + ((fboundp 'set-keymap-parent) + (set-keymap-parent map c-mode-base-map)) + ;; incompatible + (t (error "CC Mode is incompatible with this version of Emacs"))) + map)) + +(if c-mode-base-map + nil + ;; TBD: should we even worry about naming this keymap. My vote: no, + ;; because Emacs and XEmacs do it differently. + (setq c-mode-base-map (make-sparse-keymap)) + ;; put standard keybindings into MAP + ;; the following mappings correspond more or less directly to BOCM + (define-key c-mode-base-map "{" 'c-electric-brace) + (define-key c-mode-base-map "}" 'c-electric-brace) + (define-key c-mode-base-map ";" 'c-electric-semi&comma) + (define-key c-mode-base-map "#" 'c-electric-pound) + (define-key c-mode-base-map ":" 'c-electric-colon) + (define-key c-mode-base-map "(" 'c-electric-paren) + (define-key c-mode-base-map ")" 'c-electric-paren) + ;; Separate M-BS from C-M-h. The former should remain + ;; backward-kill-word. + (define-key c-mode-base-map [(control meta h)] 'c-mark-function) + (define-key c-mode-base-map "\e\C-q" 'c-indent-exp) + (substitute-key-definition 'backward-sentence + 'c-beginning-of-statement + c-mode-base-map global-map) + (substitute-key-definition 'forward-sentence + 'c-end-of-statement + c-mode-base-map global-map) + (substitute-key-definition 'indent-new-comment-line + 'c-indent-new-comment-line + c-mode-base-map global-map) + ;; RMS says don't make these the default. +;; (define-key c-mode-base-map "\e\C-a" 'c-beginning-of-defun) +;; (define-key c-mode-base-map "\e\C-e" 'c-end-of-defun) + (define-key c-mode-base-map "\C-c\C-n" 'c-forward-conditional) + (define-key c-mode-base-map "\C-c\C-p" 'c-backward-conditional) + (define-key c-mode-base-map "\C-c\C-u" 'c-up-conditional) + (substitute-key-definition 'indent-for-tab-command + 'c-indent-command + c-mode-base-map global-map) + ;; It doesn't suffice to put c-fill-paragraph on + ;; fill-paragraph-function due to the way it works. + (substitute-key-definition 'fill-paragraph 'c-fill-paragraph + c-mode-base-map global-map) + ;; In XEmacs the default fill function is called + ;; fill-paragraph-or-region. + (substitute-key-definition 'fill-paragraph-or-region 'c-fill-paragraph + c-mode-base-map global-map) + ;; Caution! Enter here at your own risk. We are trying to support + ;; several behaviors and it gets disgusting. :-( + ;; + (if (boundp 'delete-key-deletes-forward) + (progn + ;; In XEmacs 20 it is possible to sanely define both backward + ;; and forward deletion behavior under X separately (TTYs are + ;; forever beyond hope, but who cares? XEmacs 20 does the + ;; right thing with these too). + (define-key c-mode-base-map [delete] 'c-electric-delete) + (define-key c-mode-base-map [backspace] 'c-electric-backspace)) + ;; In XEmacs 19, Emacs 19, and Emacs 20, we use this to bind + ;; backwards deletion behavior to DEL, which both Delete and + ;; Backspace get translated to. There's no way to separate this + ;; behavior in a clean way, so deal with it! Besides, it's been + ;; this way since the dawn of BOCM. + (define-key c-mode-base-map "\177" 'c-electric-backspace)) + ;; these are new keybindings, with no counterpart to BOCM + (define-key c-mode-base-map "," 'c-electric-semi&comma) + (define-key c-mode-base-map "*" 'c-electric-star) + (define-key c-mode-base-map "/" 'c-electric-slash) + (define-key c-mode-base-map "\C-c\C-q" 'c-indent-defun) + (define-key c-mode-base-map "\C-c\C-\\" 'c-backslash-region) + ;; TBD: where if anywhere, to put c-backward|forward-into-nomenclature + (define-key c-mode-base-map "\C-c\C-a" 'c-toggle-auto-state) + (define-key c-mode-base-map "\C-c\C-b" 'c-submit-bug-report) + (define-key c-mode-base-map "\C-c\C-c" 'comment-region) + (define-key c-mode-base-map "\C-c\C-d" 'c-toggle-hungry-state) + (define-key c-mode-base-map "\C-c\C-o" 'c-set-offset) + (define-key c-mode-base-map "\C-c\C-s" 'c-show-syntactic-information) + (define-key c-mode-base-map "\C-c\C-t" 'c-toggle-auto-hungry-state) + (define-key c-mode-base-map "\C-c." 'c-set-style) + ;; conflicts with OOBR + ;;(define-key c-mode-base-map "\C-c\C-v" 'c-version) + ) + +(defvar c-c-menu nil) +(defvar c-c++-menu nil) +(defvar c-objc-menu nil) +(defvar c-java-menu nil) +(defvar c-pike-menu nil) + +(defun c-mode-menu (modestr) + (let ((m + '(["Comment Out Region" comment-region (c-fn-region-is-active-p)] + ["Uncomment Region" + (comment-region (region-beginning) (region-end) '(4)) + (c-fn-region-is-active-p)] + ["Fill Comment Paragraph" c-fill-paragraph t] + "---" + ["Indent Expression" c-indent-exp + (memq (char-after) '(?\( ?\[ ?\{))] + ["Indent Line or Region" c-indent-line-or-region t] + ["Up Conditional" c-up-conditional t] + ["Backward Conditional" c-backward-conditional t] + ["Forward Conditional" c-forward-conditional t] + ["Backward Statement" c-beginning-of-statement t] + ["Forward Statement" c-end-of-statement t] + "---" + ["Macro Expand Region" c-macro-expand (c-fn-region-is-active-p)] + ["Backslashify" c-backslash-region + (c-fn-region-is-active-p)] + ))) + (cons modestr m))) + +;; We don't require the outline package, but we configure it a bit anyway. +(cc-bytecomp-defvar outline-level) + +(defun c-common-init () + ;; Common initializations for all modes. + ;; these variables should always be buffer local; they do not affect + ;; indentation style. + (make-local-variable 'require-final-newline) + (make-local-variable 'parse-sexp-ignore-comments) + (make-local-variable 'indent-line-function) + (make-local-variable 'indent-region-function) + (make-local-variable 'outline-regexp) + (make-local-variable 'outline-level) + (make-local-variable 'normal-auto-fill-function) + (make-local-variable 'comment-start) + (make-local-variable 'comment-end) + (make-local-variable 'comment-column) + (make-local-variable 'comment-start-skip) + (make-local-variable 'comment-multi-line) + (make-local-variable 'paragraph-start) + (make-local-variable 'paragraph-separate) + (make-local-variable 'paragraph-ignore-fill-prefix) + (make-local-variable 'adaptive-fill-mode) + (make-local-variable 'adaptive-fill-regexp) + (make-local-variable 'imenu-generic-expression) ;set in the mode functions + ;; X/Emacs 20 only + (and (boundp 'comment-line-break-function) + (progn + (make-local-variable 'comment-line-break-function) + (setq comment-line-break-function + 'c-indent-new-comment-line))) + ;; now set their values + (setq require-final-newline t + parse-sexp-ignore-comments t + indent-line-function 'c-indent-line + indent-region-function 'c-indent-region + outline-regexp "[^#\n\^M]" + outline-level 'c-outline-level + normal-auto-fill-function 'c-do-auto-fill + comment-column 32 + comment-start-skip "/\\*+ *\\|//+ *" + comment-multi-line t) + ;; now set the mode style based on c-default-style + (let ((style (if (stringp c-default-style) + c-default-style + (or (cdr (assq major-mode c-default-style)) + (cdr (assq 'other c-default-style)) + "gnu")))) + ;; Override style variables if `c-old-style-variable-behavior' is + ;; set. Also override if we are using global style variables, + ;; have already initialized a style once, and are switching to a + ;; different style. (It's doubtful whether this is desirable, but + ;; the whole situation with nonlocal style variables is a bit + ;; awkward. It's at least the most compatible way with the old + ;; style init procedure.) + (c-set-style style (not (or c-old-style-variable-behavior + (and (not c-style-variables-are-local-p) + c-indentation-style + (not (string-equal c-indentation-style + style))))))) + ;; Fix things up for paragraph recognition and filling inside + ;; comments by using c-current-comment-prefix in the relevant + ;; places. We use adaptive filling for this to make it possible to + ;; use filladapt or some other fancy package. + (setq c-current-comment-prefix + (if (listp c-comment-prefix-regexp) + (cdr-safe (or (assoc major-mode c-comment-prefix-regexp) + (assoc 'other c-comment-prefix-regexp))) + c-comment-prefix-regexp)) + (let ((comment-line-prefix + (concat "[ \t]*\\(" c-current-comment-prefix "\\)[ \t]*"))) + (setq paragraph-start (concat comment-line-prefix + c-append-paragraph-start + "\\|" + page-delimiter) + paragraph-separate (concat comment-line-prefix + c-append-paragraph-separate + "\\|" + page-delimiter) + paragraph-ignore-fill-prefix t + adaptive-fill-mode t + adaptive-fill-regexp + (concat comment-line-prefix + (if adaptive-fill-regexp + (concat "\\(" adaptive-fill-regexp "\\)") + ""))) + (when (boundp 'adaptive-fill-first-line-regexp) + ;; XEmacs (20.x) adaptive fill mode doesn't have this. + (make-local-variable 'adaptive-fill-first-line-regexp) + (setq adaptive-fill-first-line-regexp + (concat "\\`" comment-line-prefix + ;; Maybe we should incorporate the old value here, + ;; but then we have to do all sorts of kludges to + ;; deal with the \` and \' it probably contains. + "\\'")))) + ;; we have to do something special for c-offsets-alist so that the + ;; buffer local value has its own alist structure. + (setq c-offsets-alist (copy-alist c-offsets-alist)) + ;; setup the comment indent variable in a Emacs version portable way + ;; ignore any byte compiler warnings you might get here + (make-local-variable 'comment-indent-function) + (setq comment-indent-function 'c-comment-indent) + ;; add menus to menubar + (easy-menu-add (c-mode-menu mode-name)) + ;; put auto-hungry designators onto minor-mode-alist, but only once + (or (assq 'c-auto-hungry-string minor-mode-alist) + (setq minor-mode-alist + (cons '(c-auto-hungry-string c-auto-hungry-string) + minor-mode-alist))) + ) + +(defun c-postprocess-file-styles () + "Function that post processes relevant file local variables. +Currently, this function simply applies any style and offset settings +found in the file's Local Variable list. It first applies any style +setting found in `c-file-style', then it applies any offset settings +it finds in `c-file-offsets'. + +Note that the style variables are always made local to the buffer." + ;; apply file styles and offsets + (if (or c-file-style c-file-offsets) + (c-make-styles-buffer-local t)) + (and c-file-style + (c-set-style c-file-style)) + (and c-file-offsets + (mapcar + (function + (lambda (langentry) + (let ((langelem (car langentry)) + (offset (cdr langentry))) + (c-set-offset langelem offset) + ))) + c-file-offsets))) + +(add-hook 'hack-local-variables-hook 'c-postprocess-file-styles) + + +;; Support for C + +(defvar c-mode-abbrev-table nil + "Abbreviation table used in c-mode buffers.") +(define-abbrev-table 'c-mode-abbrev-table + '(("else" "else" c-electric-continued-statement 0) + ("while" "while" c-electric-continued-statement 0))) + +(defvar c-mode-map () + "Keymap used in c-mode buffers.") +(if c-mode-map + nil + (setq c-mode-map (c-make-inherited-keymap)) + ;; add bindings which are only useful for C + (define-key c-mode-map "\C-c\C-e" 'c-macro-expand) + ) + +(easy-menu-define c-c-menu c-mode-map "C Mode Commands" + (c-mode-menu "C")) + ;;;###autoload (defun c-mode () "Major mode for editing K&R and ANSI C code. @@ -162,11 +442,13 @@ Key bindings: (set-syntax-table c-mode-syntax-table) (setq major-mode 'c-mode mode-name "C" - local-abbrev-table c-mode-abbrev-table) + local-abbrev-table c-mode-abbrev-table + abbrev-mode t) (use-local-map c-mode-map) (c-common-init) (setq comment-start "/* " comment-end " */" + c-keywords (c-identifier-re c-C-keywords) c-conditional-key c-C-conditional-key c-class-key c-C-class-key c-baseclass-key nil @@ -179,6 +461,29 @@ Key bindings: (c-update-modeline)) +;; Support for C++ + +(defvar c++-mode-abbrev-table nil + "Abbreviation table used in c++-mode buffers.") +(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))) + +(defvar c++-mode-map () + "Keymap used in c++-mode buffers.") +(if c++-mode-map + nil + (setq c++-mode-map (c-make-inherited-keymap)) + ;; add bindings which are only useful for C++ + (define-key c++-mode-map "\C-c\C-e" 'c-macro-expand) + (define-key c++-mode-map "\C-c:" 'c-scope-operator) + (define-key c++-mode-map "<" 'c-electric-lt-gt) + (define-key c++-mode-map ">" 'c-electric-lt-gt)) + +(easy-menu-define c-c++-menu c++-mode-map "C++ Mode Commands" + (c-mode-menu "C++")) + ;;;###autoload (defun c++-mode () "Major mode for editing C++ code. @@ -202,11 +507,13 @@ Key bindings: (set-syntax-table c++-mode-syntax-table) (setq major-mode 'c++-mode mode-name "C++" - local-abbrev-table c++-mode-abbrev-table) + local-abbrev-table c++-mode-abbrev-table + abbrev-mode t) (use-local-map c++-mode-map) (c-common-init) (setq comment-start "// " comment-end "" + c-keywords (c-identifier-re c-C++-keywords) c-conditional-key c-C++-conditional-key c-comment-start-regexp c-C++-comment-start-regexp c-class-key c-C++-class-key @@ -221,6 +528,25 @@ Key bindings: (c-update-modeline)) +;; Support for Objective-C + +(defvar objc-mode-abbrev-table nil + "Abbreviation table used in objc-mode buffers.") +(define-abbrev-table 'objc-mode-abbrev-table + '(("else" "else" c-electric-continued-statement 0) + ("while" "while" c-electric-continued-statement 0))) + +(defvar objc-mode-map () + "Keymap used in objc-mode buffers.") +(if objc-mode-map + nil + (setq objc-mode-map (c-make-inherited-keymap)) + ;; add bindings which are only useful for Objective-C + (define-key objc-mode-map "\C-c\C-e" 'c-macro-expand)) + +(easy-menu-define c-objc-menu objc-mode-map "ObjC Mode Commands" + (c-mode-menu "ObjC")) + ;;;###autoload (defun objc-mode () "Major mode for editing Objective C code. @@ -244,11 +570,13 @@ Key bindings: (set-syntax-table objc-mode-syntax-table) (setq major-mode 'objc-mode mode-name "ObjC" - local-abbrev-table objc-mode-abbrev-table) + local-abbrev-table objc-mode-abbrev-table + abbrev-mode t) (use-local-map objc-mode-map) (c-common-init) (setq comment-start "// " comment-end "" + c-keywords (c-identifier-re c-ObjC-keywords) c-conditional-key c-ObjC-conditional-key c-comment-start-regexp c-ObjC-comment-start-regexp c-class-key c-ObjC-class-key @@ -262,6 +590,27 @@ Key bindings: (c-update-modeline)) +;; Support for Java + +(defvar java-mode-abbrev-table nil + "Abbreviation table used in java-mode buffers.") +(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))) + +(defvar java-mode-map () + "Keymap used in java-mode buffers.") +(if java-mode-map + nil + (setq java-mode-map (c-make-inherited-keymap)) + ;; add bindings which are only useful for Java + ) + +(easy-menu-define c-java-menu java-mode-map "Java Mode Commands" + (c-mode-menu "Java")) + ;;;###autoload (defun java-mode () "Major mode for editing Java code. @@ -288,18 +637,19 @@ Key bindings: (setq major-mode 'java-mode mode-name "Java" local-abbrev-table java-mode-abbrev-table + abbrev-mode t c-append-paragraph-start c-Java-javadoc-paragraph-start) (use-local-map java-mode-map) (c-common-init) (setq comment-start "// " comment-end "" + c-keywords (c-identifier-re c-Java-keywords) c-conditional-key c-Java-conditional-key c-comment-start-regexp c-Java-comment-start-regexp c-class-key c-Java-class-key c-method-key nil c-baseclass-key nil c-recognize-knr-p nil - c-access-key c-Java-access-key c-inexpr-class-key c-Java-inexpr-class-key ;defun-prompt-regexp c-Java-defun-prompt-regexp ) @@ -309,6 +659,23 @@ Key bindings: (c-update-modeline)) +;; Support for CORBA's IDL language + +(defvar idl-mode-abbrev-table nil + "Abbreviation table used in idl-mode buffers.") +(define-abbrev-table 'idl-mode-abbrev-table ()) + +(defvar idl-mode-map () + "Keymap used in idl-mode buffers.") +(if idl-mode-map + nil + (setq idl-mode-map (c-make-inherited-keymap)) + ;; add bindings which are only useful for IDL + ) + +(easy-menu-define c-idl-menu idl-mode-map "IDL Mode Commands" + (c-mode-menu "IDL")) + ;;;###autoload (defun idl-mode () "Major mode for editing CORBA's IDL code. @@ -337,13 +704,13 @@ Key bindings: (c-common-init) (setq comment-start "// " comment-end "" + c-keywords (c-identifier-re c-IDL-keywords) c-conditional-key c-IDL-conditional-key c-comment-start-regexp c-IDL-comment-start-regexp c-class-key c-IDL-class-key c-method-key nil c-baseclass-key nil c-extra-toplevel-key c-IDL-extra-toplevel-key - c-access-key c-IDL-access-key c-recognize-knr-p nil ) ;;(cc-imenu-init cc-imenu-idl-generic-expression) ;FIXME @@ -352,6 +719,25 @@ Key bindings: (c-update-modeline)) +;; Support for Pike + +(defvar pike-mode-abbrev-table nil + "Abbreviation table used in pike-mode buffers.") +(define-abbrev-table 'pike-mode-abbrev-table + '(("else" "else" c-electric-continued-statement 0) + ("while" "while" c-electric-continued-statement 0))) + +(defvar pike-mode-map () + "Keymap used in pike-mode buffers.") +(if pike-mode-map + nil + (setq pike-mode-map (c-make-inherited-keymap)) + ;; additional bindings + (define-key pike-mode-map "\C-c\C-e" 'c-macro-expand)) + +(easy-menu-define c-pike-menu pike-mode-map "Pike Mode Commands" + (c-mode-menu "Pike")) + ;;;###autoload (defun pike-mode () "Major mode for editing Pike code. @@ -375,18 +761,21 @@ Key bindings: (set-syntax-table pike-mode-syntax-table) (setq major-mode 'pike-mode mode-name "Pike" - local-abbrev-table pike-mode-abbrev-table) + local-abbrev-table pike-mode-abbrev-table + abbrev-mode t + c-append-paragraph-start c-Pike-pikedoc-paragraph-start + c-append-paragraph-separate c-Pike-pikedoc-paragraph-separate) (use-local-map pike-mode-map) (c-common-init) (setq comment-start "// " comment-end "" + c-keywords (c-identifier-re c-Pike-keywords) c-conditional-key c-Pike-conditional-key c-comment-start-regexp c-Pike-comment-start-regexp c-class-key c-Pike-class-key c-method-key nil c-baseclass-key nil c-recognize-knr-p nil - c-access-key c-Pike-access-key c-lambda-key c-Pike-lambda-key c-inexpr-block-key c-Pike-inexpr-block-key c-inexpr-class-key c-Pike-inexpr-class-key @@ -398,6 +787,12 @@ Key bindings: (c-update-modeline)) +;; Helper for setting up Filladapt mode. It's not used by CC Mode itself. + +(cc-bytecomp-defvar filladapt-token-table) +(cc-bytecomp-defvar filladapt-token-match-table) +(cc-bytecomp-defvar filladapt-token-conversion-table) + (defun c-setup-filladapt () "Convenience function to configure Kyle E. Jones' Filladapt mode for CC Mode by making sure the proper entries are present on @@ -415,10 +810,10 @@ CC Mode by making sure the proper entries are present on (while (and p (not (eq (car-safe (cdr-safe (car-safe p))) 'c-comment))) (setq p (cdr-safe p))) (if p - (setcar (car p) c-comment-prefix-regexp) + (setcar (car p) c-current-comment-prefix) (setq filladapt-token-table (append (list (car filladapt-token-table) - (list c-comment-prefix-regexp 'c-comment)) + (list c-current-comment-prefix 'c-comment)) (cdr filladapt-token-table))))) (unless (assq 'c-comment filladapt-token-match-table) (setq filladapt-token-match-table @@ -442,16 +837,20 @@ CC Mode by making sure the proper entries are present on (message "Using CC Mode version %s" c-version) (c-keep-region-active)) +(defvar c-prepare-bug-report-hooks nil) + +;; Dynamic variables used by reporter. +(defvar reporter-prompt-for-summary-p) +(defvar reporter-dont-compact-list) + (defun c-submit-bug-report () "Submit via mail a bug report on CC Mode." (interactive) (require 'reporter) - (require 'cc-vars) ;; load in reporter (let ((reporter-prompt-for-summary-p t) (reporter-dont-compact-list '(c-offsets-alist)) (style c-indentation-style) - (hook c-special-indent-hook) (c-features c-emacs-features)) (and (if (y-or-n-p "Do you want to submit a report on CC Mode? ") @@ -500,12 +899,12 @@ CC Mode by making sure the proper entries are present on vars) (function (lambda () + (run-hooks 'c-prepare-bug-report-hooks) (insert "Buffer Style: " style "\n\n" (format "c-emacs-features: %s\n" c-features) - ))) - nil)))) + ))))))) -(provide 'cc-mode) +(cc-provide 'cc-mode) ;;; cc-mode.el ends here diff --git a/lisp/progmodes/cc-styles.el b/lisp/progmodes/cc-styles.el index 3ce24cfa3bd..68591f125c0 100644 --- a/lisp/progmodes/cc-styles.el +++ b/lisp/progmodes/cc-styles.el @@ -1,6 +1,6 @@ ;;; cc-styles.el --- support for styles in CC Mode -;; Copyright (C) 1985,87,92,93,94,95,96,97,98,99,2000 Free Software Foundation, Inc. +;; Copyright (C) 1985,1987,1992-2001 Free Software Foundation, Inc. ;; Authors: 2000- Martin Stjernholm ;; 1998-1999 Barry A. Warsaw and Martin Stjernholm @@ -25,20 +25,20 @@ ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs; see the file COPYING. If not, write to the -;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; along with this program; see the file COPYING. If not, write to +;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, ;; Boston, MA 02111-1307, USA. (eval-when-compile (let ((load-path - (if (and (boundp 'byte-compile-current-file) - (stringp byte-compile-current-file)) - (cons (file-name-directory byte-compile-current-file) - load-path) + (if (and (boundp 'byte-compile-dest-file) + (stringp byte-compile-dest-file)) + (cons (file-name-directory byte-compile-dest-file) load-path) load-path))) - (load "cc-defs" nil t))) -(require 'cc-vars) + (require 'cc-bytecomp))) +(cc-require 'cc-defs) +(cc-require 'cc-vars) ;; Warning: don't eval-defun this constant or you'll break style inheritance. @@ -339,61 +339,6 @@ STYLE using `c-set-style' if the optional SET-P flag is non-nil." (and set-p (c-set-style style))) - -(defun c-evaluate-offset (offset langelem symbol) - ;; offset can be a number, a function, a variable, a list, or one of - ;; the symbols + or - - (cond - ((eq offset '+) (setq offset c-basic-offset)) - ((eq offset '-) (setq offset (- c-basic-offset))) - ((eq offset '++) (setq offset (* 2 c-basic-offset))) - ((eq offset '--) (setq offset (* 2 (- c-basic-offset)))) - ((eq offset '*) (setq offset (/ c-basic-offset 2))) - ((eq offset '/) (setq offset (/ (- c-basic-offset) 2))) - ((functionp offset) (setq offset (funcall offset langelem))) - ((listp offset) - (setq offset - (let (done) - (while (and (not done) offset) - (setq done (c-evaluate-offset (car offset) langelem symbol) - offset (cdr offset))) - (if (not done) - (if c-strict-syntax-p - (error "No offset found for syntactic symbol %s" symbol) - 0) - done)))) - ((not (numberp offset)) (setq offset (symbol-value offset))) - ) - offset) - -(defun c-get-offset (langelem) - ;; Get offset from LANGELEM which is a cons cell of the form: - ;; (SYMBOL . RELPOS). The symbol is matched against - ;; c-offsets-alist and the offset found there is either returned, - ;; or added to the indentation at RELPOS. If RELPOS is nil, then - ;; the offset is simply returned. - (let* ((symbol (car langelem)) - (relpos (cdr langelem)) - (match (assq symbol c-offsets-alist)) - (offset (cdr-safe match))) - (if (not match) - (if c-strict-syntax-p - (error "No offset found for syntactic symbol %s" symbol) - (setq offset 0 - relpos 0)) - (setq offset (c-evaluate-offset offset langelem symbol))) - (+ (if (and relpos - (< relpos (c-point 'bol))) - (save-excursion - (goto-char relpos) - (current-column)) - 0) - (or (and (numberp offset) offset) - (and (symbolp offset) (symbol-value offset)) - 0)) - )) - - (defvar c-read-offset-history nil) @@ -405,7 +350,7 @@ STYLE using `c-set-style' if the optional SET-P flag is non-nil." 'c-stylevar-fallback))))) (symname (symbol-name langelem)) (defstr (format "(default %s): " oldoff)) - (errmsg (concat "Offset must be int, func, var, list, " + (errmsg (concat "Offset must be int, func, var, vector, list, " "or [+,-,++,--,*,/] " defstr)) (prompt (concat symname " offset " defstr)) @@ -425,11 +370,14 @@ STYLE using `c-set-style' if the optional SET-P flag is non-nil." ;; a symbol with a function binding ((fboundp (setq interned (intern input))) interned) - ;; a lambda function - ((c-safe (functionp (setq raw (read input)))) - raw) ;; a symbol with variable binding ((boundp interned) interned) + ;; a lambda function or a vector + ((progn + (c-safe (setq raw (read input))) + (or (functionp raw) + (vectorp raw))) + raw) ;; error, but don't signal one, keep trying ;; to read an input value (t (ding) @@ -466,7 +414,8 @@ and exists only for compatibility reasons." (list langelem offset current-prefix-arg))) ;; sanity check offset (unless (c-valid-offset offset) - (error "Offset must be int, func, var, list, or in [+,-,++,--,*,/]: %s" + (error (concat "Offset must be int, func, var, vector, list, " + "or in [+,-,++,--,*,/]: %s") offset)) (let ((entry (assq symbol c-offsets-alist))) (if entry @@ -485,7 +434,7 @@ and exists only for compatibility reasons." ;; style. Only do this once! (unless (get 'c-initialize-builtin-style 'is-run) (put 'c-initialize-builtin-style 'is-run t) - (c-initialize-cc-mode) + ;;(c-initialize-cc-mode) (or (assoc "cc-mode" c-style-alist) (assoc "user" c-style-alist) (progn @@ -550,5 +499,5 @@ instead of `make-variable-buffer-local'." -(provide 'cc-styles) +(cc-provide 'cc-styles) ;;; cc-styles.el ends here diff --git a/lisp/progmodes/cc-vars.el b/lisp/progmodes/cc-vars.el index e7f84f49110..ec4a729b7b3 100644 --- a/lisp/progmodes/cc-vars.el +++ b/lisp/progmodes/cc-vars.el @@ -1,6 +1,6 @@ ;;; cc-vars.el --- user customization variables for CC Mode -;; Copyright (C) 1985,87,92,93,94,95,96,97,98,99,2000 Free Software Foundation, Inc. +;; Copyright (C) 1985,1987,1992-2001 Free Software Foundation, Inc. ;; Authors: 2000- Martin Stjernholm ;; 1998-1999 Barry A. Warsaw and Martin Stjernholm @@ -25,20 +25,44 @@ ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs; see the file COPYING. If not, write to the -;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; along with this program; see the file COPYING. If not, write to +;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, ;; Boston, MA 02111-1307, USA. (eval-when-compile (let ((load-path - (if (and (boundp 'byte-compile-current-file) - (stringp byte-compile-current-file)) - (cons (file-name-directory byte-compile-current-file) - load-path) + (if (and (boundp 'byte-compile-dest-file) + (stringp byte-compile-dest-file)) + (cons (file-name-directory byte-compile-dest-file) load-path) load-path))) - (load "cc-defs" nil t))) -(require 'custom) - + (require 'cc-bytecomp))) + +(cc-require 'cc-defs) + +;; Silence the compiler. +(cc-bytecomp-defun get-char-table) ; XEmacs 20+ +(cc-bytecomp-defun char-table-range) ; Emacs 19+ +(cc-bytecomp-defun char-table-p) ; Emacs 19+, XEmacs 20+ + +;; Pull in custom if it exists and is recent enough (the one in Emacs +;; 19.34 isn't). +(eval + (cc-eval-when-compile + (condition-case nil + (progn + (require 'custom) + (or (fboundp 'defcustom) (error "")) + (require 'wid-edit) + '(progn ; Compile in the require's. + (require 'custom) + (require 'wid-edit))) + (error + (message "Warning: Compiling without Customize support \ +since a (good enough) custom library wasn't found") + (cc-bytecomp-defmacro define-widget (name class doc &rest args)) + (cc-bytecomp-defmacro defcustom (symbol value doc &rest args) + `(defvar ,symbol ,value ,doc)) + nil)))) ;;; Helpers @@ -84,11 +108,8 @@ Useful as last item in a `choice' widget." (defmacro defcustom-c-stylevar (name val doc &rest args) "Defines a style variable." - (setq val (if (eq (car-safe val) 'quote) - (nth 1 val) - (eval val))) `(progn - (put ',name 'c-stylevar-fallback ',val) + (put ',name 'c-stylevar-fallback ,val) (defcustom ,name 'set-from-style ,(concat doc " @@ -124,6 +145,7 @@ See `c-offsets-alist'." (eq offset '*) (eq offset '/) (integerp offset) + (vectorp offset) (functionp offset) (and (symbolp offset) (or (boundp offset) @@ -195,7 +217,7 @@ should be inserted. Value must be a function taking no arguments." :group 'c) (defcustom c-syntactic-indentation t - "*Whether the identation should be controlled by the syntactic context. + "*Whether the indentation should be controlled by the syntactic context. If t, the indentation functions indents according to the syntactic context, using the style settings specified by `c-offsets-alist'. @@ -240,6 +262,15 @@ comment-only lines." :type 'boolean :group 'c) +(make-obsolete-variable 'c-comment-continuation-stars + 'c-block-comment-prefix) + +;; Although c-comment-continuation-stars is obsolete, we look at it in +;; some places in CC Mode anyway, so make the compiler ignore it +;; during our compilation. +(cc-bytecomp-obsolete-var c-comment-continuation-stars) +(cc-bytecomp-defvar c-comment-continuation-stars) + (defcustom-c-stylevar c-block-comment-prefix (if (boundp 'c-comment-continuation-stars) c-comment-continuation-stars @@ -259,25 +290,50 @@ style comments." :type 'string :group 'c) -(make-obsolete-variable 'c-comment-continuation-stars - 'c-block-comment-prefix) - -(defcustom-c-stylevar c-comment-prefix-regexp "//+\\|\\**" +(defcustom-c-stylevar c-comment-prefix-regexp + '((pike-mode . "//+!?\\|\\**") + (other . "//+\\|\\**")) "*Regexp to match the line prefix inside comments. This regexp is used to recognize the fill prefix inside comments for correct paragraph filling and other things. -It should match the prefix used in both C++ style line comments and C -style block comments, but it does not need to match a block comment -starter. In other words, it should at least match \"//\" for line -comments and the string in `c-block-comment-prefix', which is -sometimes inserted by CC Mode inside block comments. It should not -match any surrounding whitespace. +If this variable is a string, it will be used in all CC Mode major +modes. It can also be an association list, to associate specific +regexps to specific major modes. The symbol for the major mode is +looked up in the association list, and its value is used as the line +prefix regexp. If it's not found, then the symbol `other' is looked +up and its value is used instead. + +The regexp should match the prefix used in both C++ style line +comments and C style block comments, but it does not need to match a +block comment starter. In other words, it should at least match +\"//\" for line comments and the string in `c-block-comment-prefix', +which is sometimes inserted by CC Mode inside block comments. It +should not match any surrounding whitespace. Note that CC Mode modifies other variables from this one at mode -initialization, so you might need to do \\[c-mode] (or whatever mode +initialization, so you will need to do \\[c-mode] (or whatever mode you're currently using) if you change it in a CC Mode buffer." - :type 'regexp + :type '(radio + (regexp :tag "Regexp for all modes") + (list + :tag "Mode-specific regexps" + (set + :inline t :format "%v" + (cons :format "%v" + (const :format "C " c-mode) (regexp :format "%v")) + (cons :format "%v" + (const :format "C++ " c++-mode) (regexp :format "%v")) + (cons :format "%v" + (const :format "ObjC " objc-mode) (regexp :format "%v")) + (cons :format "%v" + (const :format "Java " java-mode) (regexp :format "%v")) + (cons :format "%v" + (const :format "IDL " idl-mode) (regexp :format "%v")) + (cons :format "%v" + (const :format "Pike " pike-mode) (regexp :format "%v"))) + (cons :format " %v" + (const :format "Other " other) (regexp :format "%v")))) :group 'c) (defcustom c-ignore-auto-fill '(string cpp code) @@ -303,47 +359,74 @@ contexts are: (defcustom-c-stylevar c-cleanup-list '(scope-operator) "*List of various C/C++/ObjC constructs to \"clean up\". -These clean ups only take place when the auto-newline feature is -turned on, as evidenced by the `/a' or `/ah' appearing next to the -mode name. Valid symbols are: +The following clean ups only take place when the auto-newline feature +is turned on, as evidenced by the `/a' or `/ah' appearing next to the +mode name: - brace-else-brace -- cleans up `} else {' constructs by placing entire - construct on a single line. This clean up - only takes place when there is nothing but + brace-else-brace -- Clean up \"} else {\" constructs by placing + entire construct on a single line. This clean + up only takes place when there is nothing but white space between the braces and the `else'. Clean up occurs when the open brace after the `else' is typed. - brace-elseif-brace -- similar to brace-else-brace, but cleans up - `} else if (...) {' constructs. Clean up occurs - after the open parenthesis and the open brace. - brace-catch-brace -- similar to brace-elseif-brace, but cleans up - `} catch (...) {' constructs. - empty-defun-braces -- cleans up empty defun braces by placing the + brace-elseif-brace -- Similar to brace-else-brace, but clean up + \"} else if (...) {\" constructs. Clean up + occurs after the open parenthesis and the open + brace. + brace-catch-brace -- Similar to brace-elseif-brace, but clean up + \"} catch (...) {\" constructs. + empty-defun-braces -- Clean up empty defun braces by placing the braces on the same line. Clean up occurs when the defun closing brace is typed. - defun-close-semi -- cleans up the terminating semi-colon on defuns + defun-close-semi -- Clean up the terminating semi-colon on defuns by placing the semi-colon on the same line as the closing brace. Clean up occurs when the semi-colon is typed. - list-close-comma -- cleans up commas following braces in array + list-close-comma -- Clean up commas following braces in array and aggregate initializers. Clean up occurs when the comma is typed. - scope-operator -- cleans up double colons which may designate + scope-operator -- Clean up double colons which may designate a C++ scope operator split across multiple - lines. Note that certain C++ constructs can + lines. Note that certain C++ constructs can generate ambiguous situations. This clean up only takes place when there is nothing but - whitespace between colons. Clean up occurs - when the second colon is typed." + whitespace between colons. Clean up occurs + when the second colon is typed. + +The following clean ups always take place when they are on this list, +regardless of the auto-newline feature, since they typically don't +involve auto-newline inserted newlines: + + space-before-funcall -- Insert exactly one space before the opening + parenthesis of a function call. Clean up + occurs when the opening parenthesis is typed. + compact-empty-funcall -- Clean up any space before the function call + opening parenthesis if and only if the + argument list is empty. This is typically + useful together with `space-before-funcall' to + get the style \"foo (bar)\" and \"foo()\". + Clean up occurs when the closing parenthesis + is typed." :type '(set :extra-offset 8 - (const :tag "Put `} else {' on one line" brace-else-brace) - (const :tag "Put `} else if (...) {' on one line" brace-elseif-brace) - (const :tag "Put `} catch (...) {' on one line" brace-catch-brace) - (const :tag "Put empty defun braces on one line" empty-defun-braces) - (const :tag "Put `};' ending defuns on one line" defun-close-semi) - (const :tag "Put `},' in aggregates on one line" list-close-comma) - (const :tag "Put C++ style `::' on one line" scope-operator)) + (const :tag "Put \"} else {\" on one line" + brace-else-brace) + (const :tag "Put \"} else if (...) {\" on one line" + brace-elseif-brace) + (const :tag "Put \"} catch (...) {\" on one line" + brace-catch-brace) + (const :tag "Put empty defun braces on one line" + empty-defun-braces) + (const :tag "Put \"};\" ending defuns on one line" + defun-close-semi) + (const :tag "Put \"},\" in aggregates on one line" + list-close-comma) + (const :tag "Put C++ style \"::\" on one line" + scope-operator) + (const :tag "Put a space before funcall parens, e.g. \"foo (bar)\"" + space-before-funcall) + (const :tag "Remove space before empty funcalls, e.g. \"foo()\"" + compact-empty-funcall)) :group 'c) (defcustom-c-stylevar c-hanging-braces-alist '((brace-list-open) @@ -500,7 +583,7 @@ this variable to nil." :type 'integer :group 'c) -(defcustom c-default-style "gnu" +(defcustom c-default-style '((java-mode . "java") (other . "gnu")) "*Style which gets installed by default when a file is visited. The value of this variable can be any style defined in @@ -508,8 +591,7 @@ The value of this variable can be any style defined in association list of major mode symbols to style names. When the value is a string, all CC Mode major modes will install this -style by default, except `java-mode', which always installs the -\"java\" style (this is for backwards compatibility). +style by default. When the value is an alist, the major mode symbol is looked up in it and the associated style is installed. If the major mode is not @@ -519,22 +601,24 @@ the alist, then \"gnu\" style is used. The default style gets installed before your mode hooks run, so you can always override the use of `c-default-style' by making calls to -`c-set-style' in the appropriate mode hook. - -Tip: If you use different styles in different languages, you probably -want to set `c-style-variables-are-local-p'." +`c-set-style' in the appropriate mode hook." :type '(radio - (string :tag "Style in all modes (except Java)") - (repeat :tag "Mode-specific styles" - :value ((other . "gnu")) - (cons :format "%v" - (choice :tag "Mode" - (const c-mode) (const c++-mode) - (const objc-mode) (const java-mode) - (const idl-mode) (const pike-mode) - (const other)) - (string :tag "Style") - ))) + (string :tag "Style in all modes") + (set :tag "Mode-specific styles" + (cons :format "%v" + (const :format "C " c-mode) (string :format "%v")) + (cons :format "%v" + (const :format "C++ " c++-mode) (string :format "%v")) + (cons :format "%v" + (const :format "ObjC " objc-mode) (string :format "%v")) + (cons :format "%v" + (const :format "Java " java-mode) (string :format "%v")) + (cons :format "%v" + (const :format "IDL " idl-mode) (string :format "%v")) + (cons :format "%v" + (const :format "Pike " pike-mode) (string :format "%v")) + (cons :format "%v" + (const :format "Other " other) (string :format "%v")))) :group 'c) (put 'c-offsets-alist 'c-stylevar-fallback @@ -660,13 +744,13 @@ want to set `c-style-variables-are-local-p'." (inclass . +) ;; Relpos: At the class open brace if it's at boi, otherwise ;; boi at the class decl start. - (cpp-macro . -1000) + (cpp-macro . [0]) ;; Relpos: None. (cpp-macro-cont . c-lineup-dont-change) ;; Relpos: At the macro start (always at boi). (friend . 0) ;; Relpos: None. - (objc-method-intro . -1000) + (objc-method-intro . [0]) ;; Relpos: Boi. (objc-method-args-cont . c-lineup-ObjC-method-args) ;; Relpos: At the method start (always at boi). @@ -722,23 +806,33 @@ The sum of this calculation for each element in the syntactic list is the absolute offset for line being indented. If the syntactic element does not match any in the `c-offsets-alist', -an error is generated if `c-strict-syntax-p' is non-nil, otherwise the -element is ignored. - -Actually, OFFSET can be an integer, a function, a variable, or one of -the following symbols: `+', `-', `++', `--', `*', or `/'. These -latter designate positive or negative multiples of `c-basic-offset', -respectively: 1, -1, 2, -2, 0.5, and -0.5. If OFFSET is a function, -it is called with a single argument containing the cons of the -syntactic element symbol and the relative indent point. The function -should return an integer offset or nil if it can't decide. - -OFFSET can also be a list, in which case it is recursively evaluated -using the semantics described above. The first element of the list to -return a non-nil value succeeds. If none of the elements returns a -non-nil value, then what happends depends on the value of -`c-strict-syntax-p'. When `c-strict-syntax-p' is nil, then an offset -of zero is used, otherwise an error is generated. +the element is ignored. + +If OFFSET is nil, the syntactic element is ignored in the offset +calculation. + +If OFFSET is an integer, it's added to the relative indent. + +If OFFSET is one of the symbols `+', `-', `++', `--', `*', or `/', a +positive or negative multiple of `c-basic-offset' is added; 1, -1, 2, +-2, 0.5, and -0.5, respectively. + +If OFFSET is a vector, it's first element, which must be an integer, +is used as an absolute indentation column. This overrides all +relative offsets. If there are several syntactic elements which +evaluates to absolute indentation columns, the first one takes +precedence. You can see in which order CC Mode combines the syntactic +elements in a certain context by using \\[c-show-syntactic-information] on the line. + +If OFFSET is a function, it's called with a single argument +containing the cons of the syntactic element symbol and the relative +indent point. The return value from the function is then +reinterpreted as an OFFSET value. + +If OFFSET is a list, it's recursively evaluated using the semantics +described above. The first element of the list to return a non-nil +value succeeds. If none of the elements returns a non-nil value, the +syntactic element is ignored. `c-offsets-alist' is a style variable. This means that the offsets on this variable are normally taken from the style system in CC Mode @@ -962,11 +1056,18 @@ as designated in the variable `c-file-style'.") (make-variable-buffer-local 'c-file-offsets) (defvar c-syntactic-context nil - "Variable containing syntactic analysis list during indentation.") + "Variable containing syntactic analysis list during indentation. +This is always bound dynamically. It should never be set statically +(e.g. with `setq').") (defvar c-indentation-style nil - "Name of the currently installed style.") + "Name of the currently installed style. +Don't change this directly; call `c-set-style' instead.") +(defvar c-current-comment-prefix nil + "The current comment prefix regexp. +Set from `c-comment-prefix-regexp' at mode initialization.") +(make-variable-buffer-local 'c-current-comment-prefix) ;; Figure out what features this Emacs has @@ -1011,7 +1112,6 @@ supported list, along with the values for this variable: Infodock (based on XEmacs) has an additional symbol on this list: `infodock'.") - -(provide 'cc-vars) +(cc-provide 'cc-vars) ;;; cc-vars.el ends here