* POC: customizable cc-mode keywords @ 2014-05-02 5:26 Daniel Colascione 2014-05-10 23:13 ` Daniel Colascione 2014-05-11 21:13 ` Alan Mackenzie 0 siblings, 2 replies; 41+ messages in thread From: Daniel Colascione @ 2014-05-02 5:26 UTC (permalink / raw) To: Emacs developers [-- Attachment #1: Type: text/plain, Size: 18192 bytes --] cc-mode has trouble with parsing dialects of C that use the preprocessor heavily. Consider this example from the Linux kernel: static int perf_event_period(struct perf_event *event, u64 __user *arg) __user is defined to some GCC static analysis nonsense, but since cc-mode doesn't know that, we see __user fontified in font-lock-variable-name-face and *arg untouched. This example is fairly benign (if ugly), but there are other cases where variations in pre-processor C dialect confuse cc-mode in larger regions, leading to odd fontification and indentation. The patch below adds customizable options for additional C-family language "keywords". To add this feature, we have to change how cc-mode evaluates its language variables. Today, we use clever macros to hard-code the values of all cc-mode language variables into the mode functions of each cc-mode major mode function or into c-init-language-vars-for, but in order to allow users to customize cc-mode syntax, we have to be able to recompute language constants and variables at runtime. The new code simply evaluates cc-mode language setter forms at mode initialization instead. This approach is slower, but not by much: it takes 0.9ms to set up cc-mode's ~130 language variables using the precompiled function approach, while it takes 1.6ms to do the same work using dynamic evaluation. I can live with this performance regression. As implemented, the keyword list can only be customized globally, but it'd be nice to be able to do something buffer-local too. === modified file 'lisp/progmodes/cc-defs.el' --- lisp/progmodes/cc-defs.el 2014-02-09 12:34:25 +0000 +++ lisp/progmodes/cc-defs.el 2014-05-02 04:47:35 +0000 @@ -89,7 +89,7 @@ \f ;;; Variables also used at compile time. -(defconst c-version "5.32.5" +(defconst c-version "5.32.5.1" "CC Mode version number.") (defconst c-version-sym (intern c-version)) @@ -1812,8 +1812,6 @@ ;; and other miscellaneous data. The obarray might also contain ;; various other symbols, but those don't have any variable bindings. -(defvar c-lang-const-expansion nil) - (defsubst c-get-current-file () ;; Return the base name of the current file. (let ((file (cond @@ -1880,19 +1878,6 @@ constant. A file is identified by its base name." (let* ((sym (intern (symbol-name name) c-lang-constants)) - ;; Make `c-lang-const' expand to a straightforward call to - ;; `c-get-lang-constant' in `cl-macroexpand-all' below. - ;; - ;; (The default behavior, i.e. to expand to a call inside - ;; `eval-when-compile' should be equivalent, since that macro - ;; should only expand to its content if it's used inside a - ;; form that's already evaluated at compile time. It's - ;; however necessary to use our cover macro - ;; `cc-eval-when-compile' due to bugs in `eval-when-compile', - ;; and it expands to a bulkier form that in this case only is - ;; unnecessary garbage that we don't want to store in the - ;; language constant source definitions.) - (c-lang-const-expansion 'call) (c-langs-are-parametric t) bindings pre-files) @@ -2037,53 +2022,28 @@ "Unknown language %S since it got no `c-mode-prefix' property" (symbol-name lang)))) - (if (eq c-lang-const-expansion 'immediate) - ;; No need to find out the source file(s) when we evaluate - ;; immediately since all the info is already there in the - ;; `source' property. - `',(c-get-lang-constant name nil mode) - - (let ((file (c-get-current-file))) - (if file (setq file (intern file))) - ;; Get the source file(s) that must be loaded to get the value - ;; of the constant. If the symbol isn't defined yet we assume - ;; that its definition will come later in this file, and thus - ;; are no file dependencies needed. - (setq source-files (nreverse - ;; Reverse to get the right load order. - (apply 'nconc - (mapcar (lambda (elem) - (if (eq file (car elem)) - nil ; Exclude our own file. - (list (car elem)))) - (get sym 'source)))))) - - ;; Make some effort to do a compact call to - ;; `c-get-lang-constant' since it will be compiled in. - (setq args (and mode `(',mode))) - (if (or source-files args) - (setq args (cons (and source-files `',source-files) - args))) - - (if (or (eq c-lang-const-expansion 'call) - (and (not c-lang-const-expansion) - (not mode)) - load-in-progress - (not (boundp 'byte-compile-dest-file)) - (not (stringp byte-compile-dest-file))) - ;; Either a straight call is requested in the context, or - ;; we're in an "uncontrolled" context and got no language, - ;; or we're not being byte compiled so the compile time - ;; stuff below is unnecessary. - `(c-get-lang-constant ',name ,@args) - - ;; Being compiled. If the loading and compiling version is - ;; the same we use a value that is evaluated at compile time, - ;; otherwise it's evaluated at runtime. - `(if (eq c-version-sym ',c-version-sym) - (cc-eval-when-compile - (c-get-lang-constant ',name ,@args)) - (c-get-lang-constant ',name ,@args)))))) + (let ((file (c-get-current-file))) + (if file (setq file (intern file))) + ;; Get the source file(s) that must be loaded to get the value + ;; of the constant. If the symbol isn't defined yet we assume + ;; that its definition will come later in this file, and thus + ;; are no file dependencies needed. + (setq source-files (nreverse + ;; Reverse to get the right load order. + (apply 'nconc + (mapcar (lambda (elem) + (if (eq file (car elem)) + nil ; Exclude our own file. + (list (car elem)))) + (get sym 'source)))))) + + ;; Make some effort to do a compact call to `c-get-lang-constant' + ;; and omit unneeded arguments since this code will be compiled. + (setq args (and mode `(',mode))) + (if (or source-files args) + (setq args (cons (and source-files `',source-files) + args))) + `(c-get-lang-constant ',name ,@args))) (defvar c-lang-constants-under-evaluation nil) @@ -2262,6 +2222,18 @@ (setq buf-mode (get buf-mode 'c-fallback-mode)))) match)) +(defun c-clear-value-cache () + "Forget already-computed `c-lang-defvar' values. +Call this function to make changes to cc-mode language +variables take effect at the next mode initialization." + ;; Clear cached constant values + (mapatoms (lambda (sym) + (set sym nil)) + c-lang-constants) + ;; Recompute our font lock keyword constants + (when (featurep 'cc-fonts) + (load "cc-fonts" nil t))) + \f (cc-provide 'cc-defs) === modified file 'lisp/progmodes/cc-langs.el' --- lisp/progmodes/cc-langs.el 2014-01-01 07:43:34 +0000 +++ lisp/progmodes/cc-langs.el 2014-05-02 05:19:24 +0000 @@ -1921,15 +1921,13 @@ ;; declaration. Specifically, they aren't recognized in the middle ;; of multi-token types, inside declarators, and between the ;; identifier and the arglist paren of a function declaration. - ;; - ;; FIXME: This ought to be user customizable since compiler stuff - ;; like this usually is wrapped in project specific macros. (It'd - ;; of course be even better if we could cope without knowing this.) - t nil - (c c++) '(;; GCC extension. - "__attribute__" - ;; MSVC extension. - "__declspec")) + t (when (boundp (c-mode-symbol "extra-keywords")) + (mapcar #'car (c-mode-var "extra-keywords"))) + (c c++) (append (c-lang-const c-decl-hangon-kwds) + '( ;; GCC extension. + "__attribute__" + ;; MSVC extension. + "__declspec"))) (c-lang-defconst c-decl-hangon-key ;; Adorned regexp matching `c-decl-hangon-kwds'. @@ -2120,11 +2118,18 @@ (c-lang-defconst c-paren-nontype-kwds "Keywords that may be followed by a parenthesis expression that doesn't contain type identifiers." - t nil - (c c++) '(;; GCC extension. - "__attribute__" - ;; MSVC extension. - "__declspec")) + t (when (boundp (c-mode-symbol "extra-keywords")) + (apply 'nconc + (mapcar (lambda (kw) + (when (cdr kw) + (list (car kw)))) + (c-mode-var "extra-keywords")))) + (c c++) (append + (c-lang-const c-paren-nontype-kwds) + '( ;; GCC extension. + "__attribute__" + ;; MSVC extension. + "__declspec"))) (c-lang-defconst c-paren-type-kwds "Keywords that may be followed by a parenthesis expression containing @@ -3155,115 +3160,38 @@ ;; Make the `c-lang-setvar' variables buffer local in the current buffer. ;; These are typically standard emacs variables such as `comment-start'. -(defmacro c-make-emacs-variables-local () - `(progn - ,@(mapcar (lambda (init) - `(make-local-variable ',(car init))) - (cdr c-emacs-variable-inits)))) - -(defun c-make-init-lang-vars-fun (mode) - "Create a function that initializes all the language dependent variables -for the given mode. - -This function should be evaluated at compile time, so that the -function it returns is byte compiled with all the evaluated results -from the language constants. Use the `c-init-language-vars' macro to -accomplish that conveniently." - - (if (and (not load-in-progress) - (boundp 'byte-compile-dest-file) - (stringp byte-compile-dest-file)) - - ;; No need to byte compile this lambda since the byte compiler is - ;; smart enough to detect the `funcall' construct in the - ;; `c-init-language-vars' macro below and compile it all straight - ;; into the function that contains `c-init-language-vars'. - `(lambda () - - ;; This let sets up the context for `c-mode-var' and similar - ;; that could be in the result from `cl-macroexpand-all'. - (let ((c-buffer-is-cc-mode ',mode) - current-var source-eval) - (c-make-emacs-variables-local) - (condition-case err - - (if (eq c-version-sym ',c-version-sym) - (setq ,@(let ((c-buffer-is-cc-mode mode) - (c-lang-const-expansion 'immediate)) - ;; `c-lang-const' will expand to the evaluated - ;; constant immediately in `cl-macroexpand-all' - ;; below. - (mapcan - (lambda (init) - `(current-var ',(car init) - ,(car init) ,(cl-macroexpand-all - (elt init 1)))) - ;; Note: The following `append' copies the - ;; first argument. That list is small, so - ;; this doesn't matter too much. - (append (cdr c-emacs-variable-inits) - (cdr c-lang-variable-inits))))) - - ;; This diagnostic message isn't useful for end - ;; users, so it's disabled. - ;;(unless (get ',mode 'c-has-warned-lang-consts) - ;; (message ,(concat "%s compiled with CC Mode %s " - ;; "but loaded with %s - evaluating " - ;; "language constants from source") - ;; ',mode ,c-version c-version) - ;; (put ',mode 'c-has-warned-lang-consts t)) - - (setq source-eval t) - (let ((init ',(append (cdr c-emacs-variable-inits) - (cdr c-lang-variable-inits)))) - (while init - (setq current-var (caar init)) - (set (caar init) (eval (cadar init))) - (setq init (cdr init))))) - - (error - (if current-var - (message "Eval error in the `c-lang-defvar' or `c-lang-setvar' for `%s'%s: %S" - current-var - (if source-eval - (format "\ - (fallback source eval - %s compiled with CC Mode %s but loaded with %s)" - ',mode ,c-version c-version) - "") - err) - (signal (car err) (cdr err))))))) - - ;; Being evaluated from source. Always use the dynamic method to - ;; work well when `c-lang-defvar's in this file are reevaluated - ;; interactively. - `(lambda () - (require 'cc-langs) - (let ((c-buffer-is-cc-mode ',mode) - (init (append (cdr c-emacs-variable-inits) - (cdr c-lang-variable-inits))) - current-var) - (c-make-emacs-variables-local) - (condition-case err - - (while init - (setq current-var (caar init)) - (set (caar init) (eval (cadar init))) - (setq init (cdr init))) - - (error - (if current-var - (message - "Eval error in the `c-lang-defvar' or `c-lang-setver' for `%s' (source eval): %S" - current-var err) - (signal (car err) (cdr err))))))) - )) +(defun c-make-emacs-variables-local () + (mapcar (lambda (init) + (make-local-variable (car init))) + (cdr c-emacs-variable-inits))) + +(defun c-init-language-vars-for (mode) + "Initialize the cc-mode language variables for MODE. +MODE is a symbol naming the mode to initialize." + (let ((c-buffer-is-cc-mode mode) + (init (append (cdr c-emacs-variable-inits) + (cdr c-lang-variable-inits))) + current-var) + (c-make-emacs-variables-local) + (condition-case err + (while init + (setq current-var (caar init)) + (set (caar init) (eval (cadar init) nil)) + (setq init (cdr init))) + (error + (if current-var + (message + "Eval error in the `c-lang-defvar' or `c-lang-setver' for `%s' (source eval): %S" + current-var err) + (signal (car err) (cdr err))))))) (defmacro c-init-language-vars (mode) "Initialize all the language dependent variables for the given mode. -This macro is expanded at compile time to a form tailored for the mode -in question, so MODE must be a constant. Therefore MODE is not -evaluated and should not be quoted." - `(funcall ,(c-make-init-lang-vars-fun mode))) +MODE is not evaluated and should not be quoted. This macro used +to produce an optimized initialization tailored to MODE, but that +optimization is no longer worth it. Use +`c-init-language-vars-for' instead." + `(c-init-language-vars-for ',mode)) \f (cc-provide 'cc-langs) === modified file 'lisp/progmodes/cc-mode.el' --- lisp/progmodes/cc-mode.el 2014-03-04 04:03:34 +0000 +++ lisp/progmodes/cc-mode.el 2014-05-02 01:20:44 +0000 @@ -149,21 +149,6 @@ (defun c-leave-cc-mode-mode () (setq c-buffer-is-cc-mode nil)) -(defun c-init-language-vars-for (mode) - "Initialize the language variables for one of the language modes -directly supported by CC Mode. This can be used instead of the -`c-init-language-vars' macro if the language you want to use is one of -those, rather than a derived language defined through the language -variable system (see \"cc-langs.el\")." - (cond ((eq mode 'c-mode) (c-init-language-vars c-mode)) - ((eq mode 'c++-mode) (c-init-language-vars c++-mode)) - ((eq mode 'objc-mode) (c-init-language-vars objc-mode)) - ((eq mode 'java-mode) (c-init-language-vars java-mode)) - ((eq mode 'idl-mode) (c-init-language-vars idl-mode)) - ((eq mode 'pike-mode) (c-init-language-vars pike-mode)) - ((eq mode 'awk-mode) (c-init-language-vars awk-mode)) - (t (error "Unsupported mode %s" mode)))) - ;;;###autoload (defun c-initialize-cc-mode (&optional new-style-init) "Initialize CC Mode for use in the current buffer. === modified file 'lisp/progmodes/cc-vars.el' --- lisp/progmodes/cc-vars.el 2014-01-01 07:43:34 +0000 +++ lisp/progmodes/cc-vars.el 2014-05-02 05:24:28 +0000 @@ -1614,6 +1614,75 @@ :group 'c) \f + +(define-widget 'c-extra-keywords-widget 'lazy + "Internal CC Mode widget for the `*-extra-keywords' variables." + :type '(repeat + (cons + (string :tag "Keyword") + (boolean :tag "Parenthesized expression follows")))) + +(defun c-make-extra-keywords-blurb (mode1 mode2) + (concat "\ +*List of extra keywords to recognize in " + mode1 " mode. +Each list item should be a cons (KW . PAREN). +KW should be a string naming a single identifier. +PAREN should be nil or t. If t, expect the a parenthesized expression +after KW and skip over it. + +Note that this variable is only consulted when the major mode is +initialized. If you change it later you have to reinitialize CC +Mode by doing \\[" mode2 "]. Additionally, if you change this +variable outside of customize, you need to call +`c-clear-value-cache' to make your changes take effect.")) + +(defun c-extra-keywords-setter (sym val) + (set-default sym val) + (c-clear-value-cache)) + +(defcustom c-extra-keywords + nil + (c-make-extra-keywords-blurb "C" "c-mode") + :type 'c-extra-keywords-widget + :set 'c-extra-keywords-setter + :group 'c) + +(defcustom c++-extra-keywords + nil + (c-make-extra-keywords-blurb "C++" "c++-mode") + :type 'c-extra-keywords-widget + :set 'c-extra-keywords-setter + :group 'c) + +(defcustom objc-extra-keywords + nil + (c-make-extra-keywords-blurb "ObjC" "objc-mode") + :type 'c-extra-keywords-widget + :set 'c-extra-keywords-setter + :group 'c) + +(defcustom java-extra-keywords + nil + (c-make-extra-keywords-blurb "Java" "java-mode") + :type 'c-extra-keywords-widget + :set 'c-extra-keywords-setter + :group 'c) + +(defcustom idl-extra-keywords nil + nil + :type 'c-extra-keywords-widget + :set 'c-extra-keywords-setter + :group 'c) + +(defcustom pike-extra-keywords + nil + (c-make-extra-keywords-blurb "Pike" "pike-mode") + :type 'c-extra-keywords-widget + :set 'c-extra-keywords-setter + :group 'c) + +\f ;; Non-customizable variables, still part of the interface to CC Mode (defvar c-macro-with-semi-re nil ;; Regular expression which matches a (#define'd) symbol whose expansion [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 884 bytes --] ^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: POC: customizable cc-mode keywords 2014-05-02 5:26 POC: customizable cc-mode keywords Daniel Colascione @ 2014-05-10 23:13 ` Daniel Colascione 2014-05-11 21:13 ` Alan Mackenzie 1 sibling, 0 replies; 41+ messages in thread From: Daniel Colascione @ 2014-05-10 23:13 UTC (permalink / raw) To: Emacs developers, Alan Mackenzie [-- Attachment #1: Type: text/plain, Size: 764 bytes --] On 05/01/2014 10:26 PM, Daniel Colascione wrote: > cc-mode has trouble with parsing dialects of C that use the preprocessor > heavily. Consider this example from the Linux kernel: > > static int perf_event_period(struct perf_event *event, u64 __user *arg) > > __user is defined to some GCC static analysis nonsense, but since > cc-mode doesn't know that, we see __user fontified in > font-lock-variable-name-face and *arg untouched. This example is fairly > benign (if ugly), but there are other cases where variations in > pre-processor C dialect confuse cc-mode in larger regions, leading to > odd fontification and indentation. > > The patch below adds customizable options for additional C-family > language "keywords". Ping. CC Alan. [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 884 bytes --] ^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: POC: customizable cc-mode keywords 2014-05-02 5:26 POC: customizable cc-mode keywords Daniel Colascione 2014-05-10 23:13 ` Daniel Colascione @ 2014-05-11 21:13 ` Alan Mackenzie 2014-05-11 21:23 ` Daniel Colascione 1 sibling, 1 reply; 41+ messages in thread From: Alan Mackenzie @ 2014-05-11 21:13 UTC (permalink / raw) To: Daniel Colascione; +Cc: Emacs developers Hi, Daniel. On Thu, May 01, 2014 at 10:26:07PM -0700, Daniel Colascione wrote: > cc-mode has trouble with parsing dialects of C that use the preprocessor > heavily. This has been true since 4004 BC, since C hackers are able to write monstrosities using macros. But we do our best to cope with the less outlandish variants. > Consider this example from the Linux kernel: > static int perf_event_period(struct perf_event *event, u64 __user *arg) > __user is defined to some GCC static analysis nonsense, but since > cc-mode doesn't know that, we see __user fontified in > font-lock-variable-name-face and *arg untouched. This example is fairly > benign (if ugly), but there are other cases where variations in > pre-processor C dialect confuse cc-mode in larger regions, leading to > odd fontification and indentation. > The patch below adds customizable options for additional C-family > language "keywords". > To add this feature, we have to change how cc-mode evaluates its > language variables. :-) > Today, we use clever macros to hard-code the values of all cc-mode > language variables into the mode functions of each cc-mode major mode > function or into c-init-language-vars-for, but in order to allow users > to customize cc-mode syntax, we have to be able to recompute language > constants and variables at runtime. Do we, now? You can imagine I've one or two reservations about this idea. It's far from clear that this level of customisation is a good thing. The current idea is that the language variables are for creating new CC Mode languages, not as a means of customisation. > The new code simply evaluates cc-mode language setter forms at mode > initialization instead. This approach is slower, but not by much: it > takes 0.9ms to set up cc-mode's ~130 language variables using the > precompiled function approach, while it takes 1.6ms to do the same work > using dynamic evaluation. I can live with this performance regression. Have you considered turning the pertinent language variables into customisable variables in cc-vars.el, along the lines of *-font-lock-extra-types? > As implemented, the keyword list can only be customized globally, but > it'd be nice to be able to do something buffer-local too. [ snipped patch for now. ] -- Alan Mackenzie (Nuremberg, Germany). ^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: POC: customizable cc-mode keywords 2014-05-11 21:13 ` Alan Mackenzie @ 2014-05-11 21:23 ` Daniel Colascione 2014-05-16 17:52 ` Alan Mackenzie 0 siblings, 1 reply; 41+ messages in thread From: Daniel Colascione @ 2014-05-11 21:23 UTC (permalink / raw) To: Alan Mackenzie; +Cc: Emacs developers [-- Attachment #1: Type: text/plain, Size: 3004 bytes --] On 05/11/2014 02:13 PM, Alan Mackenzie wrote: > Hi, Daniel. > > On Thu, May 01, 2014 at 10:26:07PM -0700, Daniel Colascione wrote: >> cc-mode has trouble with parsing dialects of C that use the preprocessor >> heavily. > > This has been true since 4004 BC, since C hackers are able to write > monstrosities using macros. But we do our best to cope with the less > outlandish variants. We have to address the syntactic confusion these macros cause somehow, and I don't think automatic heuristics will be sufficient. I'm really sick of seeing a lot of code I look at in the real world misfontified. >> Consider this example from the Linux kernel: > >> static int perf_event_period(struct perf_event *event, u64 __user *arg) > >> __user is defined to some GCC static analysis nonsense, but since >> cc-mode doesn't know that, we see __user fontified in >> font-lock-variable-name-face and *arg untouched. This example is fairly >> benign (if ugly), but there are other cases where variations in >> pre-processor C dialect confuse cc-mode in larger regions, leading to >> odd fontification and indentation. > >> The patch below adds customizable options for additional C-family >> language "keywords". > >> To add this feature, we have to change how cc-mode evaluates its >> language variables. > > :-) > >> Today, we use clever macros to hard-code the values of all cc-mode >> language variables into the mode functions of each cc-mode major mode >> function or into c-init-language-vars-for, but in order to allow users >> to customize cc-mode syntax, we have to be able to recompute language >> constants and variables at runtime. > > Do we, now? You can imagine I've one or two reservations about this > idea. What's your alternative? > It's far from clear that this level of customisation is a good > thing. The current idea is that the language variables are for creating > new CC Mode languages, not as a means of customisation. They're public either way. >> The new code simply evaluates cc-mode language setter forms at mode >> initialization instead. This approach is slower, but not by much: it >> takes 0.9ms to set up cc-mode's ~130 language variables using the >> precompiled function approach, while it takes 1.6ms to do the same work >> using dynamic evaluation. I can live with this performance regression. > > Have you considered turning the pertinent language variables into > customisable variables in cc-vars.el, along the lines of > *-font-lock-extra-types? The patch includes user-customizable variables. The actual cc-lang constants aren't advertised as user customization points. The existing type customization is simple because it's done in isolation from the rest of cc-mode's syntactic analysis. Actually understanding keywords requires deeper, cascading changes to core language constants. The only practical way of making that happen is to allow these constants to change at runtime. [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 884 bytes --] ^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: POC: customizable cc-mode keywords 2014-05-11 21:23 ` Daniel Colascione @ 2014-05-16 17:52 ` Alan Mackenzie 2014-05-16 18:06 ` Daniel Colascione 0 siblings, 1 reply; 41+ messages in thread From: Alan Mackenzie @ 2014-05-16 17:52 UTC (permalink / raw) To: Daniel Colascione; +Cc: Emacs developers Hi, Daniel. On Sun, May 11, 2014 at 02:23:15PM -0700, Daniel Colascione wrote: > On 05/11/2014 02:13 PM, Alan Mackenzie wrote: > > Hi, Daniel. > > On Thu, May 01, 2014 at 10:26:07PM -0700, Daniel Colascione wrote: > >> cc-mode has trouble with parsing dialects of C that use the preprocessor > >> heavily. > > This has been true since 4004 BC, since C hackers are able to write > > monstrosities using macros. But we do our best to cope with the less > > outlandish variants. > We have to address the syntactic confusion these macros cause somehow, > and I don't think automatic heuristics will be sufficient. I'm really > sick of seeing a lot of code I look at in the real world misfontified. OK, so we need to have configurable "noise macros", just as we already have configurable "macros ending with a semicolon" and "extra types". [ .... ] > >> The patch below adds customizable options for additional C-family > >> language "keywords". > >> To add this feature, we have to change how cc-mode evaluates its > >> language variables. > > :-) > >> Today, we use clever macros to hard-code the values of all cc-mode > >> language variables into the mode functions of each cc-mode major mode > >> function or into c-init-language-vars-for, but in order to allow users > >> to customize cc-mode syntax, we have to be able to recompute language > >> constants and variables at runtime. > > Do we, now? You can imagine I've one or two reservations about this > > idea. > What's your alternative? Turning the pertinent c-lang-defvars, and only these, into configurable variables in cc-vars.el. [ .... ] > >> The new code simply evaluates cc-mode language setter forms at mode > >> initialization instead. This approach is slower, but not by much: it > >> takes 0.9ms to set up cc-mode's ~130 language variables using the > >> precompiled function approach, while it takes 1.6ms to do the same work > >> using dynamic evaluation. I can live with this performance regression. > > Have you considered turning the pertinent language variables into > > customisable variables in cc-vars.el, along the lines of > > *-font-lock-extra-types? > The patch includes user-customizable variables. The actual cc-lang > constants aren't advertised as user customization points. The existing > type customization is simple because it's done in isolation from the > rest of cc-mode's syntactic analysis. Actually understanding keywords > requires deeper, cascading changes to core language constants. The only > practical way of making that happen is to allow these constants to > change at runtime. I'm sorry, but I can't make much of that paragraph; it doesn't seem coherent to me. What I still don't understand is why it should be necessary to make _all_ c-lang-defvars configurable variables, rather than just those one or two directly involved in parsing these awkward C (etc.) declarations. As I said, I'm not at all happy at making such a massive change to CC Mode's architecture. There would surely be unforeseen consequences, some of which might well be negative. -- Alan Mackenzie (Nuremberg, Germany). ^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: POC: customizable cc-mode keywords 2014-05-16 17:52 ` Alan Mackenzie @ 2014-05-16 18:06 ` Daniel Colascione 2014-05-18 21:33 ` Alan Mackenzie 0 siblings, 1 reply; 41+ messages in thread From: Daniel Colascione @ 2014-05-16 18:06 UTC (permalink / raw) To: Alan Mackenzie; +Cc: Emacs developers [-- Attachment #1: Type: text/plain, Size: 1851 bytes --] On 05/16/2014 10:52 AM, Alan Mackenzie wrote: >>>> Today, we use clever macros to hard-code the values of all cc-mode >>>> language variables into the mode functions of each cc-mode major mode >>>> function or into c-init-language-vars-for, but in order to allow users >>>> to customize cc-mode syntax, we have to be able to recompute language >>>> constants and variables at runtime. > >>> Do we, now? You can imagine I've one or two reservations about this >>> idea. > >> What's your alternative? > > Turning the pertinent c-lang-defvars, and only these, into configurable > variables in cc-vars.el. Have you looked into what task actually involves? You need to modify c-decl-hangon-kwds, and as a result, c-prefix-spec-kwds, c-postfix-spec-kwds, c-keywords, c-keywords-regexp, c-keywords-obarray, c-nonlabel-token-key, and c-regular-keywords-regexp. It's easier and more flexible to simply allow the entire set of c-lang-defconst values to change. You also have to recompute the font-lock matchers, which is similarly involved. You claim that there is a great risk of negative side effects resulting from this change. I don't agree, and I don't see anyone else proposing, much less implementing, a solution to this problem, and cc-mode's being developed outside the tree makes it frustratingly slow and difficult to get much-needed fixes into core where users can see them. > As I said, I'm not at all happy at making such a massive change to CC > Mode's architecture. There would surely be unforeseen consequences, some > of which might well be negative. It's not a massive change in architecture. cc-mode can already evaluate these variables at runtime in the case of a version mismatch. I propose simply doing so all the time. My timing indicates that it's not a performance problem in practice. [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 884 bytes --] ^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: POC: customizable cc-mode keywords 2014-05-16 18:06 ` Daniel Colascione @ 2014-05-18 21:33 ` Alan Mackenzie 2014-05-18 22:28 ` Daniel Colascione 2014-09-08 17:28 ` Stefan Monnier 0 siblings, 2 replies; 41+ messages in thread From: Alan Mackenzie @ 2014-05-18 21:33 UTC (permalink / raw) To: Daniel Colascione; +Cc: Emacs developers Hello, Daniel. On Fri, May 16, 2014 at 11:06:24AM -0700, Daniel Colascione wrote: > On 05/16/2014 10:52 AM, Alan Mackenzie wrote: > >>>> Today, we use clever macros to hard-code the values of all cc-mode > >>>> language variables into the mode functions of each cc-mode major mode > >>>> function or into c-init-language-vars-for, but in order to allow users > >>>> to customize cc-mode syntax, we have to be able to recompute language > >>>> constants and variables at runtime. > >>> Do we, now? You can imagine I've one or two reservations about this > >>> idea. > >> What's your alternative? > > Turning the pertinent c-lang-defvars, and only these, into configurable > > variables in cc-vars.el. > Have you looked into what task actually involves? No I hadn't. > You need to modify c-decl-hangon-kwds, and as a result, > c-prefix-spec-kwds, c-postfix-spec-kwds, c-keywords, > c-keywords-regexp, c-keywords-obarray, c-nonlabel-token-key, and > c-regular-keywords-regexp. OK. Then another alternative is to use `or' forms in the appropriate places, of which there are several rather than many, the extra arm of the `or' looking something like "(looking-at c-noise-macro-re)". Did you consider this at all? If so, why do you prefer the solution you now propose? > It's easier and more flexible to simply allow the entire set of > c-lang-defconst values to change. It's the flexibility that worries me. Flexibility means complexity (of which there's already too much in CC Mode), and might open up a larger "attack surface" for future bugs. I've spent a lot of time trying to pin down exactly what your proposed change does and how it does it, but amn't there yet. I only have the before and after versions, not a detailed description of the change. > You also have to recompute the font-lock matchers, which is similarly > involved. Yes. > You claim that there is a great risk of negative side effects resulting > from this change. No. I've said there is a risk, without quantifying it. One question which you haven't addressed yet is does the changed code work properly on modes derived from a CC Mode mode? How easy is it to create a `foo-extra-keywords' for such a mode? Another is does the change work properly under XEmacs? What is the purpose of {java,idl,pike}-extra-keywords, given that these three languages don't have #defines? > I don't agree, and I don't see anyone else proposing, much less > implementing, a solution to this problem, ..... :-) This problem was first highlighted as such, by you, this month, not several years ago. Your patch is complicated, it's disruptive, yet you seem put out that I want to discuss it and understand it, rather than just blindly applying it as it is. It seems your use of "You need to" and "we have to" weren't mere hyperbole as I first thought. Forgive me, but I'm always suspicious when somebody tells me "there's no alternative". There are always alternatives. The question is why is your patch, which is not a straightforward or obvious change, the best solution to the problem. What are the tradeoffs? > .... and cc-mode's being developed outside the tree makes it > frustratingly slow and difficult to get much-needed fixes into core > where users can see them. Would it really be much faster if CC Mode were integrated? Not really. What makes things slow is the small number of people working on CC Mode, i.e. one, with occasional help from people like yourself. > > As I said, I'm not at all happy at making such a massive change to CC > > Mode's architecture. There would surely be unforeseen consequences, some > > of which might well be negative. > It's not a massive change in architecture. As I said, I don't fully understand the change, yet. But moving calculations from compile time to run time _is_ a change of architecture, and it seems to me not to be small. It seems to me that the rigid separation between language (e.g. C) and user configuration is being broken down. How much easier will it be for a user mistakenly to attempt to configure her CC Mode by messing around with the c-lang-consts? > cc-mode can already evaluate these variables at runtime in the case of > a version mismatch. That's a feature intended purely for CC Mode developers. > I propose simply doing so all the time. My timing indicates that it's > not a performance problem in practice. -- Alan Mackenzie (Nuremberg, Germany). ^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: POC: customizable cc-mode keywords 2014-05-18 21:33 ` Alan Mackenzie @ 2014-05-18 22:28 ` Daniel Colascione 2014-05-19 2:25 ` Stefan Monnier 2014-05-25 18:08 ` Alan Mackenzie 2014-09-08 17:28 ` Stefan Monnier 1 sibling, 2 replies; 41+ messages in thread From: Daniel Colascione @ 2014-05-18 22:28 UTC (permalink / raw) To: Alan Mackenzie; +Cc: Emacs developers [-- Attachment #1: Type: text/plain, Size: 7711 bytes --] On 05/18/2014 02:33 PM, Alan Mackenzie wrote: > On Fri, May 16, 2014 at 11:06:24AM -0700, Daniel Colascione wrote: >> On 05/16/2014 10:52 AM, Alan Mackenzie wrote: >>>>>> Today, we use clever macros to hard-code the values of all cc-mode >>>>>> language variables into the mode functions of each cc-mode major mode >>>>>> function or into c-init-language-vars-for, but in order to allow users >>>>>> to customize cc-mode syntax, we have to be able to recompute language >>>>>> constants and variables at runtime. > >>>>> Do we, now? You can imagine I've one or two reservations about this >>>>> idea. > >>>> What's your alternative? > >>> Turning the pertinent c-lang-defvars, and only these, into configurable >>> variables in cc-vars.el. > >> Have you looked into what task actually involves? > > No I hadn't. > >> You need to modify c-decl-hangon-kwds, and as a result, >> c-prefix-spec-kwds, c-postfix-spec-kwds, c-keywords, >> c-keywords-regexp, c-keywords-obarray, c-nonlabel-token-key, and >> c-regular-keywords-regexp. > > OK. Then another alternative is to use `or' forms in the appropriate > places, of which there are several rather than many, the extra arm of > the `or' looking something like "(looking-at c-noise-macro-re)". Did you > consider this at all? If so, why do you prefer the solution you now > propose? Doing it that way further increases the amount of work needed at parse time, and cc-mode isn't a speed demon already. Your proposal also introduces much-increased for complexity in the core and creates a risk of "missing a spot" and introducing a bug where we check the primary keywords but not the user-customized ones. (And what about the checking we do after calling intern-soft on the symbol obarray?) cc-engine is very difficult to follow as it is. I'd rather gracefully extend the existing functionality than add yet another set of special cases. Another approach I was considering was to change cc-mode to always skip over regions marked with a certain text properly. Then a minor mode could independently parse and fontify the buffer, marking regions it wanted cc-mode to ignore with this property. This approach is more flexible, but I don't think the complexity is worth it when a simple extension to cc-mode is within reach. >> It's easier and more flexible to simply allow the entire set of >> c-lang-defconst values to change. > > It's the flexibility that worries me. Flexibility means complexity (of > which there's already too much in CC Mode), and might open up a larger > "attack surface" for future bugs. > > I've spent a lot of time trying to pin down exactly what your proposed > change does and how it does it, but amn't there yet. I only have the > before and after versions, not a detailed description of the change. I'd hoped my initial message clearly explained the overall approach. Briefly, we want to allow users to tell cc-mode to ignore "noise macros" when parsing. IMHO, the best way to do that is to let user customizations augment the existing set of "noise macro" keywords cc-mode defines for each language. Today, cc-mode builds various data structures from these keyword sets at compile time. In order for user customizations to have any effect, we have to build these data structures at runtime instead. Doing that has no perceivable effect on mode initialization performance and lets user customizations have an effect. >> You claim that there is a great risk of negative side effects resulting >> from this change. > > No. I've said there is a risk, without quantifying it. > > One question which you haven't addressed yet is does the changed code > work properly on modes derived from a CC Mode mode? How easy is it to > create a `foo-extra-keywords' for such a mode? Trivial --- just include the variable in the c-lang-defconst calculation for the derived mode. > Another is does the change work properly under XEmacs? I don't see why it wouldn't. > What is the purpose of {java,idl,pike}-extra-keywords, given that these > three languages don't have #defines? Consistency with the type defcustoms? Accommodations for weird custom preprocessors? Why not? >> I don't agree, and I don't see anyone else proposing, much less >> implementing, a solution to this problem, ..... > > :-) This problem was first highlighted as such, by you, this month, not > several years ago. There's been a TODO in the code to this effect since 2005 in the definition of c-decl-hangon-kwds; my patch removes this TODO. > Your patch is complicated, it's disruptive, yet you > seem put out that I want to discuss it and understand it, rather than > just blindly applying it as it is. It seems your use of "You need to" > and "we have to" weren't mere hyperbole as I first thought. Forgive me, > but I'm always suspicious when somebody tells me "there's no > alternative". There are always alternatives. The question is why is > your patch, which is not a straightforward or obvious change, the best > solution to the problem. What are the tradeoffs? I discussed some of them above. The chief risk is that users might customize cc-mode by altering its language constants. I strongly discount this risk, especially since users can *already* do that by creating derived modes. >> .... and cc-mode's being developed outside the tree makes it >> frustratingly slow and difficult to get much-needed fixes into core >> where users can see them. > > Would it really be much faster if CC Mode were integrated? Not really. > What makes things slow is the small number of people working on CC Mode, > i.e. one, with occasional help from people like yourself. > >>> As I said, I'm not at all happy at making such a massive change to CC >>> Mode's architecture. There would surely be unforeseen consequences, some >>> of which might well be negative. > >> It's not a massive change in architecture. > > As I said, I don't fully understand the change, yet. But moving > calculations from compile time to run time _is_ a change of > architecture, and it seems to me not to be small. All the cc-defvar variables get the same values they did before, by default. cc-engine parses text the same way it always has. All the cc-mode customization remains. My patch merely lets users customize some existing cc-mode constants, then makes these customizations have runtime effect by removing some unnecessary old optimizations in cc-mode initialization. If you call that a massive change in architecture, then what I call architecture might as well be plate tectonics. > It seems to me > that the rigid separation between language (e.g. C) and user > configuration is being broken down. How much easier will it be for a > user mistakenly to attempt to configure her CC Mode by messing around > with the c-lang-consts? Much easier --- but it's never been a priority in Emacs to prevent users from hanging themselves. Users should be drawn to the customization settings we provide, and if they choose to bypass them, they probably know well enough what they're doing. As I mentioned, determined users can already derived from cc-mode built-in modes. >> cc-mode can already evaluate these variables at runtime in the case of >> a version mismatch. > > That's a feature intended purely for CC Mode developers. Or for people who upgrade without recompiling derived modes. But it doesn't matter --- the dynamic-computation code is there and works fine. My change just uses it all the time instead of going down a different path involving dubious compile-time optimizations. [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 884 bytes --] ^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: POC: customizable cc-mode keywords 2014-05-18 22:28 ` Daniel Colascione @ 2014-05-19 2:25 ` Stefan Monnier 2014-05-25 18:08 ` Alan Mackenzie 1 sibling, 0 replies; 41+ messages in thread From: Stefan Monnier @ 2014-05-19 2:25 UTC (permalink / raw) To: Daniel Colascione; +Cc: Alan Mackenzie, Emacs developers [ Commenting from the side lines. ] Daniel, you sell your patch very convincingly. I don't know the technical details well enough to judge, but I find CC-mode's compilation fiendishly complex (E.g. a lot of the cc-bytecomp.el tricks seem to be there so as to allow manual calls to the byte-compiler access to some data/functions which would otherwise only be defined later during runtime, IIUC), so I'm wondering if your change might rather help or hurt in this respect. Stefan ^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: POC: customizable cc-mode keywords 2014-05-18 22:28 ` Daniel Colascione 2014-05-19 2:25 ` Stefan Monnier @ 2014-05-25 18:08 ` Alan Mackenzie 1 sibling, 0 replies; 41+ messages in thread From: Alan Mackenzie @ 2014-05-25 18:08 UTC (permalink / raw) To: Daniel Colascione; +Cc: Emacs developers Hi, Daniel. Thanks for the detailed response. In general, you're gradually persuading me of your new approach. On Sun, May 18, 2014 at 03:28:50PM -0700, Daniel Colascione wrote: > On 05/18/2014 02:33 PM, Alan Mackenzie wrote: > > On Fri, May 16, 2014 at 11:06:24AM -0700, Daniel Colascione wrote: > >> On 05/16/2014 10:52 AM, Alan Mackenzie wrote: > >>>>>> Today, we use clever macros to hard-code the values of all cc-mode > >>>>>> language variables into the mode functions of each cc-mode major mode > >>>>>> function or into c-init-language-vars-for, but in order to allow users > >>>>>> to customize cc-mode syntax, we have to be able to recompute language > >>>>>> constants and variables at runtime. > >>>>> Do we, now? You can imagine I've one or two reservations about this > >>>>> idea. > >>>> What's your alternative? > >>> Turning the pertinent c-lang-defvars, and only these, into configurable > >>> variables in cc-vars.el. > >> Have you looked into what task actually involves? > > No I hadn't. > >> You need to modify c-decl-hangon-kwds, and as a result, > >> c-prefix-spec-kwds, c-postfix-spec-kwds, c-keywords, > >> c-keywords-regexp, c-keywords-obarray, c-nonlabel-token-key, and > >> c-regular-keywords-regexp. Thinking about it, changing the minimum number of c-lang-consts/vars to the new scheme would also be a feasible strategy. It would reduce the opportunity of semi-experienced users to shoot themselves in the foot (as we're discussing lower down). > > OK. Then another alternative is to use `or' forms in the appropriate > > places, of which there are several rather than many, the extra arm of > > the `or' looking something like "(looking-at c-noise-macro-re)". Did you > > consider this at all? If so, why do you prefer the solution you now > > propose? > Doing it that way further increases the amount of work needed at parse > time, and cc-mode isn't a speed demon already. Your proposal also > introduces much-increased for complexity in the core and creates a risk > of "missing a spot" and introducing a bug where we check the primary > keywords but not the user-customized ones. (And what about the checking > we do after calling intern-soft on the symbol obarray?) cc-engine is > very difficult to follow as it is. I'd rather gracefully extend the > existing functionality than add yet another set of special cases. Yes, some slight loss of processing speed, and a little extra complexity. > Another approach I was considering was to change cc-mode to always skip > over regions marked with a certain text properly. Then a minor mode > could independently parse and fontify the buffer, marking regions it > wanted cc-mode to ignore with this property. This approach is more > flexible, but I don't think the complexity is worth it when a simple > extension to cc-mode is within reach. I agree with you here. [ .... ] > > I've spent a lot of time trying to pin down exactly what your proposed > > change does and how it does it, but amn't there yet. I only have the > > before and after versions, not a detailed description of the change. > I'd hoped my initial message clearly explained the overall approach. > Briefly, we want to allow users to tell cc-mode to ignore "noise macros" > when parsing. IMHO, the best way to do that is to let user > customizations augment the existing set of "noise macro" keywords > cc-mode defines for each language. Today, cc-mode builds various data > structures from these keyword sets at compile time. In order for user > customizations to have any effect, we have to build these data > structures at runtime instead. Doing that has no perceivable effect on > mode initialization performance and lets user customizations have an effect. I've got the overall strategy and motivation. What I don't have is a detailed description of the change - what defuns/defvars have been changed, the nitty-gritty purpose of each change, the detailed functionalities which have been removed/added, things like that. In short, what would go in a very detailed ChangeLog entry. Diff files tend to approach the "write-only" nature, and it's difficult to reconstruct somebody else's thought patterns from only this diff file. [ .... ] > > One question which you haven't addressed yet is does the changed code > > work properly on modes derived from a CC Mode mode? Meaning, "Somebody" (tm) will need to test this. > > How easy is it to create a `foo-extra-keywords' for such a mode? > Trivial --- just include the variable in the c-lang-defconst calculation > for the derived mode. I don't follow the semantics here. Hopefully maintainers of derived modes won't feel the need to add extra c-lang-consts, since c-lang-consts are meant to be defined for every language. But answering my own question, it should be easy enough to define `foo-extra-keywords' using the same mechanism as for c-extra-keywords, since it will then be picked up by the (c-mode-symbol "extra-keywords") in cc-langs.el. > > Another is does the change work properly under XEmacs? > I don't see why it wouldn't. Well, it might be using, say, customize-... functions which don't (yet) exist in XEmacs. "Somebody" (tm) will need to test this too. > > What is the purpose of {java,idl,pike}-extra-keywords, given that these > > three languages don't have #defines? > Consistency with the type defcustoms? Accommodations for weird custom > preprocessors? Why not? Why not, indeed? Just there isn't one for AWK. ;-) > >> I don't agree, and I don't see anyone else proposing, much less > >> implementing, a solution to this problem, ..... > > :-) This problem was first highlighted as such, by you, this month, not > > several years ago. > There's been a TODO in the code to this effect since 2005 in the > definition of c-decl-hangon-kwds; my patch removes this TODO. Yes, OK. But nobody's raised a fuss about it up till now. > > Your patch is complicated, it's disruptive, yet you > > seem put out that I want to discuss it and understand it, rather than > > just blindly applying it as it is. It seems your use of "You need to" > > and "we have to" weren't mere hyperbole as I first thought. Forgive me, > > but I'm always suspicious when somebody tells me "there's no > > alternative". There are always alternatives. The question is why is > > your patch, which is not a straightforward or obvious change, the best > > solution to the problem. What are the tradeoffs? > I discussed some of them above. The chief risk is that users might > customize cc-mode by altering its language constants. I strongly > discount this risk, especially since users can *already* do that by > creating derived modes. No, these activities are conceptually different. Creating a derived mode is clearly hacking, as contrasted with configuring. The CC Mode language constants are like defuns of typical major modes, not their configuration variables. It should somehow be clear to people changing the c-lang-consts that they are actually hacking and not configuring. [ .... ] > >>> As I said, I'm not at all happy at making such a massive change to > >>> CC Mode's architecture. There would surely be unforeseen > >>> consequences, some of which might well be negative. > >> It's not a massive change in architecture. > > As I said, I don't fully understand the change, yet. But moving > > calculations from compile time to run time _is_ a change of > > architecture, and it seems to me not to be small. > All the cc-defvar variables get the same values they did before, by > default. cc-engine parses text the same way it always has. All the > cc-mode customization remains. My patch merely lets users customize some > existing cc-mode constants, then makes these customizations have runtime > effect by removing some unnecessary old optimizations in cc-mode > initialization. If you call that a massive change in architecture, then > what I call architecture might as well be plate tectonics. We've now reached the stage of arguing about words. Let's stop! > > It seems to me that the rigid separation between language (e.g. C) > > and user configuration is being broken down. How much easier will it > > be for a user mistakenly to attempt to configure her CC Mode by > > messing around with the c-lang-consts? > Much easier --- but it's never been a priority in Emacs to prevent users > from hanging themselves. Yes, but who's going to have to bring the corpse down from the scaffold and bury it? By what mechanism will the said user come to understand that c-lang-consts are not configuration variables? > Users should be drawn to the customization settings we provide, and if > they choose to bypass them, they probably know well enough what they're > doing. I've no problem with that if they're making an informed choice. But even in the current CC Mode mechanisms, I've occasionally been asked about configuring CC Mode via c-lang-consts. It shouldn't be too easy. > As I mentioned, determined users can already derive from cc-mode > built-in modes. Yes. But this is an intended facility, and isn't something that anyone can stumble into by accident. > >> cc-mode can already evaluate these variables at runtime in the case of > >> a version mismatch. > > That's a feature intended purely for CC Mode developers. > Or for people who upgrade without recompiling derived modes. But it > doesn't matter --- the dynamic-computation code is there and works fine. > My change just uses it all the time instead of going down a different > path involving dubious compile-time optimizations. One other point. Would it be possible to call foo-extra-keywords something else? What we're dealing with _aren't_ keywords like "if" or "class", they're macros which expand to nothing. I know that things like "__attribute__" are currently called keywords, but extending the metaphor to things like "__user" seems to be pushing things too far. How about "foo-noise-macros"? -- Alan Mackenzie (Nuremberg, Germany). ^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: POC: customizable cc-mode keywords 2014-05-18 21:33 ` Alan Mackenzie 2014-05-18 22:28 ` Daniel Colascione @ 2014-09-08 17:28 ` Stefan Monnier 2014-09-11 13:55 ` Further CC-mode changes Stefan Monnier 1 sibling, 1 reply; 41+ messages in thread From: Stefan Monnier @ 2014-09-08 17:28 UTC (permalink / raw) To: Alan Mackenzie; +Cc: Daniel Colascione, Emacs developers > :-) This problem was first highlighted as such, by you, this month, not > several years ago. Your patch is complicated, it's disruptive, yet you > seem put out that I want to discuss it and understand it, rather than > just blindly applying it as it is. FWIW, his patch is not that complicated. It has 2 parts: - get rid of some of the compile-time precomputation of settings. - add a new (set of) custom vars and use them where appropriate. The second part is very straightforward (quoted below, for reference). The first part mostly removes code, and more specifically removes complex code, so it actually makes the code simpler. I think the performance impact is higher than what Daniel claims (his machine is clearly faster than mine), but I suspect that this can be fixed. >> It's not a massive change in architecture. > As I said, I don't fully understand the change, yet. Take another look at it, below. > But moving calculations from compile time to run time _is_ a change of > architecture, and it seems to me not to be small. Right, this one is larger, but if it can be made without significant performance degradation, then it's a good change. > It seems to me that the rigid separation between language (e.g. C) and > user configuration is being broken down. How much easier will it be > for a user mistakenly to attempt to configure her CC Mode by messing > around with the c-lang-consts? I'm not too worried ;-) Stefan === modified file 'lisp/progmodes/cc-langs.el' --- lisp/progmodes/cc-langs.el 2014-01-01 07:43:34 +0000 +++ lisp/progmodes/cc-langs.el 2014-05-02 05:19:24 +0000 @@ -1921,15 +1921,13 @@ ;; declaration. Specifically, they aren't recognized in the middle ;; of multi-token types, inside declarators, and between the ;; identifier and the arglist paren of a function declaration. - ;; - ;; FIXME: This ought to be user customizable since compiler stuff - ;; like this usually is wrapped in project specific macros. (It'd - ;; of course be even better if we could cope without knowing this.) - t nil - (c c++) '(;; GCC extension. - "__attribute__" - ;; MSVC extension. - "__declspec")) + t (when (boundp (c-mode-symbol "extra-keywords")) + (mapcar #'car (c-mode-var "extra-keywords"))) + (c c++) (append (c-lang-const c-decl-hangon-kwds) + '( ;; GCC extension. + "__attribute__" + ;; MSVC extension. + "__declspec"))) (c-lang-defconst c-decl-hangon-key ;; Adorned regexp matching `c-decl-hangon-kwds'. @@ -2120,11 +2118,18 @@ (c-lang-defconst c-paren-nontype-kwds "Keywords that may be followed by a parenthesis expression that doesn't contain type identifiers." - t nil - (c c++) '(;; GCC extension. - "__attribute__" - ;; MSVC extension. - "__declspec")) + t (when (boundp (c-mode-symbol "extra-keywords")) + (apply 'nconc + (mapcar (lambda (kw) + (when (cdr kw) + (list (car kw)))) + (c-mode-var "extra-keywords")))) + (c c++) (append + (c-lang-const c-paren-nontype-kwds) + '( ;; GCC extension. + "__attribute__" + ;; MSVC extension. + "__declspec"))) (c-lang-defconst c-paren-type-kwds "Keywords that may be followed by a parenthesis expression containing === modified file 'lisp/progmodes/cc-vars.el' --- lisp/progmodes/cc-vars.el 2014-01-01 07:43:34 +0000 +++ lisp/progmodes/cc-vars.el 2014-05-02 05:24:28 +0000 @@ -1614,6 +1614,75 @@ :group 'c) \f + +(define-widget 'c-extra-keywords-widget 'lazy + "Internal CC Mode widget for the `*-extra-keywords' variables." + :type '(repeat + (cons + (string :tag "Keyword") + (boolean :tag "Parenthesized expression follows")))) + +(defun c-make-extra-keywords-blurb (mode1 mode2) + (concat "\ +*List of extra keywords to recognize in " + mode1 " mode. +Each list item should be a cons (KW . PAREN). +KW should be a string naming a single identifier. +PAREN should be nil or t. If t, expect the a parenthesized expression +after KW and skip over it. + +Note that this variable is only consulted when the major mode is +initialized. If you change it later you have to reinitialize CC +Mode by doing \\[" mode2 "]. Additionally, if you change this +variable outside of customize, you need to call +`c-clear-value-cache' to make your changes take effect.")) + +(defun c-extra-keywords-setter (sym val) + (set-default sym val) + (c-clear-value-cache)) + +(defcustom c-extra-keywords + nil + (c-make-extra-keywords-blurb "C" "c-mode") + :type 'c-extra-keywords-widget + :set 'c-extra-keywords-setter + :group 'c) + +(defcustom c++-extra-keywords + nil + (c-make-extra-keywords-blurb "C++" "c++-mode") + :type 'c-extra-keywords-widget + :set 'c-extra-keywords-setter + :group 'c) + +(defcustom objc-extra-keywords + nil + (c-make-extra-keywords-blurb "ObjC" "objc-mode") + :type 'c-extra-keywords-widget + :set 'c-extra-keywords-setter + :group 'c) + +(defcustom java-extra-keywords + nil + (c-make-extra-keywords-blurb "Java" "java-mode") + :type 'c-extra-keywords-widget + :set 'c-extra-keywords-setter + :group 'c) + +(defcustom idl-extra-keywords nil + nil + :type 'c-extra-keywords-widget + :set 'c-extra-keywords-setter + :group 'c) + +(defcustom pike-extra-keywords + nil + (c-make-extra-keywords-blurb "Pike" "pike-mode") + :type 'c-extra-keywords-widget + :set 'c-extra-keywords-setter + :group 'c) + +\f ;; Non-customizable variables, still part of the interface to CC Mode (defvar c-macro-with-semi-re nil ;; Regular expression which matches a (#define'd) symbol whose expansion [[End of PGP Signed Part]] ^ permalink raw reply [flat|nested] 41+ messages in thread
* Further CC-mode changes 2014-09-08 17:28 ` Stefan Monnier @ 2014-09-11 13:55 ` Stefan Monnier 2014-09-12 23:59 ` Alan Mackenzie 0 siblings, 1 reply; 41+ messages in thread From: Stefan Monnier @ 2014-09-11 13:55 UTC (permalink / raw) To: Alan Mackenzie; +Cc: Emacs developers While waiting for your guidance as to which parts of my patches need to be reverted and why, here's some candidate patch which (contrary to the one you reverted) actually changes the code's behavior. It's to be applied on top of the ones you removed (tho since the ones you remove are mostly cosmetic, it shouldn't make much of a difference). Questions: - should C-c C-n and friends be moved to c-derivative-mode-map (AFAIK neither Java nor IDL nor Pike have CPP conditionals)? - I notice that all cc-mode enable abbrev-mode except for idl-mode. Was that on purpose or is it just accidental? - BTW, I think it would be better not to enable abbrev-mode (let it be a user's choice). IIUC CC-mode relies on abbrev-mode internally for some of its electric-indent functionality, so we'd have to use some other approach (e.g. a post-self-insert-hook). This is not really tested, especially not on XEmacs, but AFAIK it doesn't depend on any feature specific to a particular Emacs version. Stefan - Move awk-mode's actual definition to cc-awk so as to get rid of the (require 'cc-awk) and the ":syntax-table nil" hack. - make awk-mode use syntax-propertize when available. - Use define-derived-mode's built-in keymap inheritance rather than c-make-inherited-keymap. - initialize c-mode-base-map in its defvar. - fix c-after-font-lock-init so it doesn't accidentally add a c-after-change which wasn't there to begin with. - Run c-update-modeline from after-change-major-mode-hook and hack-local-variables-hook rather than from the major mode function. This lets us fix the bug where c-mode-hook is run twice and saves us from having to define c-run-mode-hooks. - make c-mode-common into an actual parent mode. There is a naming problem since we have c-mode-base-map for the "parent map" but c-mode-common-hook for the "parent hook", and also because this "mode" doesn't end in "-mode", but I think we can live with it. - add a new parent mode c-derivative-mode which can hold those things common to c, c++, and objc (i.e. languages which include C as a subset). I was tempted to simply use c-mode as the parent for c++-mode and objc-mode, but this would be a lot more intrusive and it would force the presence of a "C" menu in both C++ and ObjC modes (we could fix that for Emacs, but I'm not sure how to do it for XEmacs, and it doesn't seem worth the trouble). === modified file 'lisp/progmodes/cc-awk.el' --- lisp/progmodes/cc-awk.el 2014-09-09 15:08:08 +0000 +++ lisp/progmodes/cc-awk.el 2014-09-11 13:48:50 +0000 @@ -42,6 +42,7 @@ (require 'cc-defs) (require 'cc-engine) +(require 'cc-mode) (defvar awk-mode-syntax-table (let ((st (make-syntax-table))) @@ -52,7 +53,7 @@ (modify-syntax-entry ?\# "< " st) ;; / can delimit regexes or be a division operator. By default we assume ;; that it is a division sign, and fix the regexp operator cases with - ;; `font-lock-syntactic-keywords'. + ;; `syntax-table' text-properties. (modify-syntax-entry ?/ "." st) ; ACM 2002/4/27. (modify-syntax-entry ?* "." st) (modify-syntax-entry ?+ "." st) @@ -848,6 +849,17 @@ (max (+ (- c-awk-old-ByLL old-len) (- end beg)) (c-awk-beyond-logical-line end))) +(defun c-awk-syntax-propertize (beg end) + (c-awk-clear-NL-props beg (point-max)) + (goto-char beg) + (c-awk-set-syntax-table-properties end)) + +(defun c-awk-syntax-propertize-extend-region (beg end) + (let ((newend (c-awk-beyond-logical-line end)) + (newbeg (c-awk-beginning-of-logical-line beg))) + (if (or (< newbeg beg) (> newend end)) + (cons newbeg newend)))) + ;; ACM 2002/5/25. When font-locking is invoked by a buffer change, the region ;; specified by the font-lock after-change function must be expanded to ;; include ALL of any string or regexp within the region. The simplest way to @@ -1129,5 +1141,80 @@ (goto-char (min start-point end-point))))))) \f +;; Support for AWK + +;;;###autoload (add-to-list 'auto-mode-alist '("\\.awk\\'" . awk-mode)) +;;;###autoload (add-to-list 'interpreter-mode-alist '("awk" . awk-mode)) +;;;###autoload (add-to-list 'interpreter-mode-alist '("mawk" . awk-mode)) +;;;###autoload (add-to-list 'interpreter-mode-alist '("nawk" . awk-mode)) +;;;###autoload (add-to-list 'interpreter-mode-alist '("gawk" . awk-mode)) + +(c-define-abbrev-table 'awk-mode-abbrev-table + '(("else" "else" c-electric-continued-statement 0) + ("while" "while" c-electric-continued-statement 0)) + "Abbreviation table used in awk-mode buffers.") + +(defvar awk-mode-map + (let ((map (make-sparse-keymap)) + (sic (if (featurep 'xemacs) 'self-insert-command))) + ;; Add bindings which are only useful for awk. + (define-key map "#" sic) ; Override electric parent binding. + (define-key map "/" sic) ; Override electric parent binding. + (define-key map "*" sic) ; Override electric parent binding. + (define-key map "\C-c\C-n" 'undefined) ; #if doesn't exist in awk. + (define-key map "\C-c\C-p" 'undefined) + (define-key map "\C-c\C-u" 'undefined) + (define-key map "\M-a" 'c-beginning-of-statement) ; 2003/10/7 + (define-key map "\M-e" 'c-end-of-statement) ; 2003/10/7 + (define-key map "\C-\M-a" 'c-awk-beginning-of-defun) + (define-key map "\C-\M-e" 'c-awk-end-of-defun) + map) + "Keymap used in awk-mode buffers.") + +(easy-menu-define c-awk-menu awk-mode-map "AWK Mode Commands" + (cons "AWK" (c-lang-const c-mode-menu awk))) + +;;;###autoload +(define-derived-mode awk-mode c-mode-common "AWK" + "Major mode for editing AWK code. +To submit a problem report, enter `\\[c-submit-bug-report]' from an +awk-mode buffer. This automatically sets up a mail buffer with version +information already added. You just need to add a description of the +problem, including a reproducible test case, and send the message. + +To see what version of CC Mode you are running, enter `\\[c-version]'. + +The hook `c-mode-common-hook' is run with no args at mode +initialization, then `awk-mode-hook'. + +Key bindings: +\\{awk-mode-map}" + (c-init-language-vars-for 'awk-mode) + (c-common-init 'awk-mode) + (c-awk-unstick-NL-prop) + (when (fboundp 'syntax-propertize) + ;; `c-basic-common-init' unconditionally adds `c-before-change' but this + ;; function does lots of irrelevant stuff for us (to do with maintaining + ;; `c-found-types' and `c-state-cache'). The only useful thing it does is + ;; run `c-get-state-before-change-functions' where we normally add + ;; `c-awk-record-region-clear-NL'. + (remove-hook 'before-change-functions #'c-before-change t) + ;; Same thing for `after-change-functions' with `c-after-change' vs + ;; `c-awk-extend-and-syntax-tablify-region' (via + ;; `c-before-font-lock-functions'). + (remove-hook 'after-change-functions #'c-after-change t) + ;; CC-mode setq c-new-BEG/END in `c-after-change' and then uses them in + ;; `font-lock-extend-after-change-region-function'. We don't need that and + ;; additionally we don't maintain c-new-BEG/END any more, so we really need + ;; it out of the way. + (kill-local-variable 'font-lock-extend-after-change-region-function) + ;; Now, setup syntax-propertize. + (add-hook 'syntax-propertize-extend-region-functions + #'c-awk-syntax-propertize-extend-region + nil t) + (set (make-local-variable 'syntax-propertize-function) + #'c-awk-syntax-propertize))) + +\f (provide 'cc-awk) ;;; cc-awk.el ends here === modified file 'lisp/progmodes/cc-mode.el' --- lisp/progmodes/cc-mode.el 2014-09-10 16:32:36 +0000 +++ lisp/progmodes/cc-mode.el 2014-09-11 13:33:16 +0000 @@ -198,24 +183,7 @@ \f ;;; 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))) - ;; Necessary to use `cc-bytecomp-fboundp' below since this - ;; function is called from top-level forms that are evaluated - ;; while cc-bytecomp is active when one does M-x eval-buffer. - (cond - ;; Emacs - ((cc-bytecomp-fboundp 'set-keymap-parent) - (set-keymap-parent map c-mode-base-map)) - ;; XEmacs - ((fboundp 'set-keymap-parents) - (set-keymap-parents map c-mode-base-map)) - ;; incompatible - (t (error "CC Mode is incompatible with this version of Emacs"))) - map)) +(defvar c-mode-base-map) (defun c-define-abbrev-table (name defs &optional doc) ;; Compatibility wrapper for `define-abbrev' which passes a non-nil @@ -236,59 +204,58 @@ (setq defs (cdr defs))))) (put 'c-define-abbrev-table 'lisp-indent-function 1) -(defun c-bind-special-erase-keys () +(defun c-bind-special-erase-keys (&optional map) ;; Only used in Emacs to bind C-c C-<delete> and C-c C-<backspace> ;; to the proper keys depending on `normal-erase-is-backspace'. + (unless map (setq map c-mode-base-map)) (if normal-erase-is-backspace (progn - (define-key c-mode-base-map (kbd "C-c C-<delete>") + (define-key map (kbd "C-c C-<delete>") 'c-hungry-delete-forward) - (define-key c-mode-base-map (kbd "C-c C-<backspace>") + (define-key map (kbd "C-c C-<backspace>") 'c-hungry-delete-backwards)) - (define-key c-mode-base-map (kbd "C-c C-<delete>") + (define-key map (kbd "C-c C-<delete>") 'c-hungry-delete-backwards) - (define-key c-mode-base-map (kbd "C-c C-<backspace>") + (define-key map (kbd "C-c C-<backspace>") 'c-hungry-delete-forward))) -(if c-mode-base-map - nil - - (setq c-mode-base-map (make-sparse-keymap)) +(defvar c-mode-base-map + (let ((map (make-sparse-keymap))) ;; 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) + (define-key map [(control meta h)] 'c-mark-function) + (define-key map "\e\C-q" 'c-indent-exp) (substitute-key-definition 'backward-sentence 'c-beginning-of-statement - c-mode-base-map global-map) + map global-map) (substitute-key-definition 'forward-sentence 'c-end-of-statement - c-mode-base-map global-map) + map global-map) (substitute-key-definition 'indent-new-comment-line 'c-indent-new-comment-line - c-mode-base-map global-map) + map global-map) (substitute-key-definition 'indent-for-tab-command ;; XXX Is this the right thing to do ;; here? 'c-indent-line-or-region - c-mode-base-map global-map) + map global-map) (when (fboundp 'comment-indent-new-line) ;; indent-new-comment-line has changed name to ;; comment-indent-new-line in Emacs 21. (substitute-key-definition 'comment-indent-new-line 'c-indent-new-comment-line - c-mode-base-map global-map)) + map global-map)) ;; RMS says don't make these the default. ;; (April 2006): RMS has now approved these commands as defaults. (unless (memq 'argumentative-bod-function c-emacs-features) - (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 map "\e\C-a" 'c-beginning-of-defun) + (define-key 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) + (define-key map "\C-c\C-n" 'c-forward-conditional) + (define-key map "\C-c\C-p" 'c-backward-conditional) + (define-key map "\C-c\C-u" 'c-up-conditional) ;; It doesn't suffice to put `c-fill-paragraph' on ;; `fill-paragraph-function' since `c-fill-paragraph' must be called @@ -299,11 +266,11 @@ ;; `fill-paragraph' and the value on `fill-paragraph-function' to ;; do the actual filling work. (substitute-key-definition 'fill-paragraph 'c-fill-paragraph - c-mode-base-map global-map) + 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) + map global-map) ;; We bind the forward deletion key and (implicitly) C-d to ;; `c-electric-delete-forward', and the backward deletion key to @@ -320,21 +287,21 @@ ;; automatically maps the [delete] and [backspace] keys to these two ;; depending on window system and user preferences. (In earlier ;; versions it's possible to do the same by using `function-key-map'.) - (define-key c-mode-base-map "\C-d" 'c-electric-delete-forward) - (define-key c-mode-base-map "\177" 'c-electric-backspace) - (define-key c-mode-base-map "\C-c\C-d" 'c-hungry-delete-forward) - (define-key c-mode-base-map [?\C-c ?\d] 'c-hungry-delete-backwards) - (define-key c-mode-base-map [?\C-c ?\C-\d] 'c-hungry-delete-backwards) - (define-key c-mode-base-map [?\C-c deletechar] 'c-hungry-delete-forward) ; C-c <delete> on a tty. - (define-key c-mode-base-map [?\C-c (control deletechar)] ; C-c C-<delete> on a tty. + (define-key map "\C-d" 'c-electric-delete-forward) + (define-key map "\177" 'c-electric-backspace) + (define-key map "\C-c\C-d" 'c-hungry-delete-forward) + (define-key map [?\C-c ?\d] 'c-hungry-delete-backwards) + (define-key map [?\C-c ?\C-\d] 'c-hungry-delete-backwards) + (define-key map [?\C-c deletechar] 'c-hungry-delete-forward) ; C-c <delete> on a tty. + (define-key map [?\C-c (control deletechar)] ; C-c C-<delete> on a tty. 'c-hungry-delete-forward) (when (boundp 'normal-erase-is-backspace) ;; The automatic C-d and DEL mapping functionality doesn't extend ;; to special combinations like C-c C-<delete>, so we have to hook ;; into the `normal-erase-is-backspace' system to bind it directly ;; as appropriate. - (add-hook 'normal-erase-is-backspace-hook 'c-bind-special-erase-keys) - (c-bind-special-erase-keys)) + (add-hook 'normal-erase-is-backspace-hook #'c-bind-special-erase-keys) + (c-bind-special-erase-keys map)) (when (fboundp 'delete-forward-p) ;; In XEmacs we fix the forward and backward deletion behavior by @@ -342,41 +309,42 @@ ;; directly, and use `delete-forward-p' to decide what [delete] ;; should do. That's done in the XEmacs specific ;; `c-electric-delete' and `c-hungry-delete' functions. - (define-key c-mode-base-map [delete] 'c-electric-delete) - (define-key c-mode-base-map [backspace] 'c-electric-backspace) - (define-key c-mode-base-map (kbd "C-c <delete>") 'c-hungry-delete) - (define-key c-mode-base-map (kbd "C-c C-<delete>") 'c-hungry-delete) - (define-key c-mode-base-map (kbd "C-c <backspace>") + (define-key map [delete] 'c-electric-delete) + (define-key map [backspace] 'c-electric-backspace) + (define-key map (kbd "C-c <delete>") 'c-hungry-delete) + (define-key map (kbd "C-c C-<delete>") 'c-hungry-delete) + (define-key map (kbd "C-c <backspace>") 'c-hungry-delete-backwards) - (define-key c-mode-base-map (kbd "C-c C-<backspace>") + (define-key map (kbd "C-c C-<backspace>") 'c-hungry-delete-backwards)) - (define-key c-mode-base-map "#" 'c-electric-pound) - (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-slash) - (define-key c-mode-base-map "*" 'c-electric-star) - (define-key c-mode-base-map ";" 'c-electric-semi&comma) - (define-key c-mode-base-map "," 'c-electric-semi&comma) - (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) - - (define-key c-mode-base-map "\C-c\C-\\" 'c-backslash-region) - (define-key c-mode-base-map "\C-c\C-a" 'c-toggle-auto-newline) - (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-l" 'c-toggle-electric-state) - (define-key c-mode-base-map "\C-c\C-o" 'c-set-offset) - (define-key c-mode-base-map "\C-c\C-q" 'c-indent-defun) - (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) Commented out by ACM, 2005-03-05. - (define-key c-mode-base-map "\C-c." 'c-set-style) + (define-key map "#" 'c-electric-pound) + (define-key map "{" 'c-electric-brace) + (define-key map "}" 'c-electric-brace) + (define-key map "/" 'c-electric-slash) + (define-key map "*" 'c-electric-star) + (define-key map ";" 'c-electric-semi&comma) + (define-key map "," 'c-electric-semi&comma) + (define-key map ":" 'c-electric-colon) + (define-key map "(" 'c-electric-paren) + (define-key map ")" 'c-electric-paren) + + (define-key map "\C-c\C-\\" 'c-backslash-region) + (define-key map "\C-c\C-a" 'c-toggle-auto-newline) + (define-key map "\C-c\C-b" 'c-submit-bug-report) + (define-key map "\C-c\C-c" 'comment-region) + (define-key map "\C-c\C-l" 'c-toggle-electric-state) + (define-key map "\C-c\C-o" 'c-set-offset) + (define-key map "\C-c\C-q" 'c-indent-defun) + (define-key map "\C-c\C-s" 'c-show-syntactic-information) + ;; (define-key map "\C-c\C-t" 'c-toggle-auto-hungry-state) Commented out by ACM, 2005-03-05. + (define-key map "\C-c." 'c-set-style) ;; conflicts with OOBR - ;;(define-key c-mode-base-map "\C-c\C-v" 'c-version) - ;; (define-key c-mode-base-map "\C-c\C-y" 'c-toggle-hungry-state) Commented out by ACM, 2005-11-22. - (define-key c-mode-base-map "\C-c\C-w" 'subword-mode) - ) + ;;(define-key map "\C-c\C-v" 'c-version) + ;; (define-key map "\C-c\C-y" 'c-toggle-hungry-state) Commented out by ACM, 2005-11-22. + (define-key map "\C-c\C-w" 'subword-mode) + map) + "Keymap shared by all CC Mode related modes.") ;; We don't require the outline package, but we configure it a bit anyway. (cc-bytecomp-defvar outline-level) @@ -805,13 +773,6 @@ (add-hook 'before-hack-local-variables-hook 'c-before-hack-hook) (add-hook 'hack-local-variables-hook 'c-postprocess-file-styles)) -(defmacro c-run-mode-hooks (&rest hooks) - ;; Emacs 21.1 has introduced a system with delayed mode hooks that - ;; requires the use of the new function `run-mode-hooks'. - (if (fboundp 'run-mode-hooks) - `(run-mode-hooks ,@hooks) - `(progn ,@(mapcar (lambda (hook) `(run-hooks ,hook)) hooks)))) - \f ;;; Change hooks, linking with Font Lock and electric-indent-mode. @@ -1202,8 +1163,9 @@ (defun c-after-font-lock-init () ;; Put on `font-lock-mode-hook'. This function ensures our after-change ;; function will get executed before the font-lock one. + (when (memq #'c-after-change after-change-functions) (remove-hook 'after-change-functions 'c-after-change t) - (add-hook 'after-change-functions 'c-after-change nil t)) + (add-hook 'after-change-functions 'c-after-change nil t))) (defun c-font-lock-init () "Set up the font-lock variables for using the font-lock support in CC Mode. @@ -1264,6 +1226,30 @@ (c-update-modeline))) \f +(defvar c-mode-common-map c-mode-base-map) + +(define-derived-mode c-mode-common prog-mode "CC-generic" + "Pseudo major mode, parent of all modes using the CC engine." + (c-initialize-cc-mode t) + (setq abbrev-mode t) ;FIXME: Why? + ;; Refresh the modeline flags after running the major mode hooks. + (add-hook 'after-change-major-mode-hook #'c-update-modeline 'append t) + (add-hook 'hack-local-variables-hook #'c-update-modeline 'append t)) + +(defvar c-derivative-mode-map + ;; FIXME: We can't have the menu on this keymap, because the menus for C, + ;; C++, and ObjC can't be shared: the only difference between them is their + ;; title, but easy-menu offers no way to compute the title dynamically. + (let ((map (make-sparse-keymap))) + ;; Add bindings which are useful for any C derivative. + (define-key map "\C-c\C-e" 'c-macro-expand) + map) + "Keymap used in c-derivative-mode buffers.") + +(define-derived-mode c-derivative-mode c-mode-common "C-derivative" + "Pseudo major mode, parent of all modes for C derivatives. +A C derivative is a language which is a superset of C (or is C itself).") + ;; Support for C (defvar c-mode-syntax-table @@ -1276,9 +1262,8 @@ "Abbreviation table used in c-mode buffers.") (defvar c-mode-map - (let ((map (c-make-inherited-keymap))) + (let ((map (make-sparse-keymap))) ;; Add bindings which are only useful for C. - (define-key map "\C-c\C-e" 'c-macro-expand) map) "Keymap used in c-mode buffers.") @@ -1314,9 +1299,8 @@ ;;;###autoload (add-to-list 'auto-mode-alist '("\\.i\\'" . c-mode)) ;;;###autoload (add-to-list 'auto-mode-alist '("\\.ii\\'" . c++-mode)) - ;;;###autoload -(define-derived-mode c-mode prog-mode "C" +(define-derived-mode c-mode c-derivative-mode "C" "Major mode for editing K&R and ANSI C code. To submit a problem report, enter `\\[c-submit-bug-report]' from a c-mode buffer. This automatically sets up a mail buffer with version @@ -1330,18 +1314,11 @@ Key bindings: \\{c-mode-map}" - (c-initialize-cc-mode t) - (set-syntax-table c-mode-syntax-table) - (setq local-abbrev-table c-mode-abbrev-table - abbrev-mode t) - (use-local-map c-mode-map) (c-init-language-vars-for 'c-mode) (c-make-macro-with-semi-re) ; matches macro names whose expansion ends with ; (c-common-init 'c-mode) (easy-menu-add c-c-menu) - (cc-imenu-init cc-imenu-c-generic-expression) - (c-run-mode-hooks 'c-mode-common-hook 'c-mode-hook) - (c-update-modeline)) + (cc-imenu-init cc-imenu-c-generic-expression)) \f ;; Support for C++ @@ -1357,9 +1334,8 @@ "Abbreviation table used in c++-mode buffers.") (defvar c++-mode-map - (let ((map (c-make-inherited-keymap))) + (let ((map (make-sparse-keymap))) ;; Add bindings which are only useful for C++. - (define-key map "\C-c\C-e" 'c-macro-expand) (define-key map "\C-c:" 'c-scope-operator) (define-key map "<" 'c-electric-lt-gt) (define-key map ">" 'c-electric-lt-gt) @@ -1370,7 +1346,7 @@ (cons "C++" (c-lang-const c-mode-menu c++))) ;;;###autoload -(define-derived-mode c++-mode prog-mode "C++" +(define-derived-mode c++-mode c-derivative-mode "C++" "Major mode for editing C++ code. To submit a problem report, enter `\\[c-submit-bug-report]' from a c++-mode buffer. This automatically sets up a mail buffer with @@ -1385,18 +1361,11 @@ Key bindings: \\{c++-mode-map}" - (c-initialize-cc-mode t) - (set-syntax-table c++-mode-syntax-table) - (setq local-abbrev-table c++-mode-abbrev-table - abbrev-mode t) - (use-local-map c++-mode-map) (c-init-language-vars-for 'c++-mode) (c-make-macro-with-semi-re) ; matches macro names whose expansion ends with ; (c-common-init 'c++-mode) (easy-menu-add c-c++-menu) - (cc-imenu-init cc-imenu-c++-generic-expression) - (c-run-mode-hooks 'c-mode-common-hook 'c++-mode-hook) - (c-update-modeline)) + (cc-imenu-init cc-imenu-c++-generic-expression)) \f ;; Support for Objective-C @@ -1411,9 +1380,8 @@ "Abbreviation table used in objc-mode buffers.") (defvar objc-mode-map - (let ((map (c-make-inherited-keymap))) + (let ((map (make-sparse-keymap))) ;; Add bindings which are only useful for Objective-C. - (define-key map "\C-c\C-e" 'c-macro-expand) map) "Keymap used in objc-mode buffers.") @@ -1423,7 +1391,7 @@ ;;;###autoload (add-to-list 'auto-mode-alist '("\\.m\\'" . objc-mode)) ;;;###autoload -(define-derived-mode objc-mode prog-mode "ObjC" +(define-derived-mode objc-mode c-derivative-mode "ObjC" "Major mode for editing Objective C code. To submit a problem report, enter `\\[c-submit-bug-report]' from an objc-mode buffer. This automatically sets up a mail buffer with @@ -1438,18 +1406,11 @@ Key bindings: \\{objc-mode-map}" - (c-initialize-cc-mode t) - (set-syntax-table objc-mode-syntax-table) - (setq local-abbrev-table objc-mode-abbrev-table - abbrev-mode t) - (use-local-map objc-mode-map) (c-init-language-vars-for 'objc-mode) (c-make-macro-with-semi-re) ; matches macro names whose expansion ends with ; (c-common-init 'objc-mode) (easy-menu-add c-objc-menu) - (cc-imenu-init nil 'cc-imenu-objc-function) - (c-run-mode-hooks 'c-mode-common-hook 'objc-mode-hook) - (c-update-modeline)) + (cc-imenu-init nil 'cc-imenu-objc-function)) \f ;; Support for Java @@ -1466,7 +1427,7 @@ "Abbreviation table used in java-mode buffers.") (defvar java-mode-map - (let ((map (c-make-inherited-keymap))) + (let ((map (make-sparse-keymap))) ;; Add bindings which are only useful for Java. map) "Keymap used in java-mode buffers.") @@ -1484,7 +1445,7 @@ ;;;###autoload (add-to-list 'auto-mode-alist '("\\.java\\'" . java-mode)) ;;;###autoload -(define-derived-mode java-mode prog-mode "Java" +(define-derived-mode java-mode c-mode-common "Java" "Major mode for editing Java code. To submit a problem report, enter `\\[c-submit-bug-report]' from a java-mode buffer. This automatically sets up a mail buffer with @@ -1499,17 +1460,10 @@ Key bindings: \\{java-mode-map}" - (c-initialize-cc-mode t) - (set-syntax-table java-mode-syntax-table) - (setq local-abbrev-table java-mode-abbrev-table - abbrev-mode t) - (use-local-map java-mode-map) (c-init-language-vars-for 'java-mode) (c-common-init 'java-mode) (easy-menu-add c-java-menu) - (cc-imenu-init cc-imenu-java-generic-expression) - (c-run-mode-hooks 'c-mode-common-hook 'java-mode-hook) - (c-update-modeline)) + (cc-imenu-init cc-imenu-java-generic-expression)) \f ;; Support for CORBA's IDL language @@ -1522,7 +1476,7 @@ "Abbreviation table used in idl-mode buffers.") (defvar idl-mode-map - (let ((map (c-make-inherited-keymap))) + (let ((map (make-sparse-keymap))) ;; Add bindings which are only useful for IDL. map) "Keymap used in idl-mode buffers.") @@ -1533,7 +1487,7 @@ ;;;###autoload (add-to-list 'auto-mode-alist '("\\.idl\\'" . idl-mode)) ;;;###autoload -(define-derived-mode idl-mode prog-mode "IDL" +(define-derived-mode idl-mode c-mode-common "IDL" "Major mode for editing CORBA's IDL, PSDL and CIDL code. To submit a problem report, enter `\\[c-submit-bug-report]' from an idl-mode buffer. This automatically sets up a mail buffer with @@ -1548,16 +1502,12 @@ Key bindings: \\{idl-mode-map}" - (c-initialize-cc-mode t) - (set-syntax-table idl-mode-syntax-table) - (setq local-abbrev-table idl-mode-abbrev-table) - (use-local-map idl-mode-map) + (kill-local-variable 'abbrev-mode) ;FIXME: Only mode that doesn't enable it!? (c-init-language-vars-for 'idl-mode) (c-common-init 'idl-mode) (easy-menu-add c-idl-menu) ;;(cc-imenu-init cc-imenu-idl-generic-expression) ;TODO - (c-run-mode-hooks 'c-mode-common-hook 'idl-mode-hook) - (c-update-modeline)) + ) \f ;; Support for Pike @@ -1572,7 +1522,7 @@ "Abbreviation table used in pike-mode buffers.") (defvar pike-mode-map - (let ((map (c-make-inherited-keymap))) + (let ((map (make-sparse-keymap))) ;; Additional bindings. (define-key map "\C-c\C-e" 'c-macro-expand) map) @@ -1585,7 +1535,7 @@ ;;;###autoload (add-to-list 'interpreter-mode-alist '("pike" . pike-mode)) ;;;###autoload -(define-derived-mode pike-mode prog-mode "Pike" +(define-derived-mode pike-mode c-mode-common "Pike" "Major mode for editing Pike code. To submit a problem report, enter `\\[c-submit-bug-report]' from a pike-mode buffer. This automatically sets up a mail buffer with @@ -1600,86 +1550,11 @@ Key bindings: \\{pike-mode-map}" - (c-initialize-cc-mode t) - (set-syntax-table pike-mode-syntax-table) - (setq local-abbrev-table pike-mode-abbrev-table - abbrev-mode t) - (use-local-map pike-mode-map) (c-init-language-vars-for 'pike-mode) (c-common-init 'pike-mode) (easy-menu-add c-pike-menu) ;;(cc-imenu-init cc-imenu-pike-generic-expression) ;TODO - (c-run-mode-hooks 'c-mode-common-hook 'pike-mode-hook) - (c-update-modeline)) - -\f -;; Support for AWK - -;;;###autoload (add-to-list 'auto-mode-alist '("\\.awk\\'" . awk-mode)) -;;;###autoload (add-to-list 'interpreter-mode-alist '("awk" . awk-mode)) -;;;###autoload (add-to-list 'interpreter-mode-alist '("mawk" . awk-mode)) -;;;###autoload (add-to-list 'interpreter-mode-alist '("nawk" . awk-mode)) -;;;###autoload (add-to-list 'interpreter-mode-alist '("gawk" . awk-mode)) - -(c-define-abbrev-table 'awk-mode-abbrev-table - '(("else" "else" c-electric-continued-statement 0) - ("while" "while" c-electric-continued-statement 0)) - "Abbreviation table used in awk-mode buffers.") - -(defvar awk-mode-map - (let ((map (c-make-inherited-keymap))) - ;; Add bindings which are only useful for awk. - (define-key map "#" 'self-insert-command) - (define-key map "/" 'self-insert-command) - (define-key map "*" 'self-insert-command) - (define-key map "\C-c\C-n" 'undefined) ; #if doesn't exist in awk. - (define-key map "\C-c\C-p" 'undefined) - (define-key map "\C-c\C-u" 'undefined) - (define-key map "\M-a" 'c-beginning-of-statement) ; 2003/10/7 - (define-key map "\M-e" 'c-end-of-statement) ; 2003/10/7 - (define-key map "\C-\M-a" 'c-awk-beginning-of-defun) - (define-key map "\C-\M-e" 'c-awk-end-of-defun) - map) - "Keymap used in awk-mode buffers.") - -(easy-menu-define c-awk-menu awk-mode-map "AWK Mode Commands" - (cons "AWK" (c-lang-const c-mode-menu awk))) - -;; (require 'cc-awk) brings these in. -(defvar awk-mode-syntax-table) -(declare-function c-awk-unstick-NL-prop "cc-awk" ()) - -;;;###autoload -(define-derived-mode awk-mode prog-mode "AWK" - "Major mode for editing AWK code. -To submit a problem report, enter `\\[c-submit-bug-report]' from an -awk-mode buffer. This automatically sets up a mail buffer with version -information already added. You just need to add a description of the -problem, including a reproducible test case, and send the message. - -To see what version of CC Mode you are running, enter `\\[c-version]'. - -The hook `c-mode-common-hook' is run with no args at mode -initialization, then `awk-mode-hook'. - -Key bindings: -\\{awk-mode-map}" - ;; We need the next line to stop the macro defining - ;; `awk-mode-syntax-table'. This would mask the real table which is - ;; declared in cc-awk.el and hasn't yet been loaded. - :syntax-table nil - (require 'cc-awk) ; Added 2003/6/10. - (c-initialize-cc-mode t) - (set-syntax-table awk-mode-syntax-table) - (setq local-abbrev-table awk-mode-abbrev-table - abbrev-mode t) - (use-local-map awk-mode-map) - (c-init-language-vars-for 'awk-mode) - (c-common-init 'awk-mode) - (c-awk-unstick-NL-prop) - - (c-run-mode-hooks 'c-mode-common-hook 'awk-mode-hook) - (c-update-modeline)) + ) \f ;; bug reporting ^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: Further CC-mode changes 2014-09-11 13:55 ` Further CC-mode changes Stefan Monnier @ 2014-09-12 23:59 ` Alan Mackenzie 2014-09-13 1:09 ` Ivan Andrus 2014-09-13 3:04 ` Stefan Monnier 0 siblings, 2 replies; 41+ messages in thread From: Alan Mackenzie @ 2014-09-12 23:59 UTC (permalink / raw) To: Stefan Monnier; +Cc: emacs-devel Hello, Stefan. On Thu, Sep 11, 2014 at 09:55:29AM -0400, Stefan Monnier wrote: > While waiting for your guidance as to which parts of my patches need to > be reverted and why, here's some candidate patch which (contrary to the > one you reverted) actually changes the code's behavior. > It's to be applied on top of the ones you removed (tho since the ones > you remove are mostly cosmetic, it shouldn't make much of a difference). > Questions: > - should C-c C-n and friends be moved to c-derivative-mode-map > (AFAIK neither Java nor IDL nor Pike have CPP conditionals)? No. Less disruptive is either to remove these bindings from c-mode-base-map and put them in c-mode-map etc., or to splat them out from java-mode-map, etc., as is done in awk-mode-map. This is a bug, I suppose, but a tiny one - attempting C-c C-n in Java Mode throws an error immediately. > - I notice that all cc-mode enable abbrev-mode except for idl-mode. > Was that on purpose or is it just accidental? Probably deliberate. IDL Mode doesn't have keywords like "else", as far as I'm aware. I'm also not aware of anyone using IDL Mode, there having been no bug reports for it for many years, if ever. > - BTW, I think it would be better not to enable abbrev-mode (let it be > a user's choice). IIUC CC-mode relies on abbrev-mode internally > for some of its electric-indent functionality, so we'd have to use > some other approach (e.g. a post-self-insert-hook). I tend to agree, having been a bit disgusted myself when I discovered how "else" and friends were being electrically indented. after-change-functions might be better here, since it's more general, and also better supported. > This is not really tested, especially not on XEmacs, but AFAIK it > doesn't depend on any feature specific to a particular Emacs version. "This"?? > Stefan > - Move awk-mode's actual definition to cc-awk so as to get rid of the > (require 'cc-awk) and the ":syntax-table nil" hack. Would leave traps for maintainers, and break uniformity between the modes. Putting all the mode defuns together was a deliberate decision, though I can't remember whether it was Martin or me that made it. This change wouldn't enhance functionality or maintainability. > - make awk-mode use syntax-propertize when available. Why? It's a lot of work to change, syntax-propertize is only available in relatively recent versions of GNU Emacs, and the documentation suggests that syntax-propertize is not called after buffer changes in general, the documentation not being entirely clear on this point. This change wouldn't enhance functionality or maintainability. > - Use define-derived-mode's built-in keymap inheritance rather than > c-make-inherited-keymap. c-make-inherited-keymap is simpler. This change wouldn't enhance functionality or maintainability. > - initialize c-mode-base-map in its defvar. An inconsequential change that wouldn't enhance functionality or maintainability. It's work to make, though. > - fix c-after-font-lock-init so it doesn't accidentally add > a c-after-change which wasn't there to begin with. ??? There's nothing broken here, surely? > - Run c-update-modeline from after-change-major-mode-hook and > hack-local-variables-hook rather than from the major mode function. > This lets us fix the bug where c-mode-hook is run twice and saves us > from having to define c-run-mode-hooks. after-change-major-mode-hook is a GNU Emacs speciality. The major mode functions (and several commands, of course) are the natural places to call c-update-modeline from. How about enhancing define-derived-mode so that modes that have things to do after running their hooks can do them? That would surely be a simple change? > - make c-mode-common into an actual parent mode. There is a naming problem > since we have c-mode-base-map for the "parent map" but > c-mode-common-hook for the "parent hook", and also because this "mode" > doesn't end in "-mode", but I think we can live with it. Why? There is no such mode c-mode-common; nobody's ever going to have a buffer in this mode; it would merely be a software-engineeringy way of achieving... what? It would add complexity where none is warranted. > - add a new parent mode c-derivative-mode which can hold those things > common to c, c++, and objc (i.e. languages which include C as a subset). > I was tempted to simply use c-mode as the parent for c++-mode and > objc-mode, but this would be a lot more intrusive and it would force > the presence of a "C" menu in both C++ and ObjC modes (we could fix > that for Emacs, but I'm not sure how to do it for XEmacs, and it > doesn't seem worth the trouble). Why? What complixity would c-derivative-mode save that would justify its existence? I think your last clause is true for the entire paragraph. [ Snipped ~750 lines of patch. ] In that patch, your assumptions about what AWK Mode needs in c-{before,after}-change were incorrect. There are likely other bugs in the patch too. Remember, a previous, "simple, cosmetic" change, using define-derived-mode to derive CC Mode's modes from prog-mode, introduced two bugs, each of which took several hours to track down. One of these is still unfixed. It has taken me several hours to study your email and answer it. Your patch is all about rearranging the deckchairs around the cruise ship's pool when the engines need looking at. It's trying to fix what's not broken. It would not contribute one single thing to fixing the many things in CC Mode which need fixing. On the contrary, it would act as a distraction, merely consuming lots more of my time reconciling these changes with the stand-alone CC Mode. In the mean time, there are several reported bugs not being fixed, and the enhancements needed for, e.g., C++11 are not progressing. The time I can spend on Emacs and CC Mode is much less than both of us would like. What needs attending to in CC Mode is NOT its embedding within X?Emacs and it's definitely NOT the lang-var system, which works just fine. It's the complexity in c-guess-basic-syntax, in c-font-lock-declarations, c-forward-type, c-forward-decl-or-cast-1, and many other such functions, and the difficulties this causes. Exasperated, -- Alan Mackenzie (Nuremberg, Germany). ^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: Further CC-mode changes 2014-09-12 23:59 ` Alan Mackenzie @ 2014-09-13 1:09 ` Ivan Andrus 2014-09-13 10:04 ` Alan Mackenzie 2014-09-13 3:04 ` Stefan Monnier 1 sibling, 1 reply; 41+ messages in thread From: Ivan Andrus @ 2014-09-13 1:09 UTC (permalink / raw) To: Alan Mackenzie; +Cc: Stefan Monnier, emacs-devel On Sep 12, 2014, at 5:59 PM, Alan Mackenzie <acm@muc.de> wrote: > Hello, Stefan. > > On Thu, Sep 11, 2014 at 09:55:29AM -0400, Stefan Monnier wrote: >> While waiting for your guidance as to which parts of my patches need to >> be reverted and why, here's some candidate patch which (contrary to the >> one you reverted) actually changes the code's behavior. > >> It's to be applied on top of the ones you removed (tho since the ones >> you remove are mostly cosmetic, it shouldn't make much of a difference). > >> Questions: >> - should C-c C-n and friends be moved to c-derivative-mode-map >> (AFAIK neither Java nor IDL nor Pike have CPP conditionals)? > > No. Less disruptive is either to remove these bindings from > c-mode-base-map and put them in c-mode-map etc., or to splat them out > from java-mode-map, etc., as is done in awk-mode-map. This is a bug, I > suppose, but a tiny one - attempting C-c C-n in Java Mode throws an error > immediately. > >> - I notice that all cc-mode enable abbrev-mode except for idl-mode. >> Was that on purpose or is it just accidental? > > Probably deliberate. IDL Mode doesn't have keywords like "else", as far > as I'm aware. I'm also not aware of anyone using IDL Mode, there having > been no bug reports for it for many years, if ever. FWIW I created slice-mode (for the ZeroC Slice language [1]) derived from IDL mode. It’s only in my .emacs right now since it’s so trivial. It’s not perfect, but good enough for the few times I actually have to edit the files (they define interfaces and are therefore quite stable). -Ivan [1] http://doc.zeroc.com/display/Ice/The+Slice+Language (define-derived-mode slice-mode idl-mode "Slice" "This is a mode for editing slice (Ice definition) files. It is based on idl-mode because of the comment at http://www.zeroc.com/forums/help-center/818-any-editor-slice-syntax-highlight.html I haven't been able to determine the differences between slice and idl, so I don't know how good it is." (font-lock-add-keywords 'slice-mode `( (,(concat "\\<\\(" (regexp-opt '("Object" "LocalObject" "exception" "interface" "idempotent")) "\\)\\> ") 1 font-lock-keyword-face t) ("^! .*" 0 font-lock-warning-face t) ;; Reserved names ("\\(Ice\\w*\\)" 1 font-lock-builtin-face) ,(concat "\\<\\(\\w*" (regexp-opt '("Helper" "Holder" "Prx" "Ptr")) "\\)\\> ") ;; Built-in types ,(concat "\\<\\(\\w*" (regexp-opt '("bool" "byte" "short" "int" "long" "float" "double" "string")) "\\)\\> ") ))) ^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: Further CC-mode changes 2014-09-13 1:09 ` Ivan Andrus @ 2014-09-13 10:04 ` Alan Mackenzie 0 siblings, 0 replies; 41+ messages in thread From: Alan Mackenzie @ 2014-09-13 10:04 UTC (permalink / raw) To: Ivan Andrus; +Cc: Stefan Monnier, emacs-devel Hi, Ivan. On Fri, Sep 12, 2014 at 07:09:18PM -0600, Ivan Andrus wrote: > On Sep 12, 2014, at 5:59 PM, Alan Mackenzie <acm@muc.de> wrote: > > IDL Mode doesn't have keywords like "else", as far as I'm aware. I'm > > also not aware of anyone using IDL Mode, there having been no bug > > reports for it for many years, if ever. > FWIW I created slice-mode (for the ZeroC Slice language [1]) derived > from IDL mode. It’s only in my .emacs right now since it’s so trivial. > It’s not perfect, but good enough for the few times I actually have to > edit the files (they define interfaces and are therefore quite stable). Hey, that's great! That removes any temptation I might have had just to expunge IDL from CC Mode. > -Ivan -- Alan Mackenzie (Nuremberg, Germany). ^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: Further CC-mode changes 2014-09-12 23:59 ` Alan Mackenzie 2014-09-13 1:09 ` Ivan Andrus @ 2014-09-13 3:04 ` Stefan Monnier 2014-09-13 15:10 ` Alan Mackenzie 1 sibling, 1 reply; 41+ messages in thread From: Stefan Monnier @ 2014-09-13 3:04 UTC (permalink / raw) To: Alan Mackenzie; +Cc: emacs-devel >> - BTW, I think it would be better not to enable abbrev-mode (let it be >> a user's choice). IIUC CC-mode relies on abbrev-mode internally >> for some of its electric-indent functionality, so we'd have to use >> some other approach (e.g. a post-self-insert-hook). > I tend to agree, having been a bit disgusted myself when I discovered how > "else" and friends were being electrically indented. > after-change-functions might be better here, since it's more general, and > also better supported. I think "more general" is a disadvantage in this case (I'd rather not have auto-indentation after I paste a space). As for better supported, I don't care too much: I'd just keep the old abbrev code for the Emacsen that don't have post-self-insert-hook yet. >> This is not really tested, especially not on XEmacs, but AFAIK it >> doesn't depend on any feature specific to a particular Emacs version. > "This"?? The patch. >> - Move awk-mode's actual definition to cc-awk so as to get rid of the >> (require 'cc-awk) and the ":syntax-table nil" hack. > Would leave traps for maintainers, Such as? > and break uniformity between the modes. Actually, I think the right move would be to move all awk-related code into cc-awk.el, thus making it more uniform with the various externally maintained cc-modes. > This change wouldn't enhance functionality or maintainability. The code is cleaner and simpler with the change than without. >> - make awk-mode use syntax-propertize when available. > Why? You know why: `syntax-propertize' is used by all major modes except cc-mode derived ones. And it's more efficient, because it's more lazy. Also its correctness argument is much simpler since it doesn't rely on interactions between before-change-functions, after-change-functions (and font-lock), contrary to your code. > It's a lot of work to change, It's work I did, pro bono. Just enjoy it. > syntax-propertize is only available in relatively recent versions of > GNU Emacs, and the documentation suggests that syntax-propertize is > not called after buffer changes in general, the documentation not > being entirely clear on this point. Indeed it's not. If you want to be sure that syntax properties have been applied upto POS, you need to call (syntax-propertize POS). > This change wouldn't enhance functionality or maintainability. Yes, it enhances maintainability of awk-mode by making it work more like all other modes. It also stops cc-mode from doing all kinds of weird unrelated crap having to do with maintaining c-found-types and c-state-cache, which are not used in cc-awk. >> - Use define-derived-mode's built-in keymap inheritance rather than >> c-make-inherited-keymap. > c-make-inherited-keymap is simpler. Huh? Have you even looked at the patch? There is nothing to do to use define-derived-mode's built-in keymap inheritance, so how can your extra code be simpler? > This change wouldn't enhance functionality or maintainability. It removes unneeded code. That improves maintainability. >> - initialize c-mode-base-map in its defvar. > An inconsequential change that wouldn't enhance functionality or > maintainability. It's work to make, though. It just makes code more standard, with no known downside. >> - fix c-after-font-lock-init so it doesn't accidentally add >> a c-after-change which wasn't there to begin with. > ??? There's nothing broken here, surely? The current code of c-after-font-lock-init has a bug, but no the current cc-mode does not trigger this bug. The bug is that c-after-font-lock-init is supposed to *move* c-after-change to the front of after-change-functions, but in case c-after-change is not in after-change-functions, it ends up *adding* it instead. Your approach to syntax-table properties requires you to be extra careful about ordering between c-after-change and font-lock's own after-change-functions, hence the c-after-font-lock-inithack. But if for some reason some cc-mode (such as cc-awk when it uses syntax-propertize) does not need/want c-after-change, the current code in c-after-font-lock-init will end up making it needlessly difficult to remove c-after-change from after-change-functions. >> - Run c-update-modeline from after-change-major-mode-hook and >> hack-local-variables-hook rather than from the major mode function. >> This lets us fix the bug where c-mode-hook is run twice and saves us >> from having to define c-run-mode-hooks. > after-change-major-mode-hook is a GNU Emacs speciality. That's why I also do it from hack-local-variables-hook. > How about enhancing define-derived-mode so that modes that have things > to do after running their hooks can do them? That's not late enough, since you need to do it after setting the file-local variables. In this particular case, the better fix would be to introduce a new `mode-name-sidekick' in the mode-line-format, so we can get rid of c-update-modeline altogether. >> - make c-mode-common into an actual parent mode. There is a naming problem >> since we have c-mode-base-map for the "parent map" but >> c-mode-common-hook for the "parent hook", and also because this "mode" >> doesn't end in "-mode", but I think we can live with it. > Why? Why not? > There is no such mode c-mode-common; nobody's ever going to have a > buffer in this mode; it would merely be a software-engineeringy way of > achieving... what? It would add complexity where none is warranted. What complexity? It reduces code duplication, if anything. > In that patch, your assumptions about what AWK Mode needs in > c-{before,after}-change were incorrect. Could you help me understand what I missed? > There are likely other bugs in the patch too. Remember, a previous, > "simple, cosmetic" change, using define-derived-mode to derive CC > Mode's modes from prog-mode, introduced two bugs, each of which took > several hours to track down. One of these is still unfixed. I admit to not remembering, especially not the remaining bug due to using prog-mode. Can you remind us which bug this is? > It has taken me several hours to study your email and answer it. Your > patch is all about rearranging the deckchairs around the cruise ship's > pool when the engines need looking at. Any package always has several problems that need fixing. Just because a change doesn't fix what you see as the main problem doesn't mean it should be rejected. My overall aim is to make cc-modes more "standard" so as to lower the entry barrier for other people. I also want to make it more modular, which I thought I'd start by moving all the awk functionality out of the generic part of the code and into cc-awk. > It's trying to fix what's not broken. I'm not sure what other people on this list feel like w.r.t cc-mode, but personally so far my attitude has been to close my eyes and pinch my nose while forwarding the bugs to you because the code is so horrendously outlandish, messy, and outdated. > It would not contribute one single thing to fixing the many things in > CC Mode which need fixing. On the contrary, it would act as > a distraction, merely consuming lots more of my time reconciling these > changes with the stand-alone CC Mode. The problem here is not my changes, it's having those two separate code bases. There is no good reason to have 2 different code bases. So let's fix this problem once and for all by merging the two and then make sure they can't diverge any more (i.e. by using the Emacs code as the place where development happens). > In the mean time, there are several reported bugs not being fixed, and > the enhancements needed for, e.g., C++11 are not progressing. The time I > can spend on Emacs and CC Mode is much less than both of us would like. On the one hand you say that you don't have enough time to deal with CC-mode, and on the other you reject the rare patches sent your way. If you prefer that I keep just forwarding bug-reports to you and never ever again look at cc-mode, I can do that. But if you want help, you'll need to be a bit more flexible. > What needs attending to in CC Mode is NOT its embedding within X?Emacs > and it's definitely NOT the lang-var system, which works just fine. It's > the complexity in c-guess-basic-syntax, in c-font-lock-declarations, > c-forward-type, c-forward-decl-or-cast-1, and many other such functions, > and the difficulties this causes. One thing at a time. Stefan ^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: Further CC-mode changes 2014-09-13 3:04 ` Stefan Monnier @ 2014-09-13 15:10 ` Alan Mackenzie 2014-09-13 19:24 ` Stefan Monnier 2014-09-15 20:24 ` Further CC-mode changes Glenn Morris 0 siblings, 2 replies; 41+ messages in thread From: Alan Mackenzie @ 2014-09-13 15:10 UTC (permalink / raw) To: Stefan Monnier; +Cc: emacs-devel Hello, Stefan. Sorry I was a bit vague about one or two things last night. I'll try and clear them up. On Fri, Sep 12, 2014 at 11:04:26PM -0400, Stefan Monnier wrote: > >> - BTW, I think it would be better not to enable abbrev-mode (let it be > >> a user's choice). IIUC CC-mode relies on abbrev-mode internally > >> for some of its electric-indent functionality, so we'd have to use > >> some other approach (e.g. a post-self-insert-hook). > > I tend to agree, having been a bit disgusted myself when I discovered how > > "else" and friends were being electrically indented. > > after-change-functions might be better here, since it's more general, and > > also better supported. > I think "more general" is a disadvantage in this case (I'd rather not > have auto-indentation after I paste a space). > As for better supported, I don't care too much: I'd just keep the old > abbrev code for the Emacsen that don't have post-self-insert-hook yet. Yes. That's a bit messy, though. But I think one could legitimately categorise the mandatory enablement of abbreviation mode as a bug. [ ... ] > >> - Move awk-mode's actual definition to cc-awk so as to get rid of the > >> (require 'cc-awk) and the ":syntax-table nil" hack. > > Would leave traps for maintainers, > Such as? A change to all of c-mode, c++-mode, ....., pike-mode. There's a danger that the maintainer will forget awk-mode, since it's not there any more. > > and break uniformity between the modes. > Actually, I think the right move would be to move all awk-related code > into cc-awk.el, thus making it more uniform with the various externally > maintained cc-modes. Another simplification would be simply to load cc-awk.elc along with the rest of CC Mode, on the grounds that the 19k file is no longer big enough to worry about on modern machines with gigabytes of RAM. > > This change wouldn't enhance functionality or maintainability. > The code is cleaner and simpler with the change than without. Yes, maybe, but.... > >> - make awk-mode use syntax-propertize when available. > > Why? > You know why: `syntax-propertize' is used by all major modes except > cc-mode derived ones. And it's more efficient, because it's more lazy. Lazy? Does C-M-f, for example, trigger syntax-propertize in any way? > Also its correctness argument is much simpler since it doesn't rely on > interactions between before-change-functions, after-change-functions > (and font-lock), contrary to your code. The argument could run that because syntax-propertize doesn't take account of these subleties, its actions aren't always correct. But ... syntax-propertize isn't documented in the Elisp manual. It's unclear when it gets called (in relation to after-change-functions, for example) and even _if_ it always gets called (e.g. when font-lock isn't enabled). Adapting code to use it is thus a _massive_ amount of work - it involves reading the source code for syntax-propertize and friends to work out what it does. I suspect that for a mode which needs syntax-table text properties early in its after-change-functions, syntax-properties wouldn't work. I don't think CC Mode comes into that category (though I'm not sure). > > It's a lot of work to change, > It's work I did, pro bono. Just enjoy it. No, you haven't. What's the equivalent of `syntax-propertize' in XEmacs, or an old GNU Emacs? "Somebody" (tm) has to write a compatibility macro which will look something like this: (defmacro c-set-syntax-propertize (f) (if (boundp 'syntax-propertize-function) `(setq syntax-propertize-function ,f) `(???? ))) What exactly goes in "????"? So many changes you want to make are of this nature - using new facilities of Emacs to replace something which works fine anyhow, and then leaving somebody else, me, to take care of backwards and XEmacs compatibility. > > syntax-propertize is only available in relatively recent versions of > > GNU Emacs, and the documentation suggests that syntax-propertize is > > not called after buffer changes in general, the documentation not > > being entirely clear on this point. What I meant here was it is not clear when (or even whether) syntax-propertize gets called when font-lock is not enabled. If s-p is not called with disabled font-lock, I think you should state this explicitly somewhere in the Elisp manual and/or doc string (or fix the problem and then document the fixed function). > Indeed it's not. If you want to be sure that syntax properties have > been applied upto POS, you need to call (syntax-propertize POS). Right. So I'm now going to have three alternative code flows in place of the one I currently have: (i) One flow for when font lock's enabled; (ii) one for when FL is disabled, which explicitly calls syntax-propertize from after-change-functions; (iii) one for Emacsen lacking syntax-propertize. I've already got (iii). I think you're asking me to add (i) and (ii). This is an increase in complexity and a lot of work. > > This change wouldn't enhance functionality or maintainability. > Yes, it enhances maintainability of awk-mode by making it work more like > all other modes. It also stops cc-mode from doing all kinds of weird > unrelated crap having to do with maintaining c-found-types and > c-state-cache, which are not used in cc-awk. c-state-cache IS used in AWK; it's used in all CC Mode modes and is fundamental to parsing braces etc. c-found-types isn't, since there are no types in AWK. Probably the neatest solution here would be to move the c-found-types stuff into its own function, called via the `c-get-state-before-change-functions' mechanism, or similar. > >> - Use define-derived-mode's built-in keymap inheritance rather than > >> c-make-inherited-keymap. > > c-make-inherited-keymap is simpler. > Huh? Have you even looked at the patch? There is nothing to do to use > define-derived-mode's built-in keymap inheritance, so how can your extra > code be simpler? OK, maybe it's not that bad. define-derived-mode does exist in (at least) newer versions of XEmacs. But it seems to mean having at least one "artificial" mode which will add to complexity. define-derived-mode is a complicated macro, with so many implicit things, that often the only way to see what it does is with `macroexpand'. > > This change wouldn't enhance functionality or maintainability. > It removes unneeded code. That improves maintainability. > >> - initialize c-mode-base-map in its defvar. > > An inconsequential change that wouldn't enhance functionality or > > maintainability. It's work to make, though. > It just makes code more standard, with no known downside. But with no upside either. The downside, as already said, is the work involved in doing it and propagating the change to stand alone CC Mode. > >> - fix c-after-font-lock-init so it doesn't accidentally add > >> a c-after-change which wasn't there to begin with. > > ??? There's nothing broken here, surely? > The current code of c-after-font-lock-init has a bug, but no the current > cc-mode does not trigger this bug. > The bug is that c-after-font-lock-init is supposed to *move* > c-after-change to the front of after-change-functions, but in case > c-after-change is not in after-change-functions, it ends up *adding* > it instead. In CC Mode, c-after-change IS on after-change-functions. This is fundamental. There is no situation in which this can't be the case. > Your approach to syntax-table properties requires you to be extra > careful about ordering between c-after-change and font-lock's own > after-change-functions, hence the c-after-font-lock-inithack. But if > for some reason some cc-mode (such as cc-awk when it uses > syntax-propertize) does not need/want c-after-change, the current code > in c-after-font-lock-init will end up making it needlessly difficult to > remove c-after-change from after-change-functions. See above. I really can't foresee any circumstances where a CC Mode mode won't need before and after change functions. Both c-before-change and c-after-change are equipped with a mechanism to have mode dependent functions called. Maybe a little more modularisation using these facilities wouldn't go amiss. > >> - Run c-update-modeline from after-change-major-mode-hook and > >> hack-local-variables-hook rather than from the major mode function. > >> This lets us fix the bug where c-mode-hook is run twice and saves us > >> from having to define c-run-mode-hooks. > > after-change-major-mode-hook is a GNU Emacs speciality. > That's why I also do it from hack-local-variables-hook. > > How about enhancing define-derived-mode so that modes that have things > > to do after running their hooks can do them? > That's not late enough, since you need to do it after setting the > file-local variables. How about doing it anyway? A major mode incorporating user changes made in its mode hook into its current state is a reasonable thing to expect to do. > In this particular case, the better fix would be to introduce a new > `mode-name-sidekick' in the mode-line-format, so we can get rid of > c-update-modeline altogether. I don't think XEmacs has the capability of running functions from mode line format elements. I looked, once. > >> - make c-mode-common into an actual parent mode. There is a naming problem > >> since we have c-mode-base-map for the "parent map" but > >> c-mode-common-hook for the "parent hook", and also because this "mode" > >> doesn't end in "-mode", but I think we can live with it. > > Why? > Why not? From a user point of view there is no "mode" here - artificially introducing it would merely create confusion. > > There is no such mode c-mode-common; nobody's ever going to have a > > buffer in this mode; it would merely be a software-engineeringy way of > > achieving... what? It would add complexity where none is warranted. > What complexity? It reduces code duplication, if anything. The complexity is in having a deep inheritance tree of modes and "modes". The number of duplicated code lines is of the order of 2 or 3, or maybe 5 or 6. Originally C Mode was simply a defun. Now it's got prog-mode as a super-mode. You're advocating inserting another one or two (I'm a bit confused as to which) modes into that tree. This might be OK if those modes had a coherent meaning (as prog-mode does), but it seems that they do not. _That_ is complexity. What makes code difficult to read is always "having to look somewhere else". Your approach will split (the function) c-mode into two or three fragments, making readers and maintainers have to deal with these two or three bits. > > In that patch, your assumptions about what AWK Mode needs in > > c-{before,after}-change were incorrect. > Could you help me understand what I missed? Already dealt with. At the very least, AWK Mode uses c-parse-state and thus needs its before-change function. > > There are likely other bugs in the patch too. Remember, a previous, > > "simple, cosmetic" change, using define-derived-mode to derive CC > > Mode's modes from prog-mode, introduced two bugs, each of which took > > several hours to track down. One of these is still unfixed. > I admit to not remembering, especially not the remaining bug due to > using prog-mode. Can you remind us which bug this is? The two bugs were the double calling of the mode hooks, and the splatting of AWK Mode syntax table by define-derived-mode defvar'ing awk-mode-syntax-table itself. > > It has taken me several hours to study your email and answer it. Your > > patch is all about rearranging the deckchairs around the cruise ship's > > pool when the engines need looking at. > Any package always has several problems that need fixing. Just because > a change doesn't fix what you see as the main problem doesn't mean it > should be rejected. My overall aim is to make cc-modes more "standard" > so as to lower the entry barrier for other people. I also want to make > it more modular, which I thought I'd start by moving all the awk > functionality out of the generic part of the code and into cc-awk. As discussed above, you're swapping one problem for another. All the entry points to CC Mode are in cc-mode.el. You'd lose that unity. As already suggested, maybe simply loading cc-awk.elc all the time would be best. > > It's trying to fix what's not broken. > I'm not sure what other people on this list feel like w.r.t cc-mode, but > personally so far my attitude has been to close my eyes and pinch my > nose while forwarding the bugs to you because the code is so > horrendously outlandish, messy, and outdated. It's outlandish and messy, yes, because it's 30 years old and handles a multiplicity of complicated languages. Are there any other Emacs modes which handle many variants on a theme, like C, C++, Java, ...? Your solution to the messiness and outdatedness is to use Emacs's newest facilities, rendering the code base in need of heavy adaptation to run elsewhere. That's not a solution. > > It would not contribute one single thing to fixing the many things in > > CC Mode which need fixing. On the contrary, it would act as > > a distraction, merely consuming lots more of my time reconciling these > > changes with the stand-alone CC Mode. > The problem here is not my changes, .... But the problem _is_ your changes. You would quite happily have committed your patch despite not realising it breaks AWK Mode. It's not reasonable to expect that you, the maintainer of Emacs as a whole, should be familiar with the last nuance of every bit of code in the system. What you want to change in CC Mode needs to be checked (just as something I might want to change in syntax.c or font lock needs checking). > ... it's having those two separate code bases. There is no good reason > to have 2 different code bases. In times past, the CC Mode code base was the primary one, and the number of changes to CC Mode made directly in savannah was small. The latter has changed in recent years. > So let's fix this problem once and for all by merging the two and then > make sure they can't diverge any more (i.e. by using the Emacs code as > the place where development happens). Then XEmacs and backward compatibility would inevitably disappear, destroyed by the inexorable creeping use of GNU Emacs only facilities. I'm not sure how you'd feel about the CC Mode version in savannah being a portable one and remaining so. You seem very unhappy about a lot of the portable coding in CC Mode. > > In the mean time, there are several reported bugs not being fixed, and > > the enhancements needed for, e.g., C++11 are not progressing. The time I > > can spend on Emacs and CC Mode is much less than both of us would like. > On the one hand you say that you don't have enough time to deal with > CC-mode, and on the other you reject the rare patches sent your way. These rare patches tend to be buggy and take a lot of time to check, and they tend to address "non-functional" issues. If the patch came in an email with Subject: "Proposed fix for bug #23456", as one did within the last fortnight (and also the one from Daniel Colascione in May), I'd be very much happier. > If you prefer that I keep just forwarding bug-reports to you and never > ever again look at cc-mode, I can do that. But if you want help, you'll > need to be a bit more flexible. > > What needs attending to in CC Mode is NOT its embedding within X?Emacs > > and it's definitely NOT the lang-var system, which works just fine. It's > > the complexity in c-guess-basic-syntax, in c-font-lock-declarations, > > c-forward-type, c-forward-decl-or-cast-1, and many other such functions, > > and the difficulties this causes. > One thing at a time. :-) > Stefan -- Alan Mackenzie (Nuremberg, Germany). ^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: Further CC-mode changes 2014-09-13 15:10 ` Alan Mackenzie @ 2014-09-13 19:24 ` Stefan Monnier 2014-09-13 23:08 ` Syntax-propertize and CC-mode [Was: Further CC-mode changes] Alan Mackenzie 2014-09-16 17:30 ` Sync'ing cc-mode Stefan Monnier 2014-09-15 20:24 ` Further CC-mode changes Glenn Morris 1 sibling, 2 replies; 41+ messages in thread From: Stefan Monnier @ 2014-09-13 19:24 UTC (permalink / raw) To: Alan Mackenzie; +Cc: emacs-devel > A change to all of c-mode, c++-mode, ....., pike-mode. There's a danger > that the maintainer will forget awk-mode, since it's not there any more. The same already applies to the dozen externally maintained modes that use the cc-mode engine. Making cc-awk more like those modes would actually help make sure the modularization is done right (or at least, "right enough for AWK"). > Another simplification would be simply to load cc-awk.elc along with the > rest of CC Mode, on the grounds that the 19k file is no longer big enough > to worry about on modern machines with gigabytes of RAM. I don't see why that would help or what it would simplify. >> You know why: `syntax-propertize' is used by all major modes except >> cc-mode derived ones. And it's more efficient, because it's more lazy. > Lazy? Does C-M-f, for example, trigger syntax-propertize in any way? Not yet, no. >> Also its correctness argument is much simpler since it doesn't rely on >> interactions between before-change-functions, after-change-functions >> (and font-lock), contrary to your code. > The argument could run that because syntax-propertize doesn't take > account of these subleties, its actions aren't always correct. But ... > syntax-propertize isn't documented in the Elisp manual. It's unclear > when it gets called (in relation to after-change-functions, for example) > and even _if_ it always gets called (e.g. when font-lock isn't enabled). That's because it's irrelevant: if *you* need the properties to be applied, then call (syntax-propertize POS). If they've already been applied, then this will return immediately. Since font-lock's syntactic fontification needs those properties to be applied, it does call syntax-propertize. Similarly, indent-according-to-mode calls it since it's usually a good idea. And yes, C-M-f should too, tho noone has been sufficiently bothered by it to implement it yet. > Adapting code to use it is thus a _massive_ amount of work - it involves > reading the source code for syntax-propertize and friends to work out > what it does. No you don't: the contract is just what I stated above and you don't need to know more than that. > I suspect that for a mode which needs syntax-table text properties > early in its after-change-functions, syntax-properties wouldn't work. Suspect all you want. But I assure you it works just fine. >> > It's a lot of work to change, >> It's work I did, pro bono. Just enjoy it. > No, you haven't. What's the equivalent of `syntax-propertize' in XEmacs, > or an old GNU Emacs? Did you look at my patch? It only uses syntax-propertize when available. When not, it keeps using your old code. And the bulk of the code is shared between the two cases. > Right. So I'm now going to have three alternative code flows in place of > the one I currently have: (i) One flow for when font lock's enabled; (ii) > one for when FL is disabled, which explicitly calls syntax-propertize > from after-change-functions; (iii) one for Emacsen lacking > syntax-propertize. I've already got (iii). I think you're asking me to > add (i) and (ii). This is an increase in complexity and a lot of work. There are many different ways to handle backward compatibility. You can do it as above (where my position would be to simply keep the current code for the old Emacsen that don't have syntax-propertize, so while there are more different ways to work than you'd like the old ways have been tested and there's no reason they should stop working, so you can largely ignore them). Or you can provide you own implementation of syntax-propertize. It's actually simple. If you prefer this route, I can do that as well. >> > This change wouldn't enhance functionality or maintainability. >> Yes, it enhances maintainability of awk-mode by making it work more like >> all other modes. It also stops cc-mode from doing all kinds of weird >> unrelated crap having to do with maintaining c-found-types and >> c-state-cache, which are not used in cc-awk. > c-state-cache IS used in AWK; it's used in all CC Mode modes and is > fundamental to parsing braces etc. Hmmm... I didn't notice it in my tests. I guess it only shows up if you really go around editing the test such that the cache becomes stale? OK, I'll rework my syntax-propertize patch accordingly. > OK, maybe it's not that bad. define-derived-mode does exist in (at > least) newer versions of XEmacs. But it seems to mean having at least > one "artificial" mode which will add to complexity. define-derived-mode > is a complicated macro, with so many implicit things, that often the only > way to see what it does is with `macroexpand'. The behavior I rely upon existed in define-derived-mode long before I started I mess with it for Emacs-21. You already have an "artificial" parent mode. Its hook is called c-mode-common-hook its keymap is called c-mode-base-map, its name for c-lang-defconst is `t', its name for c-fallback-mode' is nil. Its standard practice in OO to have a parent which is not a "real" class (because it doesn't have instances), but is only present so that various classes can share a common parent. This is just the same. > See above. I really can't foresee any circumstances where a CC Mode mode > won't need before and after change functions. syntax-propertize uses a before-change-function to "flush the cache", of course. After that you just call it when you need it. E.g. If font-lock itself doesn't call it, then we'll need to arrange to run it before font-lock does its thing. > How about doing it anyway? A major mode incorporating user changes made > in its mode hook into its current state is a reasonable thing to expect > to do. Yes, but usually those modes, just like CC-mode, need to do that after setting up file-local variables. So using hack-local-variables-hook is really not a bad option. >> In this particular case, the better fix would be to introduce a new >> `mode-name-sidekick' in the mode-line-format, so we can get rid of >> c-update-modeline altogether. > I don't think XEmacs has the capability of running functions from mode > line format elements. I looked, once. Your mode-line elements are sufficiently simple that there's no need to run functions. An element like: (c-electric-flag ("/l" (c-auto-newline "a") (c-hungry-delete-key "h") (subword-mode "w")) (c-hungry-delete-key ("/h" (subword-mode "w"))) (subword-mode "/w")) should work just fine in XEmacs as well. > The complexity is in having a deep inheritance tree of modes and "modes". That lets users configure their CC-mode more easily: they can add a single keybinding (or hook function) that'll appear in C, C++, and ObjC. >> > There are likely other bugs in the patch too. Remember, a previous, >> > "simple, cosmetic" change, using define-derived-mode to derive CC >> > Mode's modes from prog-mode, introduced two bugs, each of which took >> > several hours to track down. One of these is still unfixed. >> I admit to not remembering, especially not the remaining bug due to >> using prog-mode. Can you remind us which bug this is? > The two bugs were the double calling of the mode hooks, and the splatting > of AWK Mode syntax table by define-derived-mode defvar'ing > awk-mode-syntax-table itself. Ah, right, then: both are fixed by my patch. That's the advantage of using "standard coding practices" which have been tried and tested in many other modes already. > As discussed above, you're swapping one problem for another. All the > entry points to CC Mode are in cc-mode.el. I don't see d-mode's entry point in cc-mode. Neither do I see cuda-mode, dart-mode, php-mode, ... > You'd lose that unity. This unity is an illusion. > As already suggested, maybe simply loading cc-awk.elc all the time > would be best. No, we do not want one big monolithic monster. > multiplicity of complicated languages. Are there any other Emacs modes > which handle many variants on a theme, like C, C++, Java, ...? There's SMIE, of course. It's used for a fair number of programming languages now (Coq, OCaml, SML, Prolog, RC, SH, Modula-2, Octave, Ruby, CSS, Swift, GAP, Elixir). > Your solution to the messiness and outdatedness is to use Emacs's > newest facilities, rendering the code base in need of heavy adaptation > to run elsewhere. That's not a solution. While I have spent most of the last decade focusing on code that only runs on the latest Emacs, I have a fair bit of experience with backward compatibility. There are always various different ways to solve the problem. BTW, I'd be interested to know more about the standalone package: - what kind of emacsen is it mostly used on (e.g. is it mostly used by XEmacs users, or mostly Emacs users)? - is it mostly used so as to get support for newer language features or is it mostly used to get new major-mode features? - how many users are we talking about? This said, I admit that my general position is that backward compatibility is a burden that's not very valuable: after all people who use still use Emacs-22 can use the CC-mode that came with Emacs-22. So it's OK to make some effort at backward compatibility, but you quickly get to a point of diminishing returns. In the case of CC-mode, I think the outdated state of the code that results from the way backward compatibility has been handled is slowing down CC-mode's progress, so while a few users of XEmacs and Emacs-22 may benefit a bit, it is to the detriment of most users of Emacs-24. > But the problem _is_ your changes. You would quite happily have > committed your patch despite not realising it breaks AWK Mode. FWIW, I sent it for review, in case you did not notice. BTW, you still haven't told me what my previous (cosmetic) patches break (although you did revert them). >> So let's fix this problem once and for all by merging the two and then >> make sure they can't diverge any more (i.e. by using the Emacs code as >> the place where development happens). > Then XEmacs and backward compatibility would inevitably disappear, > destroyed by the inexorable creeping use of GNU Emacs only facilities. Don't be ridiculous. There are many packages included in Emacs where we need to preserve backward compatibility (because we know that the code is also distributed separately), so we know we have to be careful to preserve backward compatibility. Of course, we do occasionally break it by accident, but its far from common. Again, we have a lot of experience preserving backward compatibility (even if reluctantly). > I'm not sure how you'd feel about the CC Mode version in savannah being a > portable one and remaining so. You seem very unhappy about a lot of the > portable coding in CC Mode. I'm not happy about you refusing to use newer facilities. That's not the same as being unhappy about preserving compatibility. > These rare patches tend to be buggy and take a lot of time to check, and > they tend to address "non-functional" issues. If the patch came in an > email with Subject: "Proposed fix for bug #23456", as one did within the > last fortnight (and also the one from Daniel Colascione in May), I'd be > very much happier. I don't intend to fix bugs, no. I intend to clean up the code so that it is more accessible. Hopefully that will also make it easier to improve the modes and fix bugs. What are my options: ask for your extensive test suite (which we did already a long time ago, and haven't seen it yet), then test my changes against it, then install my patch. And then see it reverted because you don't like my cosmetic changes? Stefan ^ permalink raw reply [flat|nested] 41+ messages in thread
* Syntax-propertize and CC-mode [Was: Further CC-mode changes] 2014-09-13 19:24 ` Stefan Monnier @ 2014-09-13 23:08 ` Alan Mackenzie 2014-09-14 4:04 ` Stefan Monnier 2014-09-16 17:30 ` Sync'ing cc-mode Stefan Monnier 1 sibling, 1 reply; 41+ messages in thread From: Alan Mackenzie @ 2014-09-13 23:08 UTC (permalink / raw) To: Stefan Monnier; +Cc: emacs-devel Hello again, Stefan. I've separated the discussion on syntax-propertize from the rest, because things are threatening to get out of hand. On Sat, Sep 13, 2014 at 03:24:03PM -0400, Stefan Monnier wrote: > >> You know why: `syntax-propertize' is used by all major modes except > >> cc-mode derived ones. And it's more efficient, because it's more lazy. > > Lazy? Does C-M-f, for example, trigger syntax-propertize in any way? > Not yet, no. OK. I'm not yet convinced that syntax-propertize works well in languages like C++ and Java, where template/generic delimiters < and > are marked with category properties. (These have symbols with syntax-table properties.) Because applying these properties is expensive at runtime, they are tended to with loving care in CC Mode. When a buffer change is made, a before-change function c-before-change-check-<>-operators removes the category properties from exactly those pairs of <>s which need it, in particular, the removal region is LIMITED TO THE CURRENT "STATEMENT". (A template/generic construct cannot include braces or semicolons.) The properties get applied, when necessary, as a side effect of the scanning which happens during font-locking. It is a long-standing bug that they aren't applied when font-locking is disabled. > >> Also its correctness argument is much simpler since it doesn't rely on > >> interactions between before-change-functions, after-change-functions > >> (and font-lock), contrary to your code. > > The argument could run that because syntax-propertize doesn't take > > account of these subleties, its actions aren't always correct. But ... > > syntax-propertize isn't documented in the Elisp manual. It's unclear > > when it gets called (in relation to after-change-functions, for example) > > and even _if_ it always gets called (e.g. when font-lock isn't enabled). > That's because it's irrelevant: if *you* need the properties to be > applied, then call (syntax-propertize POS). If they've already been > applied, then this will return immediately. That's useful to know. I didn't know that (and couldn't have known it) before, since it is undocumented. How is the lower limit determined (matching the upper limit POS)? At a guess, this is going to be anywhere down to BOB. This isn't very lazy. Why doesn't syntax-propertize take TWO parameters, BEG and END? > Since font-lock's syntactic fontification needs those properties to be > applied, it does call syntax-propertize. I didn't know this either. How will this be interacting with C++/Java Modes' use of category properties to set the syntax? I don't have good feelings about this. Looking at the source, syntax-propertize is unoptimised. It will always erase the syntax-table properties from the last buffer change onwards, in contrast to C++ Mode, which only erases them locally as needed. There is surely an opportunity for better customisation here. > Similarly, indent-according-to-mode calls it since it's usually a good > idea. And yes, C-M-f should too, tho noone has been sufficiently > bothered by it to implement it yet. > > Adapting code to use it is thus a _massive_ amount of work - it involves > > reading the source code for syntax-propertize and friends to work out > > what it does. > No you don't: the contract is just what I stated above and you don't > need to know more than that. That is not true. I need to know that syntax-propertize would nullify C++/Java Modes' careful optimisations. I need to know whether or not syntax-propertize properly handles category properties. I suspect it doesn't. That involves reading the source code, for lack of documentation. > > I suspect that for a mode which needs syntax-table text properties > > early in its after-change-functions, syntax-properties wouldn't work. > Suspect all you want. But I assure you it works just fine. > >> > It's a lot of work to change, > >> It's work I did, pro bono. Just enjoy it. > > No, you haven't. What's the equivalent of `syntax-propertize' in XEmacs, > > or an old GNU Emacs? > Did you look at my patch? It only uses syntax-propertize > when available. When not, it keeps using your old code. And the bulk of > the code is shared between the two cases. I looked at the patch, yes, but didn't catch every last detail. There's the philosophical question why add this extra code when it's not replacing old code, but causing bloat. I now think syntactic-propertize contains a severe pessimisation: At a buffer change, all syntax-table properties are effectively erased between the change point and EOB. This wasn't done in the existing AWK Mode code. Perhaps it doesn't matter too much, since AWK buffers tend not to be very big. > > Right. So I'm now going to have three alternative code flows in place of > > the one I currently have: (i) One flow for when font lock's enabled; (ii) > > one for when FL is disabled, which explicitly calls syntax-propertize > > from after-change-functions; (iii) one for Emacsen lacking > > syntax-propertize. I've already got (iii). I think you're asking me to > > add (i) and (ii). This is an increase in complexity and a lot of work. > There are many different ways to handle backward compatibility. You can > do it as above (where my position would be to simply keep the current > code for the old Emacsen that don't have syntax-propertize, so while > there are more different ways to work than you'd like the old ways have > been tested and there's no reason they should stop working, so you can > largely ignore them). > Or you can provide you own implementation of syntax-propertize. > It's actually simple. If you prefer this route, I can do > that as well. syntax-propertize needs a way of customizing its before-change function to avoid removing ST properties needlessly from large chunks of buffer. How about `syntax-depropertize-function', which if non-nil would be run in place of a bit of syntax-ppss-flush-cache? Or something like that? [ .... ] > syntax-propertize uses a before-change-function to "flush the cache", of > course. After that you just call it when you need it. E.g. If > font-lock itself doesn't call it, then we'll need to arrange to run it > before font-lock does its thing. [ .... ] > Stefan -- Alan Mackenzie (Nuremberg, Germany). ^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: Syntax-propertize and CC-mode [Was: Further CC-mode changes] 2014-09-13 23:08 ` Syntax-propertize and CC-mode [Was: Further CC-mode changes] Alan Mackenzie @ 2014-09-14 4:04 ` Stefan Monnier 0 siblings, 0 replies; 41+ messages in thread From: Stefan Monnier @ 2014-09-14 4:04 UTC (permalink / raw) To: Alan Mackenzie; +Cc: emacs-devel > I've separated the discussion on syntax-propertize from the rest, > because things are threatening to get out of hand. Important note: I only provided a patch to use syntax-propertize for awk-mode. This case is much simpler to handle than the C/C++/Java cases (at least, IIUC, the way you apply syntax-table properties in awk-mode is easy to map to what syntax-propertize needs). Using syntax-propertize for C/C++/Java is a whole other project, which I hope to get to at some point, but I'll need to dig much deeper into the belly of the beast before I can hope to do that. > How is the lower limit determined (matching the upper limit POS)? Syntax-propertize internally keeps track of "up-to-where have properties been applied", so that it can provide the lower limit. > At a guess, this is going to be anywhere down to BOB. That can be, tho usually it's just "the beginning of the last buffer modification". > This isn't very lazy. Why doesn't syntax-propertize take TWO > parameters, BEG and END? How would you know what is BEG without knowing what other packages (indent.el, font-lock.el, ...) have already `syntax-propertize'd? > Looking at the source, syntax-propertize is unoptimised. It will always > erase the syntax-table properties from the last buffer change onwards, in > contrast to C++ Mode, which only erases them locally as needed. syntax-propertize is lazy, but indeed it always assumes pessimistically that any change to the buffer at POS might cause everything after POS to be interpreted completely differently and hence require re-propertization. So far, this has not proved to be problematic in any of the 20 or so major modes that use syntax-propertize. > There is surely an opportunity for better customisation here. Yes, we could spice up syntax.el so that you can set some properties and explain when modifications in previous text don't invalidate them. We haven't seen a need for it so far. > That is not true. I need to know that syntax-propertize would nullify > C++/Java Modes' careful optimisations. syntax-propertize (as it stands) is probably not compatible with some of the optimizations you use, indeed. It probably gives you other optimization opportunities, of course. How well it would work is hard to tell without a lot more investigation. > I need to know whether or not syntax-propertize properly handles > category properties. By and large, `syntax-propertize' doesn't handle anything at all. It does is keep track of the BEG argument for you, and it does erase the `syntax-table' properties over BEG..END before calling syntax-propertize-function. But that's about all it does. > I suspect it doesn't. That involves reading the > source code, for lack of documentation. The source is all in a single function (called, you guessed, syntax-propertize) which weighs in at 39 lines of Elisp code, a good half of which has to do with calling syntax-propertize-extend-region-functions. > syntax-propertize needs a way of customizing its before-change function > to avoid removing ST properties needlessly from large chunks of buffer. Note that in 99% of the cases, there aren't any properties applied further in the buffer anyway, so we don't actually "needlessly" throwaway data on large chunks of buffer. That's why so far, this optimization you're suggesting has not been requested by anyone, even though modes such as (C)perl do have rather complex/costly syntax-propertize-functions and are sometimes applied to very large buffers as well. IOW, I wouldn't worry about this problem for now. We'll cross this bridge when we get there. Stefan ^ permalink raw reply [flat|nested] 41+ messages in thread
* Sync'ing cc-mode 2014-09-13 19:24 ` Stefan Monnier 2014-09-13 23:08 ` Syntax-propertize and CC-mode [Was: Further CC-mode changes] Alan Mackenzie @ 2014-09-16 17:30 ` Stefan Monnier 2014-09-26 19:19 ` Stefan Monnier 1 sibling, 1 reply; 41+ messages in thread From: Stefan Monnier @ 2014-09-16 17:30 UTC (permalink / raw) To: Alan Mackenzie; +Cc: emacs-devel > What are my options: ask for your extensive test suite (which we did > already a long time ago, and haven't seen it yet), OK I finally noticed that it's included in the Hg repository of the standalone CC-mode. Talking about that standalone CC-mode: when were the two last merged (ideally, what is the exact revision IDs (both int the Hg repository and in Emacs's Bzr) corresponding to this sync)? Stefan ^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: Sync'ing cc-mode 2014-09-16 17:30 ` Sync'ing cc-mode Stefan Monnier @ 2014-09-26 19:19 ` Stefan Monnier 0 siblings, 0 replies; 41+ messages in thread From: Stefan Monnier @ 2014-09-26 19:19 UTC (permalink / raw) To: Alan Mackenzie; +Cc: emacs-devel Hi Alan, Find below a patch against Emacs's trunk which should bring Emacs's trunk up-to-date w.r.t your standalone cc-mode Hg repository. IOW I think that most of the remaining differences should either be applied to your Hg repository, or kept as "differences between the two versions". Note that many/most of the differences are in whitespace, so use "diff -bw" or something like that if you want to see the "real" remaining changes. I decided to keep the whitespace as it is in Emacs rather than in your branch, except for some cases where our branch had clearly some mis-indentations (which can be seen in big hunks in cc-engine.el below, which merit checking with diff-refine-hunk to see that they indeed only change whitespace). Actually, there are also a few grey areas where I couldn't decide how to merge the two: e.g. one side uses `eval-after-load' and the other commented it out and I'm not sure exactly how they should be merged. Guaranteed 99% untested (I can open a file in C, C++, Java, AWK modes, but I didn't get to test much more than that). Stefan PS: Most changes are just straightforward inclusion of new code from your branch, but there are a few other details of note: - rather than merge your cc-bytecomp-defmacro and cc-bytecomp-push thingies, I just removed all their uses, since there pretty much weren't any left anyway. - I define c-subword-mode as an obsolete alias for subword-mode when subword-mode is available so as to try and share some code between the two cases. - I use c--macroexpand-all to handle the fact that some emacsen don't have cl-macroexpand-all and some don't have macroexpand-all. - I use c--make-local-hook to handle the fact that some emacsen require the use of make-local-hook whereas others have obsoleted it many years ago and removed it a few years ago. - I reverted the Emacs code to use `cl' instead of `cl-lib' in cc-langs now that it's not loaded at runtime any more. - When introducing c-unmark-<->-as-paren, you changed a (c-clear-char-property pos 'category) to (c-unmark-<->-as-paren (point)) and I assumed this was a copy&paste error. === modified file 'lisp/progmodes/cc-align.el' --- lisp/progmodes/cc-align.el 2014-01-01 07:43:34 +0000 +++ lisp/progmodes/cc-align.el 2014-09-25 17:09:45 +0000 @@ -1229,6 +1229,18 @@ (back-to-indentation) (vector (current-column)))) +(defun c-lineup-respect-col-0 (langelem) + "If the current line starts at column 0, return [0]. Otherwise return nil. + +This can be used for comments (in conjunction with, say, +`c-lineup-comment'), to keep comments already at column 0 +anchored there, but reindent other comments." + (save-excursion + (back-to-indentation) + (if (eq (current-column) 0) + [0] + nil))) + \f (defun c-snug-do-while (syntax pos) "Dynamically calculate brace hanginess for do-while statements. === modified file 'lisp/progmodes/cc-awk.el' --- lisp/progmodes/cc-awk.el 2014-09-10 21:38:11 +0000 +++ lisp/progmodes/cc-awk.el 2014-09-25 17:09:33 +0000 @@ -61,7 +61,6 @@ (cc-bytecomp-defun c-backward-token-1) (cc-bytecomp-defun c-beginning-of-statement-1) (cc-bytecomp-defun c-backward-sws) -(cc-bytecomp-defun c-forward-sws) (defvar awk-mode-syntax-table (let ((st (make-syntax-table))) @@ -174,6 +173,7 @@ (concat "\"\\(" c-awk-string-ch-re "\\|" c-awk-esc-pair-re "\\)*" "\\(\"\\|$\\|\\'\\)")) + ;; REGEXPS FOR AWK REGEXPS. (defconst c-awk-regexp-normal-re "[^[/\\\n\r]") ;; Matches any AWK regexp character which doesn't require special analysis. @@ -201,6 +201,7 @@ (concat "/" c-awk-regexp-innards-re)) ;; Matches an AWK regexp up to, but not including, any terminating /. + ;; REGEXPS used for scanning an AWK buffer in order to decide IF A '/' IS A ;; REGEXP OPENER OR A DIVISION SIGN. By "state" in the following is meant ;; whether a '/' at the current position would by a regexp opener or a === modified file 'lisp/progmodes/cc-bytecomp.el' --- lisp/progmodes/cc-bytecomp.el 2014-01-01 07:43:34 +0000 +++ lisp/progmodes/cc-bytecomp.el 2014-09-25 21:30:55 +0000 @@ -65,8 +65,7 @@ ;; elsewhere in the load path. ;; ;; To suppress byte compiler warnings, use the macros -;; `cc-bytecomp-defun', `cc-bytecomp-defvar', -;; `cc-bytecomp-obsolete-fun', and `cc-bytecomp-obsolete-var'. +;; `cc-bytecomp-defun' and `cc-bytecomp-defvar'. ;; ;; This file is not used at all after the package has been byte ;; compiled. It is however necessary when running uncompiled. @@ -78,6 +77,12 @@ (defvar cc-bytecomp-original-functions nil) (defvar cc-bytecomp-original-properties nil) (defvar cc-bytecomp-loaded-files nil) + +(setq cc-bytecomp-unbound-variables nil) +(setq cc-bytecomp-original-functions nil) +(setq cc-bytecomp-original-properties nil) +(setq cc-bytecomp-loaded-files nil) + (defvar cc-bytecomp-environment-set nil) (defmacro cc-bytecomp-debug-msg (&rest args) @@ -370,33 +375,6 @@ "cc-bytecomp-put: Bound property %s for %s to %s" ,propname ,symbol ,value))) -(defmacro cc-bytecomp-obsolete-var (symbol) - "Suppress warnings 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) - ;; This avoids a superfluous compiler warning - ;; about calling `get' for effect. - t))) - -(defun cc-bytecomp-ignore-obsolete (form) - ;; Wraps a call to `byte-compile-obsolete' that suppresses the warning. - (let ((byte-compile-warnings byte-compile-warnings)) - (byte-compile-disable-warning 'obsolete) - (byte-compile-obsolete form))) - -(defmacro cc-bytecomp-obsolete-fun (symbol) - "Suppress warnings 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) - ;; This avoids a superfluous compiler warning - ;; about calling `get' for effect. - t))) - (defmacro cc-bytecomp-boundp (symbol) "Return non-nil if the given symbol is bound as a variable outside the compilation. This is the same as using `boundp' but additionally === modified file 'lisp/progmodes/cc-cmds.el' --- lisp/progmodes/cc-cmds.el 2014-02-17 18:16:32 +0000 +++ lisp/progmodes/cc-cmds.el 2014-09-26 15:25:52 +0000 @@ -45,8 +45,11 @@ (cc-require 'cc-engine) ;; Silence the compiler. +(cc-bytecomp-defun delete-forward-p) ; XEmacs (cc-bytecomp-defvar filladapt-mode) ; c-fill-paragraph contains a kludge ; which looks at this. +(cc-bytecomp-defun c-forward-subword) +(cc-bytecomp-defun c-backward-subword) \f ;; Indentation / Display syntax functions (defvar c-fix-backslashes t) @@ -258,9 +261,11 @@ "a" "") (if c-hungry-delete-key "h" "") (if (and - ;; subword might not be loaded. - (boundp 'subword-mode) - (symbol-value 'subword-mode)) + ;; (cc-)subword might not be loaded. + (boundp 'c-subword-mode) + (symbol-value 'c-subword-mode)) + ;; FIXME: subword-mode already comes with its + ;; own lighter! "w" ""))) ;; FIXME: Derived modes might want to use something else @@ -936,8 +941,15 @@ ;; do all cleanups and newline insertions if c-auto-newline is on. (if (or (not c-auto-newline) (not (looking-at "[ \t]*\\\\?$"))) - (if c-syntactic-indentation - (c-indent-line)) + (when c-syntactic-indentation + (let ((syntax (c-guess-basic-syntax))) + (c-indent-line syntax) + ;; Guard against the C hacker inserting a statement before a + ;; non-compound statement in an if/while/for. + (if (eq (caar syntax) 'substatement) + (save-excursion + (if (eq 0 (forward-line)) + (c-indent-line)))))) ;; clean ups: list-close-comma or defun-close-semi (let ((pos (- (point-max) (point)))) (if (c-save-buffer-state () @@ -1090,7 +1102,7 @@ (interactive "*P") (let ((c-echo-syntactic-information-p nil) - final-pos close-paren-inserted found-delim case-fold-search) + final-pos found-delim case-fold-search) (self-insert-command (prefix-numeric-value arg)) (setq final-pos (point)) @@ -1303,20 +1315,43 @@ (declare-function subword-forward "subword" (&optional arg)) (declare-function subword-backward "subword" (&optional arg)) +(cond + ((and (fboundp 'subword-mode) (not (fboundp 'c-subword-mode))) + ;; Recent Emacsen come with their own subword support. Use that. + (define-obsolete-function-alias 'c-subword-mode 'subword-mode "24.3") + (define-obsolete-variable-alias 'c-subword-mode 'subword-mode "24.3")) + (t + ;; Autoload directive for emacsen that doesn't have an older CC Mode + ;; version in the dist. + (autoload 'c-subword-mode "cc-subword" + "Mode enabling subword movement and editing keys." t))) + ;; "nomenclature" functions + c-scope-operator. (defun c-forward-into-nomenclature (&optional arg) "Compatibility alias for `c-forward-subword'." (interactive "p") - (require 'subword) - (subword-forward arg)) -(make-obsolete 'c-forward-into-nomenclature 'subword-forward "23.2") + (if (fboundp 'subword-mode) + (progn + (require 'subword) + (subword-forward arg)) + (require 'cc-subword) + (c-forward-subword arg))) +(make-obsolete 'c-forward-into-nomenclature + (if (fboundp 'subword-mode) 'subword-forward 'c-forward-subword) + "23.2") (defun c-backward-into-nomenclature (&optional arg) "Compatibility alias for `c-backward-subword'." (interactive "p") - (require 'subword) - (subword-backward arg)) -(make-obsolete 'c-backward-into-nomenclature 'subword-backward "23.2") + (if (fboundp 'subword-mode) + (progn + (require 'subword) + (subword-backward arg)) + (require 'cc-subword) + (c-forward-backword arg))) +(make-obsolete + 'c-backward-into-nomenclature + (if (fboundp 'subword-mode) 'subword-backward 'c-backward-subword) "23.2") (defun c-scope-operator () "Insert a double colon scope operator at point. @@ -1408,18 +1443,20 @@ ;; Kluge so that c-beginning-of-decl-1 won't go back if we're already ;; at a declaration. (if (or (and (eolp) (not (eobp))) ; EOL is matched by "\\s>" - (not (looking-at -"\\([;#]\\|\\'\\|\\s(\\|\\s)\\|\\s\"\\|\\s\\\\|\\s$\\|\\s<\\|\\s>\\|\\s!\\)"))) + (not (c-looking-at-non-alphnumspace))) (forward-char)) (setq kluge-start (point)) (setq decl-result (car (c-beginning-of-decl-1 ;; NOTE: If we're in a K&R region, this might be the start ;; of a parameter declaration, not the actual function. + ;; It might also leave us at a label or "label" like + ;; "private:". (and least-enclosing ; LIMIT for c-b-of-decl-1 (c-safe-position least-enclosing paren-state))))) ;; Has the declaration we've gone back to got braces? + (or (eq decl-result 'label) (setq brace-decl-p (save-excursion (and (c-syntactic-re-search-forward "[;{]" nil t t) @@ -1429,10 +1466,11 @@ ;; ';' in a K&R argdecl. In ;; that case the declaration ;; should contain a block. - (c-in-knr-argdecl)))))) + (c-in-knr-argdecl))))))) (cond - ((= (point) kluge-start) ; might be BOB or unbalanced parens. + ((or (eq decl-result 'label) ; e.g. "private:" or invalid syntax. + (= (point) kluge-start)) ; might be BOB or unbalanced parens. 'outwith-function) ((eq decl-result 'same) (if brace-decl-p @@ -1808,7 +1846,7 @@ (looking-at c-symbol-key)) (match-string-no-properties 0)) - ((looking-at "DEFUN\\_>") + ((looking-at "DEFUN\\s-*(") ;"DEFUN\\_>") think of XEmacs! ;; DEFUN ("file-name-directory", Ffile_name_directory, Sfile_name_directory, ...) ==> Ffile_name_directory ;; DEFUN(POSIX::STREAM-LOCK, stream lockp &key BLOCK SHARED START LENGTH) ==> POSIX::STREAM-LOCK (down-list 1) @@ -2001,7 +2039,7 @@ (eq last-command 'c-mark-function))) (push-mark-p (and (eq this-command 'c-mark-function) (not extend-region-p) - (not (and transient-mark-mode mark-active))))) + (not (c-region-is-active-p))))) (if push-mark-p (push-mark (point))) (if extend-region-p (progn @@ -3338,7 +3376,7 @@ starting on the current line. Otherwise reindent just the current line." (interactive - (list current-prefix-arg (use-region-p))) + (list current-prefix-arg (c-region-is-active-p))) (if region (c-indent-region (region-beginning) (region-end)) (c-indent-command arg))) === modified file 'lisp/progmodes/cc-defs.el' --- lisp/progmodes/cc-defs.el 2014-09-10 21:38:11 +0000 +++ lisp/progmodes/cc-defs.el 2014-09-26 15:12:06 +0000 @@ -48,12 +48,16 @@ ;; 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-defvar deactivate-mark) ; Emacs (cc-bytecomp-defvar inhibit-point-motion-hooks) ; Emacs (cc-bytecomp-defvar parse-sexp-lookup-properties) ; Emacs (cc-bytecomp-defvar text-property-default-nonsticky) ; Emacs 21 +(cc-bytecomp-defvar lookup-syntax-properties) ; XEmacs (cc-bytecomp-defun string-to-syntax) ; Emacs 21 \f @@ -64,15 +68,14 @@ (not (fboundp 'push))) (cc-load "cc-fix"))) -; (eval-after-load "font-lock" ; 2006-07-09. font-lock is now preloaded -; ' -(if (and (featurep 'xemacs) ; There is now (2005/12) code in GNU Emacs CVS +(when (featurep 'xemacs) ; There is now (2005/12) code in GNU Emacs CVS ; to make the call to f-l-c-k throw an error. - (not (featurep 'cc-fix)) ; only load the file once. + (eval-after-load "font-lock" + '(if (and (not (featurep 'cc-fix)) ; only load the file once. (let (font-lock-keywords) (font-lock-compile-keywords '("\\<\\>")) font-lock-keywords)) ; did the previous call foul this up? - (load "cc-fix")) ;) + (load "cc-fix")))) ;; The above takes care of the delayed loading, but this is necessary ;; to ensure correct byte compilation. @@ -86,10 +89,15 @@ font-lock-keywords))) (cc-load "cc-fix"))) +;; XEmacs 21.4 doesn't have `delete-dups'. +(eval-and-compile + (if (and (not (fboundp 'delete-dups)) + (not (featurep 'cc-fix))) + (cc-load "cc-fix"))) \f ;;; Variables also used at compile time. -(defconst c-version "5.32.5" +(defconst c-version "5.33" "CC Mode version number.") (defconst c-version-sym (intern c-version)) @@ -169,6 +177,10 @@ (put 'cc-eval-when-compile 'lisp-indent-hook 0)) +(eval-and-compile + (defalias 'c--macroexpand-all + (if (fboundp 'macroexpand-all) + 'macroexpand-all 'cl-macroexpand-all))) \f ;;; Macros. @@ -327,21 +339,28 @@ (t (error "Unknown buffer position requested: %s" position)))) (point)))) +(defmacro c-next-single-property-change (position prop &optional object limit) + ;; See the doc string for either of the defuns expanded to. + (if (and (featurep 'xemacs) + (fboundp 'next-single-char-property-change)) + ;; XEmacs >= 2005-01-25 + `(next-single-char-property-change ,position ,prop ,object ,limit) + ;; Emacs and earlier XEmacs + `(next-single-property-change ,position ,prop ,object ,limit))) + (defmacro c-region-is-active-p () ;; Return t when the region is active. The determination of region ;; activeness is different in both Emacs and XEmacs. - ;; FIXME? Emacs has region-active-p since 23.1, so maybe this test - ;; should be updated. - (if (cc-bytecomp-boundp 'mark-active) - ;; Emacs. - 'mark-active + (if (cc-bytecomp-fboundp 'region-active-p) ;; XEmacs. - '(region-active-p))) + '(region-active-p) + ;; Old Emacs. + 'mark-active)) (defmacro c-set-region-active (activate) ;; Activate the region if ACTIVE is non-nil, deactivate it ;; otherwise. Covers the differences between Emacs and XEmacs. - (if (fboundp 'zmacs-activate-region) + (if (cc-bytecomp-fboundp 'zmacs-activate-region) ;; XEmacs. `(if ,activate (zmacs-activate-region) @@ -438,6 +457,7 @@ (put 'c-save-buffer-state 'lisp-indent-function 1) (defmacro c-tentative-buffer-changes (&rest body) + ;; FIXME: Use atomic-change-group! "Eval BODY and optionally restore the buffer contents to the state it was in before BODY. Any changes are kept if the last form in BODY returns non-nil. Otherwise it's undone using the undo facility, and @@ -705,9 +725,9 @@ ;; `c-parse-state'. `(progn - (if (and ,(fboundp 'buffer-syntactic-context-depth) + (if (and ,(cc-bytecomp-fboundp 'buffer-syntactic-context-depth) c-enable-xemacs-performance-kludge-p) - ,(when (fboundp 'buffer-syntactic-context-depth) + ,(when (cc-bytecomp-fboundp 'buffer-syntactic-context-depth) ;; XEmacs only. This can improve the performance of ;; c-parse-state to between 3 and 60 times faster when ;; braces are hung. It can also degrade performance by @@ -913,6 +933,12 @@ (cc-bytecomp-fboundp 'delete-extent) (cc-bytecomp-fboundp 'map-extents)))) +(defconst c-<-as-paren-syntax '(4 . ?>)) +(put 'c-<-as-paren-syntax 'syntax-table c-<-as-paren-syntax) + +(defconst c->-as-paren-syntax '(5 . ?<)) +(put 'c->-as-paren-syntax 'syntax-table c->-as-paren-syntax) + ;; `c-put-char-property' is complex enough in XEmacs and Emacs < 21 to ;; make it a function. (defalias 'c-put-char-property-fun @@ -966,6 +992,21 @@ `(let ((-pos- ,pos)) (put-text-property -pos- (1+ -pos-) ',property ,value)))) +(eval-and-compile + ;; Constant to decide at compilation time whether to use category + ;; properties. Currently (2010-03) they're available only on GNU Emacs. + (defconst c-use-category + (with-temp-buffer + (let ((parse-sexp-lookup-properties t) + (lookup-syntax-properties t)) + (set-syntax-table (make-syntax-table)) + (insert "<()>") + (c-put-char-property (point-min) 'category 'c-<-as-paren-syntax) + (c-put-char-property (+ 3 (point-min)) 'category 'c->-as-paren-syntax) + (goto-char (point-min)) + (forward-sexp) + (= (point) (+ 4 (point-min))))))) + (defmacro c-get-char-property (pos property) ;; Get the value of the given property on the character at POS if ;; it's been put there by `c-put-char-property'. PROPERTY is @@ -1046,8 +1087,8 @@ (while (and (< place ,(or limit '(point-max))) - (not (equal (get-text-property place ,property) ,value))) - (setq place (next-single-property-change + (not (equal (c-get-char-property place ,property) ,value))) + (setq place (c-next-single-property-change place ,property nil ,(or limit '(point-max))))) (when (< place ,(or limit '(point-max))) (goto-char place) @@ -1065,10 +1106,15 @@ (while (and (> place ,(or limit '(point-min))) - (not (equal (get-text-property (1- place) ,property) ,value))) - (setq place (previous-single-property-change + (not (equal (c-get-char-property (1- place) ,property) ,value))) + (setq place (,(if (and (featurep 'xemacs) + (fboundp 'previous-single-char-property-change)) + ;; XEmacs > 2005-01-25. + 'previous-single-char-property-change + ;; Emacs and earlier XEmacs. + 'previous-single-property-change) place ,property nil ,(or limit '(point-min))))) - (when (> place ,(or limit '(point-max))) + (when (> place ,(or limit '(point-min))) (goto-char place) (search-backward-regexp ".") ; to set the match-data. (point)))) @@ -1085,9 +1131,9 @@ (and (< place to) (not (equal (get-text-property place property) value))) - (setq place (next-single-property-change place property nil to))) + (setq place (c-next-single-property-change place property nil to))) (< place to)) - (setq end-place (next-single-property-change place property nil to)) + (setq end-place (c-next-single-property-change place property nil to)) (remove-text-properties place end-place (cons property nil)) ;; Do we have to do anything with stickiness here? (setq place end-place)))) @@ -1104,7 +1150,7 @@ (if (equal (extent-property ext -property-) val) (delete-extent ext))) nil ,from ,to ,value nil -property-)) - ;; Gnu Emacs + ;; GNU Emacs `(c-clear-char-property-with-value-function ,from ,to ,property ,value))) \f ;; Macros to put overlays (Emacs) or extents (XEmacs) on buffer text. @@ -1188,42 +1234,43 @@ (if (< (point) start) (goto-char (point-max))))) -(defconst c-<-as-paren-syntax '(4 . ?>)) -(put 'c-<-as-paren-syntax 'syntax-table c-<-as-paren-syntax) - -(defsubst c-mark-<-as-paren (pos) +(defmacro c-mark-<-as-paren (pos) ;; Mark the "<" character at POS as a template opener using the - ;; `syntax-table' property via the `category' property. + ;; `syntax-table' property either directly (XEmacs) or via a `category' + ;; property (GNU Emacs). ;; ;; This function does a hidden buffer change. Note that we use ;; indirection through the `category' text property. This allows us to ;; toggle the property in all template brackets simultaneously and ;; cheaply. We use this, for instance, in `c-parse-state'. - (c-put-char-property pos 'category 'c-<-as-paren-syntax)) - -(defconst c->-as-paren-syntax '(5 . ?<)) -(put 'c->-as-paren-syntax 'syntax-table c->-as-paren-syntax) - -(defsubst c-mark->-as-paren (pos) + (if c-use-category + `(c-put-char-property ,pos 'category 'c-<-as-paren-syntax) + `(c-put-char-property ,pos 'syntax-table c-<-as-paren-syntax))) + + +(defmacro c-mark->-as-paren (pos) ;; Mark the ">" character at POS as an sexp list closer using the - ;; syntax-table property. + ;; `syntax-table' property either directly (XEmacs) or via a `category' + ;; property (GNU Emacs). ;; ;; This function does a hidden buffer change. Note that we use ;; indirection through the `category' text property. This allows us to ;; toggle the property in all template brackets simultaneously and ;; cheaply. We use this, for instance, in `c-parse-state'. - (c-put-char-property pos 'category 'c->-as-paren-syntax)) + (if c-use-category + `(c-put-char-property ,pos 'category 'c->-as-paren-syntax) + `(c-put-char-property ,pos 'syntax-table c->-as-paren-syntax))) -(defsubst c-unmark-<->-as-paren (pos) - ;; Unmark the "<" or "<" character at POS as an sexp list opener using - ;; the syntax-table property indirectly through the `category' text - ;; property. +(defmacro c-unmark-<->-as-paren (pos) + ;; Unmark the "<" or "<" character at POS as an sexp list opener using the + ;; `syntax-table' property either directly or indirectly through a + ;; `category' text property. ;; - ;; This function does a hidden buffer change. Note that we use + ;; This function does a hidden buffer change. Note that we try to use ;; indirection through the `category' text property. This allows us to ;; toggle the property in all template brackets simultaneously and ;; cheaply. We use this, for instance, in `c-parse-state'. - (c-clear-char-property pos 'category)) + `(c-clear-char-property ,pos ,(if c-use-category ''category ''syntax-table))) (defsubst c-suppress-<->-as-parens () ;; Suppress the syntactic effect of all marked < and > as parens. Note @@ -1304,6 +1351,122 @@ (widen) (c-set-cpp-delimiters ,beg ,end))))) \f +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; The following macros are to be used only in `c-parse-state' and its +;; subroutines. Their main purpose is to simplify the handling of C++/Java +;; template delimiters and CPP macros. In GNU Emacs, this is done slickly by +;; the judicious use of 'category properties. These don't exist in XEmacs. +;; +;; Note: in the following macros, there is no special handling for parentheses +;; inside CPP constructs. That is because CPPs are always syntactically +;; balanced, thanks to `c-neutralize-CPP-line' in cc-mode.el. +(defmacro c-sc-scan-lists-no-category+1+1 (from) + ;; Do a (scan-lists FROM 1 1). Any finishing position which either (i) is + ;; determined by and angle bracket; or (ii) is inside a macro whose start + ;; isn't POINT-MACRO-START doesn't count as a finishing position. + `(let ((here (point)) + (pos (scan-lists ,from 1 1))) + (while (eq (char-before pos) ?>) + (setq pos (scan-lists pos 1 1))) + pos)) + +(defmacro c-sc-scan-lists-no-category+1-1 (from) + ;; Do a (scan-lists FROM 1 -1). Any finishing position which either (i) is + ;; determined by an angle bracket; or (ii) is inside a macro whose start + ;; isn't POINT-MACRO-START doesn't count as a finishing position. + `(let ((here (point)) + (pos (scan-lists ,from 1 -1))) + (while (eq (char-before pos) ?<) + (setq pos (scan-lists pos 1 1)) + (setq pos (scan-lists pos 1 -1))) + pos)) + +(defmacro c-sc-scan-lists-no-category-1+1 (from) + ;; Do a (scan-lists FROM -1 1). Any finishing position which either (i) is + ;; determined by and angle bracket; or (ii) is inside a macro whose start + ;; isn't POINT-MACRO-START doesn't count as a finishing position. + `(let ((here (point)) + (pos (scan-lists ,from -1 1))) + (while (eq (char-after pos) ?<) + (setq pos (scan-lists pos -1 1))) + pos)) + +(defmacro c-sc-scan-lists-no-category-1-1 (from) + ;; Do a (scan-lists FROM -1 -1). Any finishing position which either (i) is + ;; determined by and angle bracket; or (ii) is inside a macro whose start + ;; isn't POINT-MACRO-START doesn't count as a finishing position. + `(let ((here (point)) + (pos (scan-lists ,from -1 -1))) + (while (eq (char-after pos) ?>) + (setq pos (scan-lists pos -1 1)) + (setq pos (scan-lists pos -1 -1))) + pos)) + +(defmacro c-sc-scan-lists (from count depth) + (if c-use-category + `(scan-lists ,from ,count ,depth) + (cond + ((and (eq count 1) (eq depth 1)) + `(c-sc-scan-lists-no-category+1+1 ,from)) + ((and (eq count 1) (eq depth -1)) + `(c-sc-scan-lists-no-category+1-1 ,from)) + ((and (eq count -1) (eq depth 1)) + `(c-sc-scan-lists-no-category-1+1 ,from)) + ((and (eq count -1) (eq depth -1)) + `(c-sc-scan-lists-no-category-1-1 ,from)) + (t (error "Invalid parameter(s) to c-sc-scan-lists"))))) + + +(defun c-sc-parse-partial-sexp-no-category (from to targetdepth stopbefore + oldstate) + ;; Do a parse-partial-sexp using the supplied arguments, disregarding + ;; template/generic delimiters < > and disregarding macros other than the + ;; one at POINT-MACRO-START. + ;; + ;; NOTE that STOPBEFORE must be nil. TARGETDEPTH should be one less than + ;; the depth in OLDSTATE. This function is thus a SPECIAL PURPOSE variation + ;; on parse-partial-sexp, designed for calling from + ;; `c-remove-stale-state-cache'. + ;; + ;; Any finishing position which is determined by an angle bracket delimiter + ;; doesn't count as a finishing position. + ;; + ;; Note there is no special handling of CPP constructs here, since these are + ;; always syntactically balanced (thanks to `c-neutralize-CPP-line'). + (let ((state + (parse-partial-sexp from to targetdepth stopbefore oldstate))) + (while + (and (< (point) to) + ;; We must have hit targetdepth. + (or (eq (char-before) ?<) + (eq (char-before) ?>))) + (setcar state + (if (memq (char-before) '(?> ?\) ?\} ?\])) + (1+ (car state)) + (1- (car state)))) + (setq state + (parse-partial-sexp (point) to targetdepth stopbefore oldstate))) + state)) + +(defmacro c-sc-parse-partial-sexp (from to &optional targetdepth stopbefore + oldstate) + (if c-use-category + `(parse-partial-sexp ,from ,to ,targetdepth ,stopbefore ,oldstate) + `(c-sc-parse-partial-sexp-no-category ,from ,to ,targetdepth ,stopbefore + ,oldstate))) + +\f +(defmacro c-looking-at-non-alphnumspace () + "Are we looking at a character which isn't alphanumeric or space?" + (if (memq 'gen-comment-delim c-emacs-features) + `(looking-at +"\\([;#]\\|\\'\\|\\s(\\|\\s)\\|\\s\"\\|\\s\\\\|\\s$\\|\\s<\\|\\s>\\|\\s!\\)") + `(or (looking-at +"\\([;#]\\|\\'\\|\\s(\\|\\s)\\|\\s\"\\|\\s\\\\|\\s$\\|\\s<\\|\\s>\\)" + (let ((prop (c-get-char-property (point) 'syntax-table))) + (eq prop '(14))))))) ; '(14) is generic comment delimiter. + +\f (defsubst c-intersect-lists (list alist) ;; return the element of ALIST that matches the first element found ;; in LIST. Uses assq. @@ -1419,8 +1582,8 @@ (defun c-make-keywords-re (adorn list &optional mode) "Make a regexp that matches all the strings the list. -Duplicates and nil elements in the list are removed. The resulting -regexp may contain zero or more submatch expressions. +Duplicates and nil elements in the list are removed. The +resulting regexp may contain zero or more submatch expressions. If ADORN is t there will be at least one submatch and the first surrounds the matched alternative, and the regexp will also not match @@ -1438,11 +1601,7 @@ when it's needed. The default is the current language taken from `c-buffer-is-cc-mode'." - (let (unique) - (dolist (elt list) - (unless (member elt unique) - (push elt unique))) - (setq list (delete nil unique))) + (setq list (delete nil (delete-dups list))) (if list (let (re) @@ -1556,7 +1715,11 @@ (cc-bytecomp-defvar open-paren-in-column-0-is-defun-start) -(defvar lookup-syntax-properties) ;XEmacs. +(defalias 'c--make-local-hook + (let ((tmphook (make-symbol "tmphook"))) + ;; Check if `add-hook' makes the hook buffer-local. + (add-hook tmphook 'foo nil t) + (if (local-variable-p tmphook) 'ignore 'make-local-hook))) (defconst c-emacs-features (let (list) @@ -1609,6 +1772,9 @@ (not (end-of-defun)))) (setq list (cons 'argumentative-bod-function list)))) + ;; Record whether the `category' text property works. + (if c-use-category (setq list (cons 'category-properties list))) + (let ((buf (generate-new-buffer " test")) parse-sexp-lookup-properties parse-sexp-ignore-comments @@ -1638,13 +1804,13 @@ "support for the `syntax-table' text property " "is required."))) - ;; Find out if generic comment delimiters work. + ;; Find out if "\\s!" (generic comment delimiters) work. (c-safe (modify-syntax-entry ?x "!") (if (string-match "\\s!" "x") (setq list (cons 'gen-comment-delim list)))) - ;; Find out if generic string delimiters work. + ;; Find out if "\\s|" (generic string delimiters) work. (c-safe (modify-syntax-entry ?x "|") (if (string-match "\\s|" "x") @@ -1691,7 +1857,8 @@ (kill-buffer buf)) ;; See if `parse-partial-sexp' returns the eighth element. - (if (c-safe (>= (length (save-excursion (parse-partial-sexp (point) (point)))) + (if (c-safe (>= (length (save-excursion + (parse-partial-sexp (point) (point)))) 10)) (setq list (cons 'pps-extended-state list)) (error (concat @@ -1707,13 +1874,14 @@ '8-bit 8 bit syntax entry flags (XEmacs style). '1-bit 1 bit syntax entry flags (Emacs style). -'argumentative-bod-function beginning-of-defun passes ARG through - to a non-null beginning-of-defun-function. It is assumed - the end-of-defun does the same thing. +'argumentative-bod-function beginning-of-defun and end-of-defun pass + ARG through to beginning/end-of-defun-function. 'syntax-properties It works to override the syntax for specific characters in the buffer with the 'syntax-table property. It's always set - CC Mode no longer works in emacsen without this feature. +'category-properties Syntax routines can add a level of indirection to text + properties using the 'category property. 'gen-comment-delim Generic comment delimiters work (i.e. the syntax class `!'). 'gen-string-delim Generic string delimiters work @@ -1803,18 +1971,18 @@ (error "Unknown base mode `%s'" base-mode)) (put mode 'c-fallback-mode base-mode)) -(defvar c-lang-constants (make-vector 151 0) - "Obarray used as a cache to keep track of the language constants. -The constants stored are those defined by `c-lang-defconst' and the values -computed by `c-lang-const'. It's mostly used at compile time but it's not -stored in compiled files. +(defvar c-lang-constants (make-vector 151 0)) +;; Obarray used as a cache to keep track of the language constants. +;; The constants stored are those defined by `c-lang-defconst' and the values +;; computed by `c-lang-const'. It's mostly used at compile time but it's not +;; stored in compiled files. -The obarray contains all the language constants as symbols. The -value cells hold the evaluated values as alists where each car is -the mode name symbol and the corresponding cdr is the evaluated -value in that mode. The property lists hold the source definitions -and other miscellaneous data. The obarray might also contain -various other symbols, but those don't have any variable bindings.") +;; The obarray contains all the language constants as symbols. The +;; value cells hold the evaluated values as alists where each car is +;; the mode name symbol and the corresponding cdr is the evaluated +;; value in that mode. The property lists hold the source definitions +;; and other miscellaneous data. The obarray might also contain +;; various other symbols, but those don't have any variable bindings. (defvar c-lang-const-expansion nil) @@ -1831,7 +1999,9 @@ (t ;; Being evaluated interactively. (buffer-file-name))))) - (and file (file-name-base file)))) + (and file + (file-name-sans-extension + (file-name-nondirectory file))))) (defmacro c-lang-defconst-eval-immediately (form) "Can be used inside a VAL in `c-lang-defconst' to evaluate FORM @@ -1945,7 +2115,7 @@ ;; reason, but we also use this expansion handle ;; `c-lang-defconst-eval-immediately' and to register ;; dependencies on the `c-lang-const's in VAL.) - (setq val (macroexpand-all val)) + (setq val (c--macroexpand-all val)) (setq bindings `(cons (cons ',assigned-mode (lambda () ,val)) ,bindings) args (cdr args)))) @@ -1963,10 +2133,9 @@ ,@(and pre-files `(',pre-files)))))) (put 'c-lang-defconst 'lisp-indent-function 1) -;(eval-after-load "edebug" ; 2006-07-09: def-edebug-spec is now in subr.el. -; ' -(def-edebug-spec c-lang-defconst - (&define name [&optional stringp] [&rest sexp def-form])) +(eval-after-load "edebug" + '(def-edebug-spec c-lang-defconst + (&define name [&optional stringp] [&rest sexp def-form]))) (defun c-define-lang-constant (name bindings &optional pre-files) ;; Used by `c-lang-defconst'. === modified file 'lisp/progmodes/cc-engine.el' --- lisp/progmodes/cc-engine.el 2014-09-11 19:44:25 +0000 +++ lisp/progmodes/cc-engine.el 2014-09-25 20:11:21 +0000 @@ -147,18 +147,24 @@ (cc-require-when-compile 'cc-langs) (cc-require 'cc-vars) +(eval-when-compile (require 'cl)) + +;; Silence the compiler. +(cc-bytecomp-defun buffer-syntactic-context) ; XEmacs +(cc-bytecomp-defun c-fontify-recorded-types-and-refs) +(cc-bytecomp-defvar c-maybe-stale-found-type) + \f ;; Make declarations for all the `c-lang-defvar' variables in cc-langs. (defmacro c-declare-lang-variables () `(progn - ,@(apply 'nconc - (mapcar (lambda (init) - `(,(if (elt init 2) - `(defvar ,(car init) nil ,(elt init 2)) - `(defvar ,(car init) nil)) - (make-variable-buffer-local ',(car init)))) - (cdr c-lang-variable-inits))))) + ,@(mapcan (lambda (init) + `(,(if (elt init 2) + `(defvar ,(car init) nil ,(elt init 2)) + `(defvar ,(car init) nil)) + (make-variable-buffer-local ',(car init)))) + (cdr c-lang-variable-inits)))) (c-declare-lang-variables) \f @@ -514,7 +520,7 @@ (while (progn (when (eq (get-text-property (point) 'c-type) value) (c-clear-char-property (point) 'c-type)) - (goto-char (next-single-property-change (point) 'c-type nil to)) + (goto-char (c-next-single-property-change (point) 'c-type nil to)) (< (point) to))))) \f @@ -826,7 +832,6 @@ ;; Record this as the first token if not starting inside it. (setq tok start)) - ;; The following while loop goes back one sexp (balanced parens, ;; etc. with contents, or symbol or suchlike) each iteration. This ;; movement is accomplished with a call to c-backward-sexp approx 170 @@ -1370,8 +1375,9 @@ ;; 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) (elt (parse-partial-sexp start (point)) 7)) - (condition-case nil (forward-char 1))) + (when (featurep 'xemacs) + (if (and (eolp) (elt (parse-partial-sexp start (point)) 7)) + (condition-case nil (forward-char 1)))) t)))) @@ -1704,7 +1710,7 @@ ;; the cases when the marked rung is complete. ;; (`next-single-property-change' is certain to move at least one ;; step forward.) - (setq rung-pos (1- (next-single-property-change + (setq rung-pos (1- (c-next-single-property-change rung-is-marked 'c-is-sws nil rung-end-pos))) ;; Got no marked rung here. Since the simple ws might have started ;; inside a line comment or cpp directive we must set `rung-pos' as @@ -1720,7 +1726,7 @@ ;; The following search is the main reason that `c-in-sws' ;; and `c-is-sws' aren't combined to one property. - (goto-char (next-single-property-change + (goto-char (c-next-single-property-change (point) 'c-in-sws nil (point-max))) (unless (get-text-property (point) 'c-is-sws) ;; If the `c-in-sws' region extended past the last @@ -1842,7 +1848,7 @@ ;; possible since we can't be in the ending ws of a line comment or ;; cpp directive now. (if (setq rung-is-marked next-rung-is-marked) - (setq rung-pos (1- (next-single-property-change + (setq rung-pos (1- (c-next-single-property-change rung-is-marked 'c-is-sws nil rung-end-pos))) (setq rung-pos next-rung-pos)) (setq safe-start t))) @@ -1920,7 +1926,7 @@ (unless (get-text-property (point) 'c-is-sws) ;; If the `c-in-sws' region extended past the first ;; `c-is-sws' char we have to go forward a bit. - (goto-char (next-single-property-change + (goto-char (c-next-single-property-change (point) 'c-is-sws))) (c-debug-sws-msg @@ -2159,7 +2165,6 @@ ;; the middle of the desert, as long as it is not within a brace pair ;; recorded in `c-state-cache' or a paren/bracket pair. - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; We maintain a simple cache of positions which aren't in a literal, so as to ;; speed up testing for non-literality. @@ -2530,7 +2535,7 @@ (setq pos here+) (c-safe (while - (setq ren+1 (scan-lists pos 1 1)) ; might signal + (setq ren+1 (c-sc-scan-lists pos 1 1)) ; might signal (setq lonely-rens (cons ren+1 lonely-rens) pos ren+1))))) @@ -2542,7 +2547,7 @@ (c-safe (while (and lonely-rens ; actual values aren't used. - (setq pa (scan-lists pos -1 1))) + (setq pa (c-sc-scan-lists pos -1 1))) (setq pos pa) (setq lonely-rens (cdr lonely-rens))))) pos)) @@ -2698,8 +2703,8 @@ (progn (c-safe (while - (and (setq ce (scan-lists bra -1 -1)) ; back past )/]/}; might signal - (setq bra (scan-lists ce -1 1)) ; back past (/[/{; might signal + (and (setq ce (c-sc-scan-lists bra -1 -1)) ; back past )/]/}; might signal + (setq bra (c-sc-scan-lists ce -1 1)) ; back past (/[/{; might signal (or (> bra here) ;(> ce here) (and (< ce here) @@ -2751,7 +2756,7 @@ (not (c-beginning-of-macro)))) (setq c-state-cache (cons (cons (1- bra+1) - (scan-lists bra+1 1 1)) + (c-sc-scan-lists bra+1 1 1)) (if (consp (car c-state-cache)) (cdr c-state-cache) c-state-cache))) @@ -2780,7 +2785,7 @@ paren+1 ; Pos after some opening or closing paren. paren+1s ; A list of `paren+1's; used to determine a ; good-pos. - bra+1 ce+1 ; just after L/R bra-ces. + bra+1 ; just after L bra-ce. bra+1s ; list of OLD values of bra+1. mstart) ; start of a macro. @@ -2801,9 +2806,9 @@ ;; are no more b/b/p's to scan. (c-safe (while t - (setq pa+1 (scan-lists ren+1 1 -1) ; Into (/{/[; might signal + (setq pa+1 (c-sc-scan-lists ren+1 1 -1) ; Into (/{/[; might signal paren+1s (cons pa+1 paren+1s)) - (setq ren+1 (scan-lists pa+1 1 1)) ; Out of )/}/]; might signal + (setq ren+1 (c-sc-scan-lists pa+1 1 1)) ; Out of )/}/]; might signal (if (and (eq (char-before pa+1) ?{)) ; Check for a macro later. (setq bra+1 pa+1)) (setcar paren+1s ren+1))) @@ -2827,7 +2832,7 @@ ;; finished - we just need to check for having found an ;; unmatched )/}/], which we ignore. Such a )/}/] can't be in a ;; macro, due the action of `c-neutralize-syntax-in-CPP'. - (c-safe (setq ren+1 (scan-lists ren+1 1 1)))))) ; acts as loop control. + (c-safe (setq ren+1 (c-sc-scan-lists ren+1 1 1)))))) ; acts as loop control. ;; Record the final, innermost, brace-pair if there is one. (c-state-push-any-brace-pair bra+1 macro-start-or-here) @@ -2954,7 +2959,7 @@ ;; Scan! (setq pps-state - (parse-partial-sexp + (c-sc-parse-partial-sexp (point) (if (< (point) pps-point) pps-point here) target-depth nil pps-state)) @@ -2985,9 +2990,10 @@ ))) (if (< (point) pps-point) - (setq pps-state (parse-partial-sexp (point) pps-point - nil nil ; TARGETDEPTH, STOPBEFORE - pps-state))) + (setq pps-state (c-sc-parse-partial-sexp + (point) pps-point + nil nil ; TARGETDEPTH, STOPBEFORE + pps-state))) ;; If the last paren pair we moved out of was actually a brace pair, ;; insert it into `c-state-cache'. @@ -3108,12 +3114,15 @@ (save-restriction (narrow-to-region here-bol (point-max)) (setq pos here-lit-start) - (c-safe (while (setq pa (scan-lists pos -1 1)) + (c-safe (while (setq pa (c-sc-scan-lists pos -1 1)) (setq pos pa)))) ; might signal nil)) ; for the cond - ((setq ren (c-safe-scan-lists pos -1 -1 too-far-back)) - ;; CASE 3: After a }/)/] before `here''s BOL. + ((save-restriction + (narrow-to-region too-far-back (point-max)) + (setq ren (c-safe (c-sc-scan-lists pos -1 -1)))) + + ;; CASE 3: After a }/)/] before `here''s BOL. (list (1+ ren) (and dropped-cons pos) nil)) ; Return value (t @@ -3335,15 +3344,19 @@ ;; of all parens in preprocessor constructs, except for any such construct ;; containing point. We can then call `c-invalidate-state-cache-1' without ;; worrying further about macros and template delimiters. - (c-with-<->-as-parens-suppressed - (if (and c-state-old-cpp-beg - (< c-state-old-cpp-beg here)) - (c-with-all-but-one-cpps-commented-out - c-state-old-cpp-beg - (min c-state-old-cpp-end here) - (c-invalidate-state-cache-1 here)) - (c-with-cpps-commented-out - (c-invalidate-state-cache-1 here))))) + (if (eval-when-compile (memq 'category-properties c-emacs-features)) + ;; Emacs + (c-with-<->-as-parens-suppressed + (if (and c-state-old-cpp-beg + (< c-state-old-cpp-beg here)) + (c-with-all-but-one-cpps-commented-out + c-state-old-cpp-beg + (min c-state-old-cpp-end here) + (c-invalidate-state-cache-1 here)) + (c-with-cpps-commented-out + (c-invalidate-state-cache-1 here)))) + ;; XEmacs + (c-invalidate-state-cache-1 here))) (defmacro c-state-maybe-marker (place marker) ;; If PLACE is non-nil, return a marker marking it, otherwise nil. @@ -3371,13 +3384,17 @@ ;; FIXME!!! Put in a `condition-case' here to protect the integrity of the ;; subsystem. (prog1 - (c-with-<->-as-parens-suppressed - (if (and here-cpp-beg (> here-cpp-end here-cpp-beg)) - (c-with-all-but-one-cpps-commented-out - here-cpp-beg here-cpp-end - (c-parse-state-1)) - (c-with-cpps-commented-out - (c-parse-state-1)))) + (if (eval-when-compile (memq 'category-properties c-emacs-features)) + ;; Emacs + (c-with-<->-as-parens-suppressed + (if (and here-cpp-beg (> here-cpp-end here-cpp-beg)) + (c-with-all-but-one-cpps-commented-out + here-cpp-beg here-cpp-end + (c-parse-state-1)) + (c-with-cpps-commented-out + (c-parse-state-1)))) + ;; XEmacs + (c-parse-state-1)) (setq c-state-old-cpp-beg (c-state-maybe-marker here-cpp-beg c-state-old-cpp-beg-marker) c-state-old-cpp-end @@ -3392,6 +3409,7 @@ (defvar c-parse-state-point nil) (defvar c-parse-state-state nil) +(make-variable-buffer-local 'c-parse-state-state) (defun c-record-parse-state-state () (setq c-parse-state-point (point)) (setq c-parse-state-state @@ -3399,9 +3417,9 @@ (lambda (arg) (let ((val (symbol-value arg))) (cons arg - (if (consp val) - (copy-tree val) - val)))) + (cond ((consp val) (copy-tree val)) + ((markerp val) (copy-marker val)) + (t val))))) '(c-state-cache c-state-cache-good-pos c-state-nonlit-pos-cache @@ -3421,7 +3439,11 @@ (concat "(setq " (mapconcat (lambda (arg) - (format "%s %s%s" (car arg) (if (atom (cdr arg)) "" "'") (cdr arg))) + (format "%s %s%s" (car arg) + (if (atom (cdr arg)) "" "'") + (if (markerp (cdr arg)) + (format "(copy-marker %s)" (marker-position (cdr arg))) + (cdr arg)))) c-parse-state-state " ") ")"))) @@ -4156,8 +4178,7 @@ (goto-char bound)) nil))) -(defvar safe-pos-list) ; bound in c-syntactic-skip-backward - +(cc-bytecomp-defvar safe-pos-list) ; bound in c-syntactic-skip-backward (defsubst c-ssb-lit-begin () ;; Return the start of the literal point is in, or nil. ;; We read and write the variables `safe-pos', `safe-pos-list', `state' @@ -4166,7 +4187,7 @@ ;; Use `parse-partial-sexp' from a safe position down to the point to check ;; if it's outside comments and strings. (save-excursion - (let ((pos (point)) safe-pos state pps-end-pos) + (let ((pos (point)) safe-pos state) ;; Pick a safe position as close to the point as possible. ;; ;; FIXME: Consult `syntax-ppss' here if our cache doesn't give a good @@ -4765,7 +4786,7 @@ (unless cfd-prop-match (save-excursion (while (progn - (goto-char (next-single-property-change + (goto-char (c-next-single-property-change (point) 'c-type nil cfd-limit)) (and (< (point) cfd-limit) (not (eq (c-get-char-property (1- (point)) 'c-type) @@ -4805,7 +4826,7 @@ ;; Pseudo match inside a comment or string literal. Skip out ;; of comments and string literals. (while (progn - (goto-char (next-single-property-change + (goto-char (c-next-single-property-change (point) 'face nil cfd-limit)) (and (< (point) cfd-limit) (c-got-face-at (point) c-literal-faces)))) @@ -4860,14 +4881,17 @@ ;; it should return non-nil to ensure that the next search will find them. ;; ;; Such a spot is: - ;; o The first token after bob. - ;; o The first token after the end of submatch 1 in - ;; `c-decl-prefix-or-start-re' when that submatch matches. - ;; o The start of each `c-decl-prefix-or-start-re' match when - ;; submatch 1 doesn't match. - ;; o The first token after the end of each occurrence of the - ;; `c-type' text property with the value `c-decl-end', provided - ;; `c-type-decl-end-used' is set. + ;; o The first token after bob. + ;; o The first token after the end of submatch 1 in + ;; `c-decl-prefix-or-start-re' when that submatch matches. This + ;; submatch is typically a (L or R) brace or paren, a ;, or a ,. + ;; o The start of each `c-decl-prefix-or-start-re' match when + ;; submatch 1 doesn't match. This is, for example, the keyword + ;; "class" in Pike. + ;; o The start of a previously recognized declaration; "recognized" + ;; means that the last char of the previous token has a `c-type' + ;; text property with the value `c-decl-end'; this only holds + ;; when `c-type-decl-end-used' is set. ;; ;; Only a spot that match CFD-DECL-RE and whose face is in the ;; CFD-FACE-CHECKLIST list causes CFD-FUN to be called. The face @@ -4899,7 +4923,7 @@ ;; ;; This function might do hidden buffer changes. - (let ((cfd-start-pos (point)) + (let ((cfd-start-pos (point)) ; never changed (cfd-buffer-end (point-max)) ;; The end of the token preceding the decl spot last found ;; with `c-decl-prefix-or-start-re'. `cfd-limit' if there's @@ -4913,7 +4937,16 @@ ;; `c-find-decl-prefix-search'. `cfd-limit' if there's no ;; match. If searching for the property isn't needed then we ;; disable it by setting it to `cfd-limit' directly. - (cfd-prop-match (unless c-type-decl-end-used cfd-limit)) + (cfd-prop-match + (if c-type-decl-end-used + (save-excursion + (c-backward-syntactic-ws) + (and + (not (bobp)) + (eq (c-get-char-property (1- (point)) 'c-type) + 'c-decl-end) + (point))) + cfd-limit)) ;; The end of the token preceding the decl spot last found by ;; `c-find-decl-prefix-search'. 0 for the implicit match at ;; bob. `cfd-limit' if there's no match. In other words, @@ -4938,10 +4971,20 @@ ;; statement or declaration, which is earlier than the first ;; returned match. + ;; This `cond' moves back over any literals or macros. It has special + ;; handling for when the region being searched is entirely within a + ;; macro. It sets `cfd-continue-pos' (unless we've reached + ;; `cfd-limit'). (cond ;; First we need to move to a syntactically relevant position. ;; Begin by backing out of comment or string literals. + ;; + ;; This arm of the cond actually triggers if we're in a literal, + ;; and cfd-limit is at most at BONL. ((and + ;; This arm of the `and' moves backwards out of a literal when + ;; the face at point is a literal face. In this case, its value + ;; is always non-nil. (when (c-got-face-at (point) c-literal-faces) ;; Try to use the faces to back up to the start of the ;; literal. FIXME: What if the point is on a declaration @@ -4970,7 +5013,7 @@ (let ((range (c-literal-limits))) (if range (goto-char (car range))))) - (setq start-in-literal (point))) + (setq start-in-literal (point))) ; end of `and' arm. ;; The start is in a literal. If the limit is in the same ;; one we don't have to find a syntactic position etc. We @@ -4981,22 +5024,22 @@ (save-excursion (goto-char cfd-start-pos) (while (progn - (goto-char (next-single-property-change + (goto-char (c-next-single-property-change (point) 'face nil cfd-limit)) (and (< (point) cfd-limit) (c-got-face-at (point) c-literal-faces)))) - (= (point) cfd-limit))) + (= (point) cfd-limit))) ; end of `cond' arm condition ;; Completely inside a literal. Set up variables to trig the ;; (< cfd-continue-pos cfd-start-pos) case below and it'll ;; find a suitable start position. - (setq cfd-continue-pos start-in-literal)) + (setq cfd-continue-pos start-in-literal)) ; end of `cond' arm ;; Check if the region might be completely inside a macro, to ;; optimize that like the completely-inside-literal above. ((save-excursion (and (= (forward-line 1) 0) - (bolp) ; forward-line has funny behavior at eob. + (bolp) ; forward-line has funny behavior at eob. (>= (point) cfd-limit) (progn (backward-char) (eq (char-before) ?\\)))) @@ -5006,6 +5049,8 @@ (setq cfd-continue-pos (1- cfd-start-pos) start-in-macro t)) + ;; The default arm of the `cond' moves back over any macro we're in + ;; and over any syntactic WS. It sets `c-find-decl-syntactic-pos'. (t ;; Back out of any macro so we don't miss any declaration ;; that could follow after it. @@ -5052,10 +5097,10 @@ (< (point) cfd-limit)) ;; Do an initial search now. In the bob case above it's ;; only done to search for a `c-decl-end' spot. - (c-find-decl-prefix-search)) + (c-find-decl-prefix-search)) ; sets cfd-continue-pos (setq c-find-decl-match-pos (and (< cfd-match-pos cfd-start-pos) - cfd-match-pos))))) + cfd-match-pos))))) ; end of `cond' ;; Advance `cfd-continue-pos' if it's before the start position. ;; The closest continue position that might have effect at or @@ -5114,7 +5159,7 @@ ;; `cfd-match-pos' so we can continue at the start position. ;; (Note that we don't get here if the first match is below ;; it.) - (goto-char cfd-start-pos))) + (goto-char cfd-start-pos))) ; end of `cond' ;; Delete found matches if they are before our new continue ;; position, so that `c-find-decl-prefix-search' won't back up @@ -5123,7 +5168,7 @@ (when (and cfd-re-match (< cfd-re-match cfd-continue-pos)) (setq cfd-re-match nil)) (when (and cfd-prop-match (< cfd-prop-match cfd-continue-pos)) - (setq cfd-prop-match nil))) + (setq cfd-prop-match nil))) ; end of `when' (if syntactic-pos ;; This is the normal case and we got a proper syntactic @@ -5144,9 +5189,10 @@ ;; good start position for the search, so do it. (c-find-decl-prefix-search))) - ;; Now loop. Round what? (ACM, 2006/7/5). We already got the first match. - + ;; Now loop, one decl spot per iteration. We already have the first + ;; match in `cfd-match-pos'. (while (progn + ;; Go foward over "false matches", one per iteration. (while (and (< cfd-match-pos cfd-limit) @@ -5187,10 +5233,10 @@ (goto-char cfd-continue-pos) t))) - (< (point) cfd-limit)) - (c-find-decl-prefix-search)) + (< (point) cfd-limit)) ; end of "false matches" condition + (c-find-decl-prefix-search)) ; end of "false matches" loop - (< (point) cfd-limit)) + (< (point) cfd-limit)) ; end of condition for "decl-spot" while (when (and (>= (point) cfd-start-pos) @@ -5218,7 +5264,7 @@ ;; The matched token was the last thing in the macro, ;; so the whole match is bogus. (setq cfd-macro-end 0) - nil)))) + nil)))) ; end of when condition (c-debug-put-decl-spot-faces cfd-match-pos (point)) (if (funcall cfd-fun cfd-match-pos (/= cfd-macro-end 0)) @@ -5398,8 +5444,8 @@ (c-go-list-forward)) (when (equal (c-get-char-property (1- (point)) 'syntax-table) c->-as-paren-syntax) ; should always be true. - (c-clear-char-property (1- (point)) 'category)) - (c-clear-char-property pos 'category)))) + (c-unmark-<->-as-paren (1- (point)))) + (c-unmark-<->-as-paren pos)))) (defun c-clear->-pair-props (&optional pos) ;; POS (default point) is at a > character. If it is marked with @@ -5415,8 +5461,8 @@ (c-go-up-list-backward)) (when (equal (c-get-char-property (point) 'syntax-table) c-<-as-paren-syntax) ; should always be true. - (c-clear-char-property (point) 'category)) - (c-clear-char-property pos 'category)))) + (c-unmark-<->-as-paren (point))) + (c-unmark-<->-as-paren pos)))) (defun c-clear-<>-pair-props (&optional pos) ;; POS (default point) is at a < or > character. If it has an @@ -5505,9 +5551,10 @@ (c-syntactic-skip-backward "^;{}" (c-determine-limit 512)) (setq new-beg (point)) - ;; Remove the syntax-table properties from each pertinent <...> pair. - ;; Firsly, the ones with the < before beg and > after beg. - (while (c-search-forward-char-property 'category 'c-<-as-paren-syntax beg) + ;; Remove the syntax-table/category properties from each pertinent <...> + ;; pair. Firsly, the ones with the < before beg and > after beg. + (while + (c-search-forward-char-property 'syntax-table c-<-as-paren-syntax beg) (if (c-clear-<-pair-props-if-match-after beg (1- (point))) (setq need-new-beg t))) @@ -5518,7 +5565,7 @@ ;; Remove syntax-table properties from the remaining pertinent <...> ;; pairs, those with a > after end and < before end. - (while (c-search-backward-char-property 'category 'c->-as-paren-syntax end) + (while (c-search-backward-char-property 'syntax-table c->-as-paren-syntax end) (if (c-clear->-pair-props-if-match-before end) (setq need-new-end t))) @@ -5531,8 +5578,6 @@ (when need-new-end (and (> new-end c-new-END) (setq c-new-END new-end)))))) - - (defun c-after-change-check-<>-operators (beg end) ;; This is called from `after-change-functions' when ;; c-recognize-<>-arglists' is set. It ensures that no "<" or ">" @@ -5867,7 +5912,6 @@ ;; Recursive part of `c-forward-<>-arglist'. ;; ;; This function might do hidden buffer changes. - (let ((start (point)) res pos tmp ;; Cover this so that any recorded found type ranges are ;; automatically lost if it turns out to not be an angle @@ -5903,32 +5947,31 @@ (while (and (progn (c-forward-syntactic-ws) - (let ((orig-record-found-types c-record-found-types)) - (when (or (and c-record-type-identifiers all-types) - (c-major-mode-is 'java-mode)) - ;; All encountered identifiers are types, so set the - ;; promote flag and parse the type. - (progn - (c-forward-syntactic-ws) - (if (looking-at "\\?") - (forward-char) - (when (looking-at c-identifier-start) - (let ((c-promote-possible-types t) - (c-record-found-types t)) - (c-forward-type)))) - - (c-forward-syntactic-ws) - - (when (or (looking-at "extends") - (looking-at "super")) - (forward-word) - (c-forward-syntactic-ws) + (when (or (and c-record-type-identifiers all-types) + (c-major-mode-is 'java-mode)) + ;; All encountered identifiers are types, so set the + ;; promote flag and parse the type. + (progn + (c-forward-syntactic-ws) + (if (looking-at "\\?") + (forward-char) + (when (looking-at c-identifier-start) (let ((c-promote-possible-types t) (c-record-found-types t)) - (c-forward-type) - (c-forward-syntactic-ws)))))) - - (setq pos (point)) ; e.g. first token inside the '<' + (c-forward-type)))) + + (c-forward-syntactic-ws) + + (when (or (looking-at "extends") + (looking-at "super")) + (forward-word) + (c-forward-syntactic-ws) + (let ((c-promote-possible-types t) + (c-record-found-types t)) + (c-forward-type) + (c-forward-syntactic-ws))))) + + (setq pos (point)) ; e.g. first token inside the '<' ;; Note: These regexps exploit the match order in \| so ;; that "<>" is matched by "<" rather than "[^>:-]>". @@ -5993,7 +6036,6 @@ (c-keyword-member (c-keyword-sym (match-string 1)) 'c-<>-type-kwds))))))) - ;; It was an angle bracket arglist. (setq c-record-found-types subres) @@ -6449,6 +6491,7 @@ (goto-char (match-end 1)) (c-forward-syntactic-ws) (setq res t))) + ;; Step over any type suffix operator. Do not let the existence ;; of these alter the classification of the found type, since ;; these operators typically are allowed in normal expressions @@ -7100,36 +7143,35 @@ (catch 'at-decl-or-cast ;; CASE 1 - (when (> paren-depth 0) - ;; Encountered something inside parens that isn't matched by - ;; the `c-type-decl-*' regexps, so it's not a type decl - ;; expression. Try to skip out to the same paren depth to - ;; not confuse the cast check below. - (c-safe (goto-char (scan-lists (point) 1 paren-depth))) - ;; If we've found a specifier keyword then it's a - ;; declaration regardless. - (throw 'at-decl-or-cast (eq at-decl-or-cast t))) - - (setq at-decl-end - (looking-at (cond ((eq context '<>) "[,>]") - (context "[,\)]") - (t "[,;]")))) - - ;; Now we've collected info about various characteristics of - ;; the construct we're looking at. Below follows a decision - ;; tree based on that. It's ordered to check more certain - ;; signs before less certain ones. - - (if got-identifier - (progn - - ;; CASE 2 - (when (and (or at-type maybe-typeless) - (not (or got-prefix got-parens))) - ;; Got another identifier directly after the type, so it's a - ;; declaration. - (throw 'at-decl-or-cast t)) - + (when (> paren-depth 0) + ;; Encountered something inside parens that isn't matched by + ;; the `c-type-decl-*' regexps, so it's not a type decl + ;; expression. Try to skip out to the same paren depth to + ;; not confuse the cast check below. + (c-safe (goto-char (scan-lists (point) 1 paren-depth))) + ;; If we've found a specifier keyword then it's a + ;; declaration regardless. + (throw 'at-decl-or-cast (eq at-decl-or-cast t))) + + (setq at-decl-end + (looking-at (cond ((eq context '<>) "[,>]") + (context "[,\)]") + (t "[,;]")))) + + ;; Now we've collected info about various characteristics of + ;; the construct we're looking at. Below follows a decision + ;; tree based on that. It's ordered to check more certain + ;; signs before less certain ones. + + (if got-identifier + (progn + + ;; CASE 2 + (when (and (or at-type maybe-typeless) + (not (or got-prefix got-parens))) + ;; Got another identifier directly after the type, so it's a + ;; declaration. + (throw 'at-decl-or-cast t)) (when (and got-parens (not got-prefix) @@ -7151,9 +7193,9 @@ (c-fdoc-shift-type-backward))) ;; Found no identifier. - (if backup-at-type - (progn + (if backup-at-type + (progn ;; CASE 3 (when (= (point) start) @@ -7176,251 +7218,251 @@ (setq backup-if-not-cast t) (throw 'at-decl-or-cast t))) - ;; CASE 4 - (when (and got-suffix - (not got-prefix) - (not got-parens)) - ;; Got a plain list of identifiers followed by some suffix. - ;; If this isn't a cast then the last identifier probably is - ;; the declared one and we should back up to the previous - ;; type. - (setq backup-if-not-cast t) - (throw 'at-decl-or-cast t))) - - ;; CASE 5 - (when (eq at-type t) - ;; If the type is known we know that there can't be any - ;; identifier somewhere else, and it's only in declarations in - ;; e.g. function prototypes and in casts that the identifier may - ;; be left out. - (throw 'at-decl-or-cast t)) - - (when (= (point) start) - ;; Only got a single identifier (parsed as a type so far). - ;; CASE 6 - (if (and - ;; Check that the identifier isn't at the start of an - ;; expression. - at-decl-end - (cond - ((eq context 'decl) - ;; Inside an arglist that contains declarations. If K&R - ;; style declarations and parenthesis style initializers - ;; aren't allowed then the single identifier must be a - ;; type, else we require that it's known or found - ;; (primitive types are handled above). - (or (and (not c-recognize-knr-p) - (not c-recognize-paren-inits)) - (memq at-type '(known found)))) - ((eq context '<>) - ;; Inside a template arglist. Accept known and found - ;; types; other identifiers could just as well be - ;; constants in C++. - (memq at-type '(known found))))) - (throw 'at-decl-or-cast t) - ;; CASE 7 - ;; Can't be a valid declaration or cast, but if we've found a - ;; specifier it can't be anything else either, so treat it as - ;; an invalid/unfinished declaration or cast. - (throw 'at-decl-or-cast at-decl-or-cast)))) - - (if (and got-parens - (not got-prefix) - (not context) - (not (eq at-type t)) - (or backup-at-type - maybe-typeless - backup-maybe-typeless - (when c-recognize-typeless-decls - (or (not got-suffix) - (not (looking-at - c-after-suffixed-type-maybe-decl-key)))))) - ;; Got an empty paren pair and a preceding type that probably - ;; really is the identifier. Shift the type backwards to make - ;; the last one the identifier. This is analogous to the - ;; "backtracking" done inside the `c-type-decl-suffix-key' loop - ;; above. - ;; - ;; Exception: In addition to the conditions in that - ;; "backtracking" code, do not shift backward if we're not - ;; looking at either `c-after-suffixed-type-decl-key' or "[;,]". - ;; Since there's no preceding type, the shift would mean that - ;; the declaration is typeless. But if the regexp doesn't match - ;; then we will simply fall through in the tests below and not - ;; recognize it at all, so it's better to try it as an abstract - ;; declarator instead. - (c-fdoc-shift-type-backward) - - ;; Still no identifier. - ;; CASE 8 - (when (and got-prefix (or got-parens got-suffix)) - ;; Require `got-prefix' together with either `got-parens' or - ;; `got-suffix' to recognize it as an abstract declarator: - ;; `got-parens' only is probably an empty function call. - ;; `got-suffix' only can build an ordinary expression together - ;; with the preceding identifier which we've taken as a type. - ;; We could actually accept on `got-prefix' only, but that can - ;; easily occur temporarily while writing an expression so we - ;; avoid that case anyway. We could do a better job if we knew - ;; the point when the fontification was invoked. - (throw 'at-decl-or-cast t)) - - ;; CASE 9 - (when (and at-type - (not got-prefix) - (not got-parens) - got-suffix-after-parens - (eq (char-after got-suffix-after-parens) ?\()) - ;; Got a type, no declarator but a paren suffix. I.e. it's a - ;; normal function call after all (or perhaps a C++ style object - ;; instantiation expression). - (throw 'at-decl-or-cast nil)))) - - ;; CASE 10 - (when at-decl-or-cast - ;; By now we've located the type in the declaration that we know - ;; we're in. - (throw 'at-decl-or-cast t)) - - ;; CASE 11 - (when (and got-identifier - (not context) - (looking-at c-after-suffixed-type-decl-key) - (if (and got-parens - (not got-prefix) - (not got-suffix) - (not (eq at-type t))) - ;; Shift the type backward in the case that there's a - ;; single identifier inside parens. That can only - ;; occur in K&R style function declarations so it's - ;; more likely that it really is a function call. - ;; Therefore we only do this after - ;; `c-after-suffixed-type-decl-key' has matched. - (progn (c-fdoc-shift-type-backward) t) - got-suffix-after-parens)) - ;; A declaration according to `c-after-suffixed-type-decl-key'. - (throw 'at-decl-or-cast t)) - - ;; CASE 12 - (when (and (or got-prefix (not got-parens)) - (memq at-type '(t known))) - ;; It's a declaration if a known type precedes it and it can't be a - ;; function call. - (throw 'at-decl-or-cast t)) - - ;; If we get here we can't tell if this is a type decl or a normal - ;; expression by looking at it alone. (That's under the assumption - ;; that normal expressions always can look like type decl expressions, - ;; which isn't really true but the cases where it doesn't hold are so - ;; uncommon (e.g. some placements of "const" in C++) it's not worth - ;; the effort to look for them.) + ;; CASE 4 + (when (and got-suffix + (not got-prefix) + (not got-parens)) + ;; Got a plain list of identifiers followed by some suffix. + ;; If this isn't a cast then the last identifier probably is + ;; the declared one and we should back up to the previous + ;; type. + (setq backup-if-not-cast t) + (throw 'at-decl-or-cast t))) + + ;; CASE 5 + (when (eq at-type t) + ;; If the type is known we know that there can't be any + ;; identifier somewhere else, and it's only in declarations in + ;; e.g. function prototypes and in casts that the identifier may + ;; be left out. + (throw 'at-decl-or-cast t)) + + (when (= (point) start) + ;; Only got a single identifier (parsed as a type so far). + ;; CASE 6 + (if (and + ;; Check that the identifier isn't at the start of an + ;; expression. + at-decl-end + (cond + ((eq context 'decl) + ;; Inside an arglist that contains declarations. If K&R + ;; style declarations and parenthesis style initializers + ;; aren't allowed then the single identifier must be a + ;; type, else we require that it's known or found + ;; (primitive types are handled above). + (or (and (not c-recognize-knr-p) + (not c-recognize-paren-inits)) + (memq at-type '(known found)))) + ((eq context '<>) + ;; Inside a template arglist. Accept known and found + ;; types; other identifiers could just as well be + ;; constants in C++. + (memq at-type '(known found))))) + (throw 'at-decl-or-cast t) + ;; CASE 7 + ;; Can't be a valid declaration or cast, but if we've found a + ;; specifier it can't be anything else either, so treat it as + ;; an invalid/unfinished declaration or cast. + (throw 'at-decl-or-cast at-decl-or-cast)))) + + (if (and got-parens + (not got-prefix) + (not context) + (not (eq at-type t)) + (or backup-at-type + maybe-typeless + backup-maybe-typeless + (when c-recognize-typeless-decls + (or (not got-suffix) + (not (looking-at + c-after-suffixed-type-maybe-decl-key)))))) + ;; Got an empty paren pair and a preceding type that probably + ;; really is the identifier. Shift the type backwards to make + ;; the last one the identifier. This is analogous to the + ;; "backtracking" done inside the `c-type-decl-suffix-key' loop + ;; above. + ;; + ;; Exception: In addition to the conditions in that + ;; "backtracking" code, do not shift backward if we're not + ;; looking at either `c-after-suffixed-type-decl-key' or "[;,]". + ;; Since there's no preceding type, the shift would mean that + ;; the declaration is typeless. But if the regexp doesn't match + ;; then we will simply fall through in the tests below and not + ;; recognize it at all, so it's better to try it as an abstract + ;; declarator instead. + (c-fdoc-shift-type-backward) + + ;; Still no identifier. + ;; CASE 8 + (when (and got-prefix (or got-parens got-suffix)) + ;; Require `got-prefix' together with either `got-parens' or + ;; `got-suffix' to recognize it as an abstract declarator: + ;; `got-parens' only is probably an empty function call. + ;; `got-suffix' only can build an ordinary expression together + ;; with the preceding identifier which we've taken as a type. + ;; We could actually accept on `got-prefix' only, but that can + ;; easily occur temporarily while writing an expression so we + ;; avoid that case anyway. We could do a better job if we knew + ;; the point when the fontification was invoked. + (throw 'at-decl-or-cast t)) + + ;; CASE 9 + (when (and at-type + (not got-prefix) + (not got-parens) + got-suffix-after-parens + (eq (char-after got-suffix-after-parens) ?\()) + ;; Got a type, no declarator but a paren suffix. I.e. it's a + ;; normal function call after all (or perhaps a C++ style object + ;; instantiation expression). + (throw 'at-decl-or-cast nil)))) + + ;; CASE 10 + (when at-decl-or-cast + ;; By now we've located the type in the declaration that we know + ;; we're in. + (throw 'at-decl-or-cast t)) + + ;; CASE 11 + (when (and got-identifier + (not context) + (looking-at c-after-suffixed-type-decl-key) + (if (and got-parens + (not got-prefix) + (not got-suffix) + (not (eq at-type t))) + ;; Shift the type backward in the case that there's a + ;; single identifier inside parens. That can only + ;; occur in K&R style function declarations so it's + ;; more likely that it really is a function call. + ;; Therefore we only do this after + ;; `c-after-suffixed-type-decl-key' has matched. + (progn (c-fdoc-shift-type-backward) t) + got-suffix-after-parens)) + ;; A declaration according to `c-after-suffixed-type-decl-key'. + (throw 'at-decl-or-cast t)) + + ;; CASE 12 + (when (and (or got-prefix (not got-parens)) + (memq at-type '(t known))) + ;; It's a declaration if a known type precedes it and it can't be a + ;; function call. + (throw 'at-decl-or-cast t)) + + ;; If we get here we can't tell if this is a type decl or a normal + ;; expression by looking at it alone. (That's under the assumption + ;; that normal expressions always can look like type decl expressions, + ;; which isn't really true but the cases where it doesn't hold are so + ;; uncommon (e.g. some placements of "const" in C++) it's not worth + ;; the effort to look for them.) ;;; 2008-04-16: commented out the next form, to allow the function to recognize ;;; "foo (int bar)" in CC (an implicit type (in class foo) without a semicolon) ;;; as a(n almost complete) declaration, enabling it to be fontified. - ;; CASE 13 - ;; (unless (or at-decl-end (looking-at "=[^=]")) - ;; If this is a declaration it should end here or its initializer(*) - ;; should start here, so check for allowed separation tokens. Note - ;; that this rule doesn't work e.g. with a K&R arglist after a - ;; function header. - ;; - ;; *) Don't check for C++ style initializers using parens - ;; since those already have been matched as suffixes. - ;; - ;; If `at-decl-or-cast' is then we've found some other sign that - ;; it's a declaration or cast, so then it's probably an - ;; invalid/unfinished one. - ;; (throw 'at-decl-or-cast at-decl-or-cast)) - - ;; Below are tests that only should be applied when we're certain to - ;; not have parsed halfway through an expression. - - ;; CASE 14 - (when (memq at-type '(t known)) - ;; The expression starts with a known type so treat it as a - ;; declaration. - (throw 'at-decl-or-cast t)) - - ;; CASE 15 - (when (and (c-major-mode-is 'c++-mode) - ;; In C++ we check if the identifier is a known type, since - ;; (con|de)structors use the class name as identifier. - ;; We've always shifted over the identifier as a type and - ;; then backed up again in this case. - identifier-type - (or (memq identifier-type '(found known)) - (and (eq (char-after identifier-start) ?~) - ;; `at-type' probably won't be 'found for - ;; destructors since the "~" is then part of the - ;; type name being checked against the list of - ;; known types, so do a check without that - ;; operator. - (or (save-excursion - (goto-char (1+ identifier-start)) - (c-forward-syntactic-ws) - (c-with-syntax-table - c-identifier-syntax-table - (looking-at c-known-type-key))) - (save-excursion - (goto-char (1+ identifier-start)) - ;; We have already parsed the type earlier, - ;; so it'd be possible to cache the end - ;; position instead of redoing it here, but - ;; then we'd need to keep track of another - ;; position everywhere. - (c-check-type (point) - (progn (c-forward-type) - (point)))))))) - (throw 'at-decl-or-cast t)) - - (if got-identifier - (progn - ;; CASE 16 - (when (and got-prefix-before-parens - at-type - (or at-decl-end (looking-at "=[^=]")) - (not context) - (not got-suffix)) - ;; Got something like "foo * bar;". Since we're not inside an - ;; arglist it would be a meaningless expression because the - ;; result isn't used. We therefore choose to recognize it as - ;; a declaration. Do not allow a suffix since it could then - ;; be a function call. - (throw 'at-decl-or-cast t)) - - ;; CASE 17 - (when (and (or got-suffix-after-parens - (looking-at "=[^=]")) - (eq at-type 'found) - (not (eq context 'arglist))) - ;; Got something like "a (*b) (c);" or "a (b) = c;". It could - ;; be an odd expression or it could be a declaration. Treat - ;; it as a declaration if "a" has been used as a type - ;; somewhere else (if it's a known type we won't get here). - (throw 'at-decl-or-cast t))) - - ;; CASE 18 - (when (and context - (or got-prefix - (and (eq context 'decl) - (not c-recognize-paren-inits) - (or got-parens got-suffix)))) - ;; Got a type followed by an abstract declarator. If `got-prefix' - ;; is set it's something like "a *" without anything after it. If - ;; `got-parens' or `got-suffix' is set it's "a()", "a[]", "a()[]", - ;; or similar, which we accept only if the context rules out - ;; expressions. - (throw 'at-decl-or-cast t))) - - ;; If we had a complete symbol table here (which rules out - ;; `c-found-types') we should return t due to the disambiguation rule - ;; (in at least C++) that anything that can be parsed as a declaration - ;; is a declaration. Now we're being more defensive and prefer to - ;; highlight things like "foo (bar);" as a declaration only if we're - ;; inside an arglist that contains declarations. - ;; CASE 19 - (eq context 'decl)))) + ;; CASE 13 + ;; (unless (or at-decl-end (looking-at "=[^=]")) + ;; If this is a declaration it should end here or its initializer(*) + ;; should start here, so check for allowed separation tokens. Note + ;; that this rule doesn't work e.g. with a K&R arglist after a + ;; function header. + ;; + ;; *) Don't check for C++ style initializers using parens + ;; since those already have been matched as suffixes. + ;; + ;; If `at-decl-or-cast' is then we've found some other sign that + ;; it's a declaration or cast, so then it's probably an + ;; invalid/unfinished one. + ;; (throw 'at-decl-or-cast at-decl-or-cast)) + + ;; Below are tests that only should be applied when we're certain to + ;; not have parsed halfway through an expression. + + ;; CASE 14 + (when (memq at-type '(t known)) + ;; The expression starts with a known type so treat it as a + ;; declaration. + (throw 'at-decl-or-cast t)) + + ;; CASE 15 + (when (and (c-major-mode-is 'c++-mode) + ;; In C++ we check if the identifier is a known type, since + ;; (con|de)structors use the class name as identifier. + ;; We've always shifted over the identifier as a type and + ;; then backed up again in this case. + identifier-type + (or (memq identifier-type '(found known)) + (and (eq (char-after identifier-start) ?~) + ;; `at-type' probably won't be 'found for + ;; destructors since the "~" is then part of the + ;; type name being checked against the list of + ;; known types, so do a check without that + ;; operator. + (or (save-excursion + (goto-char (1+ identifier-start)) + (c-forward-syntactic-ws) + (c-with-syntax-table + c-identifier-syntax-table + (looking-at c-known-type-key))) + (save-excursion + (goto-char (1+ identifier-start)) + ;; We have already parsed the type earlier, + ;; so it'd be possible to cache the end + ;; position instead of redoing it here, but + ;; then we'd need to keep track of another + ;; position everywhere. + (c-check-type (point) + (progn (c-forward-type) + (point)))))))) + (throw 'at-decl-or-cast t)) + + (if got-identifier + (progn + ;; CASE 16 + (when (and got-prefix-before-parens + at-type + (or at-decl-end (looking-at "=[^=]")) + (not context) + (not got-suffix)) + ;; Got something like "foo * bar;". Since we're not inside an + ;; arglist it would be a meaningless expression because the + ;; result isn't used. We therefore choose to recognize it as + ;; a declaration. Do not allow a suffix since it could then + ;; be a function call. + (throw 'at-decl-or-cast t)) + + ;; CASE 17 + (when (and (or got-suffix-after-parens + (looking-at "=[^=]")) + (eq at-type 'found) + (not (eq context 'arglist))) + ;; Got something like "a (*b) (c);" or "a (b) = c;". It could + ;; be an odd expression or it could be a declaration. Treat + ;; it as a declaration if "a" has been used as a type + ;; somewhere else (if it's a known type we won't get here). + (throw 'at-decl-or-cast t))) + + ;; CASE 18 + (when (and context + (or got-prefix + (and (eq context 'decl) + (not c-recognize-paren-inits) + (or got-parens got-suffix)))) + ;; Got a type followed by an abstract declarator. If `got-prefix' + ;; is set it's something like "a *" without anything after it. If + ;; `got-parens' or `got-suffix' is set it's "a()", "a[]", "a()[]", + ;; or similar, which we accept only if the context rules out + ;; expressions. + (throw 'at-decl-or-cast t))) + + ;; If we had a complete symbol table here (which rules out + ;; `c-found-types') we should return t due to the disambiguation rule + ;; (in at least C++) that anything that can be parsed as a declaration + ;; is a declaration. Now we're being more defensive and prefer to + ;; highlight things like "foo (bar);" as a declaration only if we're + ;; inside an arglist that contains declarations. + ;; CASE 19 + (eq context 'decl)))) ;; The point is now after the type decl expression. @@ -7609,10 +7651,10 @@ (c-put-c-type-property (1- (point)) 'c-decl-end) t) - ;; It's an unfinished label. We consider the keyword enough - ;; to recognize it as a label, so that it gets fontified. - ;; Leave the point at the end of it, but don't put any - ;; `c-decl-end' marker. + ;; It's an unfinished label. We consider the keyword enough + ;; to recognize it as a label, so that it gets fontified. + ;; Leave the point at the end of it, but don't put any + ;; `c-decl-end' marker. (goto-char kwd-end) t)))) @@ -7797,69 +7839,69 @@ ;; ;; This function might do hidden buffer changes. - (let ((start (point)) - start-char - (c-promote-possible-types t) - lim - ;; Turn off recognition of angle bracket arglists while parsing - ;; types here since the protocol reference list might then be - ;; considered part of the preceding name or superclass-name. - c-recognize-<>-arglists) - - (if (or - (when (looking-at - (eval-when-compile - (c-make-keywords-re t - (append (c-lang-const c-protection-kwds objc) - '("@end")) - 'objc-mode))) - (goto-char (match-end 1)) - t) - - (and - (looking-at - (eval-when-compile - (c-make-keywords-re t - '("@interface" "@implementation" "@protocol") - 'objc-mode))) - - ;; Handle the name of the class itself. - (progn -; (c-forward-token-2) ; 2006/1/13 This doesn't move if the token's -; at EOB. - (goto-char (match-end 0)) - (setq lim (point)) - (c-skip-ws-forward) - (c-forward-type)) - - (catch 'break - ;; Look for ": superclass-name" or "( category-name )". - (when (looking-at "[:\(]") - (setq start-char (char-after)) - (forward-char) - (c-forward-syntactic-ws) - (unless (c-forward-type) (throw 'break nil)) - (when (eq start-char ?\() - (unless (eq (char-after) ?\)) (throw 'break nil)) - (forward-char) - (c-forward-syntactic-ws))) - - ;; Look for a protocol reference list. - (if (eq (char-after) ?<) - (let ((c-recognize-<>-arglists t) - (c-parse-and-markup-<>-arglists t) - c-restricted-<>-arglists) - (c-forward-<>-arglist t)) - t)))) - - (progn - (c-backward-syntactic-ws lim) - (c-clear-c-type-property start (1- (point)) 'c-decl-end) - (c-put-c-type-property (1- (point)) 'c-decl-end) - t) - - (c-clear-c-type-property start (point) 'c-decl-end) - nil))) + (let ((start (point)) + start-char + (c-promote-possible-types t) + lim + ;; Turn off recognition of angle bracket arglists while parsing + ;; types here since the protocol reference list might then be + ;; considered part of the preceding name or superclass-name. + c-recognize-<>-arglists) + + (if (or + (when (looking-at + (eval-when-compile + (c-make-keywords-re t + (append (c-lang-const c-protection-kwds objc) + '("@end")) + 'objc-mode))) + (goto-char (match-end 1)) + t) + + (and + (looking-at + (eval-when-compile + (c-make-keywords-re t + '("@interface" "@implementation" "@protocol") + 'objc-mode))) + + ;; Handle the name of the class itself. + (progn + ;; (c-forward-token-2) ; 2006/1/13 This doesn't move if the token's + ;; at EOB. + (goto-char (match-end 0)) + (setq lim (point)) + (c-skip-ws-forward) + (c-forward-type)) + + (catch 'break + ;; Look for ": superclass-name" or "( category-name )". + (when (looking-at "[:\(]") + (setq start-char (char-after)) + (forward-char) + (c-forward-syntactic-ws) + (unless (c-forward-type) (throw 'break nil)) + (when (eq start-char ?\() + (unless (eq (char-after) ?\)) (throw 'break nil)) + (forward-char) + (c-forward-syntactic-ws))) + + ;; Look for a protocol reference list. + (if (eq (char-after) ?<) + (let ((c-recognize-<>-arglists t) + (c-parse-and-markup-<>-arglists t) + c-restricted-<>-arglists) + (c-forward-<>-arglist t)) + t)))) + + (progn + (c-backward-syntactic-ws lim) + (c-clear-c-type-property start (1- (point)) 'c-decl-end) + (c-put-c-type-property (1- (point)) 'c-decl-end) + t) + + (c-clear-c-type-property start (point) 'c-decl-end) + nil))) (defun c-beginning-of-inheritance-list (&optional lim) ;; Go to the first non-whitespace after the colon that starts a @@ -7946,7 +7988,7 @@ ;; ;; This function might do hidden buffer changes. - (let ((beg (point)) end id-start) + (let ((beg (point)) id-start) (and (eq (c-beginning-of-statement-1 lim) 'same) @@ -8036,54 +8078,54 @@ (throw 'knr nil))) (if after-rparen - ;; We're inside a paren. Could it be our argument list....? - (if - (and - (progn - (goto-char after-rparen) - (unless (c-go-list-backward) (throw 'knr nil)) ; - ;; FIXME!!! What about macros between the parens? 2007/01/20 - (setq before-lparen (point))) - - ;; It can't be the arg list if next token is ; or { - (progn (goto-char after-rparen) - (c-forward-syntactic-ws) - (not (memq (char-after) '(?\; ?\{ ?\=)))) - - ;; Is the thing preceding the list an identifier (the - ;; function name), or a macro expansion? - (progn - (goto-char before-lparen) - (eq (c-backward-token-2) 0) - (or (eq (c-on-identifier) (point)) - (and (eq (char-after) ?\)) - (c-go-up-list-backward) - (eq (c-backward-token-2) 0) - (eq (c-on-identifier) (point))))) - - ;; Have we got a non-empty list of comma-separated - ;; identifiers? - (progn - (goto-char before-lparen) - (c-forward-token-2) ; to first token inside parens - (and - (c-on-identifier) - (c-forward-token-2) - (catch 'id-list - (while (eq (char-after) ?\,) - (c-forward-token-2) - (unless (c-on-identifier) (throw 'id-list nil)) - (c-forward-token-2)) - (eq (char-after) ?\)))))) - - ;; ...Yes. We've identified the function's argument list. - (throw 'knr - (progn (goto-char after-rparen) - (c-forward-syntactic-ws) - (point))) - - ;; ...No. The current parens aren't the function's arg list. - (goto-char before-lparen)) + ;; We're inside a paren. Could it be our argument list....? + (if + (and + (progn + (goto-char after-rparen) + (unless (c-go-list-backward) (throw 'knr nil)) ; + ;; FIXME!!! What about macros between the parens? 2007/01/20 + (setq before-lparen (point))) + + ;; It can't be the arg list if next token is ; or { + (progn (goto-char after-rparen) + (c-forward-syntactic-ws) + (not (memq (char-after) '(?\; ?\{ ?\=)))) + + ;; Is the thing preceding the list an identifier (the + ;; function name), or a macro expansion? + (progn + (goto-char before-lparen) + (eq (c-backward-token-2) 0) + (or (eq (c-on-identifier) (point)) + (and (eq (char-after) ?\)) + (c-go-up-list-backward) + (eq (c-backward-token-2) 0) + (eq (c-on-identifier) (point))))) + + ;; Have we got a non-empty list of comma-separated + ;; identifiers? + (progn + (goto-char before-lparen) + (c-forward-token-2) ; to first token inside parens + (and + (c-on-identifier) + (c-forward-token-2) + (catch 'id-list + (while (eq (char-after) ?\,) + (c-forward-token-2) + (unless (c-on-identifier) (throw 'id-list nil)) + (c-forward-token-2)) + (eq (char-after) ?\)))))) + + ;; ...Yes. We've identified the function's argument list. + (throw 'knr + (progn (goto-char after-rparen) + (c-forward-syntactic-ws) + (point))) + + ;; ...No. The current parens aren't the function's arg list. + (goto-char before-lparen)) (or (c-go-list-backward) ; backwards over [ .... ] (throw 'knr nil))))))))) @@ -8289,7 +8331,7 @@ (and (progn (while ; keep going back to "[;={"s until we either find - ; no more, or get to one which isn't an "operator =" + ; no more, or get to one which isn't an "operator =" (and (c-syntactic-re-search-forward "[;={]" start t t t) (eq (char-before) ?=) c-overloadable-operators-regexp @@ -8403,10 +8445,7 @@ (when (and c-recognize-<>-arglists (eq (char-before) ?>)) ;; Could be at the end of a template arglist. - (let ((c-parse-and-markup-<>-arglists t) - (c-disallow-comma-in-<>-arglists - (and containing-sexp - (not (eq (char-after containing-sexp) ?{))))) + (let ((c-parse-and-markup-<>-arglists t)) (while (and (c-backward-<>-arglist nil limit) (progn @@ -8612,86 +8651,86 @@ (while (and (not bufpos) containing-sexp) (when paren-state - (if (consp (car paren-state)) - (setq lim (cdr (car paren-state)) - paren-state (cdr paren-state)) - (setq lim (car paren-state))) - (when paren-state - (setq next-containing (car paren-state) - paren-state (cdr paren-state)))) - (goto-char containing-sexp) - (if (c-looking-at-inexpr-block next-containing next-containing) - ;; We're in an in-expression block of some kind. Do not - ;; check nesting. We deliberately set the limit to the - ;; containing sexp, so that c-looking-at-inexpr-block - ;; doesn't check for an identifier before it. - (setq containing-sexp nil) - ;; see if the open brace is preceded by = or [...] in - ;; this statement, but watch out for operator= - (setq braceassignp 'dontknow) - (c-backward-token-2 1 t lim) - ;; Checks to do only on the first sexp before the brace. - (when (and c-opt-inexpr-brace-list-key - (eq (char-after) ?\[)) - ;; In Java, an initialization brace list may follow - ;; directly after "new Foo[]", so check for a "new" - ;; earlier. - (while (eq braceassignp 'dontknow) - (setq braceassignp - (cond ((/= (c-backward-token-2 1 t lim) 0) nil) - ((looking-at c-opt-inexpr-brace-list-key) t) - ((looking-at "\\sw\\|\\s_\\|[.[]") - ;; Carry on looking if this is an - ;; identifier (may contain "." in Java) - ;; or another "[]" sexp. - 'dontknow) - (t nil))))) - ;; Checks to do on all sexps before the brace, up to the - ;; beginning of the statement. - (while (eq braceassignp 'dontknow) - (cond ((eq (char-after) ?\;) - (setq braceassignp nil)) - ((and class-key - (looking-at class-key)) - (setq braceassignp nil)) - ((eq (char-after) ?=) - ;; We've seen a =, but must check earlier tokens so - ;; that it isn't something that should be ignored. - (setq braceassignp 'maybe) - (while (and (eq braceassignp 'maybe) - (zerop (c-backward-token-2 1 t lim))) - (setq braceassignp - (cond - ;; Check for operator = - ((and c-opt-op-identifier-prefix - (looking-at c-opt-op-identifier-prefix)) - nil) - ;; Check for `<opchar>= in Pike. - ((and (c-major-mode-is 'pike-mode) - (or (eq (char-after) ?`) - ;; Special case for Pikes - ;; `[]=, since '[' is not in - ;; the punctuation class. - (and (eq (char-after) ?\[) - (eq (char-before) ?`)))) - nil) - ((looking-at "\\s.") 'maybe) - ;; make sure we're not in a C++ template - ;; argument assignment - ((and - (c-major-mode-is 'c++-mode) - (save-excursion - (let ((here (point)) - (pos< (progn - (skip-chars-backward "^<>") - (point)))) - (and (eq (char-before) ?<) - (not (c-crosses-statement-barrier-p - pos< here)) - (not (c-in-literal)) - )))) - nil) - (t t)))))) + (if (consp (car paren-state)) + (setq lim (cdr (car paren-state)) + paren-state (cdr paren-state)) + (setq lim (car paren-state))) + (when paren-state + (setq next-containing (car paren-state) + paren-state (cdr paren-state)))) + (goto-char containing-sexp) + (if (c-looking-at-inexpr-block next-containing next-containing) + ;; We're in an in-expression block of some kind. Do not + ;; check nesting. We deliberately set the limit to the + ;; containing sexp, so that c-looking-at-inexpr-block + ;; doesn't check for an identifier before it. + (setq containing-sexp nil) + ;; see if the open brace is preceded by = or [...] in + ;; this statement, but watch out for operator= + (setq braceassignp 'dontknow) + (c-backward-token-2 1 t lim) + ;; Checks to do only on the first sexp before the brace. + (when (and c-opt-inexpr-brace-list-key + (eq (char-after) ?\[)) + ;; In Java, an initialization brace list may follow + ;; directly after "new Foo[]", so check for a "new" + ;; earlier. + (while (eq braceassignp 'dontknow) + (setq braceassignp + (cond ((/= (c-backward-token-2 1 t lim) 0) nil) + ((looking-at c-opt-inexpr-brace-list-key) t) + ((looking-at "\\sw\\|\\s_\\|[.[]") + ;; Carry on looking if this is an + ;; identifier (may contain "." in Java) + ;; or another "[]" sexp. + 'dontknow) + (t nil))))) + ;; Checks to do on all sexps before the brace, up to the + ;; beginning of the statement. + (while (eq braceassignp 'dontknow) + (cond ((eq (char-after) ?\;) + (setq braceassignp nil)) + ((and class-key + (looking-at class-key)) + (setq braceassignp nil)) + ((eq (char-after) ?=) + ;; We've seen a =, but must check earlier tokens so + ;; that it isn't something that should be ignored. + (setq braceassignp 'maybe) + (while (and (eq braceassignp 'maybe) + (zerop (c-backward-token-2 1 t lim))) + (setq braceassignp + (cond + ;; Check for operator = + ((and c-opt-op-identifier-prefix + (looking-at c-opt-op-identifier-prefix)) + nil) + ;; Check for `<opchar>= in Pike. + ((and (c-major-mode-is 'pike-mode) + (or (eq (char-after) ?`) + ;; Special case for Pikes + ;; `[]=, since '[' is not in + ;; the punctuation class. + (and (eq (char-after) ?\[) + (eq (char-before) ?`)))) + nil) + ((looking-at "\\s.") 'maybe) + ;; make sure we're not in a C++ template + ;; argument assignment + ((and + (c-major-mode-is 'c++-mode) + (save-excursion + (let ((here (point)) + (pos< (progn + (skip-chars-backward "^<>") + (point)))) + (and (eq (char-before) ?<) + (not (c-crosses-statement-barrier-p + pos< here)) + (not (c-in-literal)) + )))) + nil) + (t t)))))) (if (and (eq braceassignp 'dontknow) (/= (c-backward-token-2 1 t lim) 0)) (setq braceassignp nil))) @@ -9214,7 +9253,7 @@ (max (c-point 'boi paren-pos) (point)))) (t (c-add-syntax 'defun-block-intro nil)))) - (c-add-syntax 'statement-block-intro nil))) + (c-add-syntax 'statement-block-intro nil))) (if (= paren-pos boi) ;; Always done if the open brace was at boi. The @@ -10327,7 +10366,6 @@ (c-add-syntax 'topmost-intro-cont (c-point 'boi))) )) - ;; (CASE 6 has been removed.) ;; CASE 7: line is an expression, not a statement. Most === modified file 'lisp/progmodes/cc-fonts.el' --- lisp/progmodes/cc-fonts.el 2014-09-10 21:38:11 +0000 +++ lisp/progmodes/cc-fonts.el 2014-09-25 20:19:06 +0000 @@ -176,6 +176,7 @@ 'font-lock-negation-char-face)) (cc-bytecomp-defun face-inverse-video-p) ; Only in Emacs. +(cc-bytecomp-defun face-property-instance) ; Only in XEmacs. (defun c-make-inverse-face (oldface newface) ;; Emacs and XEmacs have completely different face manipulation @@ -266,7 +267,7 @@ ;; This function might do hidden buffer changes. (when (c-got-face-at (point) c-literal-faces) (while (progn - (goto-char (next-single-property-change + (goto-char (c-next-single-property-change (point) 'face nil limit)) (and (< (point) limit) (c-got-face-at (point) c-literal-faces)))) @@ -366,39 +367,7 @@ (parse-sexp-lookup-properties (cc-eval-when-compile (boundp 'parse-sexp-lookup-properties)))) - - ;; (while (re-search-forward ,regexp limit t) - ;; (unless (progn - ;; (goto-char (match-beginning 0)) - ;; (c-skip-comments-and-strings limit)) - ;; (goto-char (match-end 0)) - ;; ,@(mapcar - ;; (lambda (highlight) - ;; (if (integerp (car highlight)) - ;; (progn - ;; (unless (eq (nth 2 highlight) t) - ;; (error - ;; "The override flag must currently be t in %s" - ;; highlight)) - ;; (when (nth 3 highlight) - ;; (error - ;; "The laxmatch flag may currently not be set in %s" - ;; highlight)) - ;; `(save-match-data - ;; (c-put-font-lock-face - ;; (match-beginning ,(car highlight)) - ;; (match-end ,(car highlight)) - ;; ,(elt highlight 1)))) - ;; (when (nth 3 highlight) - ;; (error "Match highlights currently not supported in %s" - ;; highlight)) - ;; `(progn - ;; ,(nth 1 highlight) - ;; (save-match-data ,(car highlight)) - ;; ,(nth 2 highlight)))) - ;; highlights))) ,(c-make-font-lock-search-form regexp highlights)) - nil))) (defun c-make-font-lock-BO-decl-search-function (regexp &rest highlights) @@ -591,8 +560,7 @@ (progn (c-mark-<-as-paren beg) (c-mark->-as-paren end)) - ;; (c-clear-char-property beg 'syntax-table) - (c-clear-char-property beg 'category))) + (c-unmark-<->-as-paren beg))) nil))))))) ;; #define. @@ -716,7 +684,11 @@ (let ((start (1- (point)))) (save-excursion (and (eq (elt (parse-partial-sexp start (c-point 'eol)) 8) start) - (if (integerp c-multiline-string-start-char) + (if (if (eval-when-compile (integerp ?c)) + ;; Emacs + (integerp c-multiline-string-start-char) + ;; XEmacs + (characterp c-multiline-string-start-char)) ;; There's no multiline string start char before the ;; string, so newlines aren't allowed. (not (eq (char-before start) c-multiline-string-start-char)) @@ -771,6 +743,13 @@ `(,(concat "\\<" (c-lang-const c-regular-keywords-regexp)) 1 font-lock-keyword-face)) + ;; The following must come before c-font-lock-enclosing-decls in + ;; c-complex-decl-matchers. It fontifies java @annotations. + ,@(when (c-major-mode-is 'java-mode) + `((eval . (list "\\<\\(@[a-zA-Z0-9]+\\)\\>" 1 + c-annotation-face + )))) + ;; Fontify leading identifiers in fully qualified names like ;; "foo::bar" in languages that supports such things. ,@(when (c-lang-const c-opt-identifier-concat-key) @@ -1151,7 +1130,6 @@ (when list ;; Jump past any initializer or function prototype to see if ;; there's a ',' to continue at. - (cond ((eq id-face 'font-lock-function-name-face) ;; Skip a parenthesized initializer (C++) or a function ;; prototype. @@ -1219,8 +1197,8 @@ ;; o - nil, if not in an arglist at all. This includes the ;; parenthesized condition which follows "if", "while", etc. context - ;; The position of the next token after the closing paren of - ;; the last detected cast. + ;; A list of starting positions of possible type declarations, or of + ;; the typedef preceding one, if any. last-cast-end ;; The result from `c-forward-decl-or-cast-1'. decl-or-cast @@ -1564,9 +1542,7 @@ ;; Note that this function won't attempt to fontify beyond the end of the ;; current enum block, if any. (let* ((paren-state (c-parse-state)) - (encl-pos (c-most-enclosing-brace paren-state)) - (start (point)) - ) + (encl-pos (c-most-enclosing-brace paren-state))) (when (and encl-pos (eq (char-after encl-pos) ?\{) @@ -1948,11 +1924,7 @@ "\\)\\>") '((c-fontify-types-and-refs ((c-promote-possible-types t)) (c-forward-keyword-clause 1) - (if (> (point) limit) (goto-char limit)))))))) - - ,@(when (c-major-mode-is 'java-mode) - `((eval . (list "\\<\\(@[a-zA-Z0-9]+\\)\\>" 1 c-annotation-face)))) - )) + (if (> (point) limit) (goto-char limit)))))))))) (c-lang-defconst c-matchers-1 t (c-lang-const c-cpp-matchers)) === modified file 'lisp/progmodes/cc-guess.el' --- lisp/progmodes/cc-guess.el 2014-06-26 07:13:13 +0000 +++ lisp/progmodes/cc-guess.el 2014-09-25 18:27:32 +0000 @@ -75,6 +75,9 @@ (cc-require 'cc-defs) (cc-require 'cc-engine) (cc-require 'cc-styles) +(cc-bytecomp-defvar make-progress-reporter) +(cc-bytecomp-defvar progress-reporter-update) +(cc-bytecomp-defvar progress-reporter-done) \f @@ -519,7 +522,8 @@ (goto-char (point-min)) (when (search-forward (concat "(" (symbol-name (car needs-markers)) - " ") nil t) + " ") + nil t) (move-end-of-line 1) (comment-dwim nil) (insert " Guessed value")) === modified file 'lisp/progmodes/cc-langs.el' --- lisp/progmodes/cc-langs.el 2014-09-10 21:38:11 +0000 +++ lisp/progmodes/cc-langs.el 2014-09-26 15:07:26 +0000 @@ -130,9 +130,7 @@ ;; This file is not always loaded. See note above. -;; Except it is always loaded - see bug#17463. -;;;(cc-external-require 'cl) -(require 'cl-lib) +(cc-external-require 'cl) \f ;;; Setup for the `c-lang-defvar' system. @@ -253,14 +251,14 @@ (unless xlate (setq xlate 'identity)) (c-with-syntax-table (c-lang-const c-mode-syntax-table) - (cl-delete-duplicates - (cl-mapcan (lambda (opgroup) + (delete-duplicates + (mapcan (lambda (opgroup) (when (if (symbolp (car opgroup)) (when (funcall opgroup-filter (car opgroup)) (setq opgroup (cdr opgroup)) t) t) - (cl-mapcan (lambda (op) + (mapcan (lambda (op) (when (funcall op-filter op) (let ((res (funcall xlate op))) (if (listp res) res (list res))))) @@ -301,7 +299,8 @@ ["Set Style..." c-set-style t] ["Show Current Style Name" (message "Style Name: %s" - c-indentation-style) t] + c-indentation-style) + t] ["Guess Style from this Buffer" c-guess-buffer-no-install t] ["Install the Last Guessed Style..." c-guess-install (and c-guess-guessed-offsets-alist @@ -319,9 +318,9 @@ :style toggle :selected c-auto-newline] ["Hungry delete" c-toggle-hungry-state :style toggle :selected c-hungry-delete-key] - ["Subword mode" subword-mode - :style toggle :selected (and (boundp 'subword-mode) - subword-mode)]))) + ["Subword mode" c-subword-mode + :style toggle :selected (and (boundp 'c-subword-mode) + c-subword-mode)]))) \f ;;; Syntax tables. @@ -578,6 +577,15 @@ (c c++ objc) t) (c-lang-defvar c-has-bitfields (c-lang-const c-has-bitfields)) +(c-lang-defconst c-modified-constant + "Regexp that matches a \"modified\" constant literal such as \"L'a'\", +a \"long character\". In particular, this recognizes forms of constant +which `c-backward-sexp' needs to be called twice to move backwards over." + t nil + (c c++ objc) "L'\\([^\\'\t\f\n\r]\\|\\\\.\\)'") +;; FIXME!!! Extend this to cover strings, if needed. 2008-04-11 +(c-lang-defvar c-modified-constant (c-lang-const c-modified-constant)) + (c-lang-defconst c-symbol-start "Regexp that matches the start of a symbol, i.e. any identifier or keyword. It's unspecified how far it matches. Does not contain a \\| @@ -1144,7 +1152,8 @@ c++ (append '("&" "<%" "%>" "<:" ":>" "%:" "%:%:") (c-lang-const c-other-op-syntax-tokens)) objc (append '("#" "##" ; Used by cpp. - "+" "-") (c-lang-const c-other-op-syntax-tokens)) + "+" "-") + (c-lang-const c-other-op-syntax-tokens)) idl (append '("#" "##") ; Used by cpp. (c-lang-const c-other-op-syntax-tokens)) pike (append '("..") @@ -1155,7 +1164,7 @@ (c-lang-defconst c-all-op-syntax-tokens ;; List of all tokens in the punctuation and parenthesis syntax ;; classes. - t (cl-delete-duplicates (append (c-lang-const c-other-op-syntax-tokens) + t (delete-duplicates (append (c-lang-const c-other-op-syntax-tokens) (c-lang-const c-operator-list)) :test 'string-equal)) @@ -1587,13 +1596,14 @@ (c-lang-defvar c-syntactic-eol (c-lang-const c-syntactic-eol)) \f -;;; Defun functions +;;; Defun handling. -;; The Emacs variables beginning-of-defun-function and -;; end-of-defun-function will be set so that commands like -;; `mark-defun' and `narrow-to-defun' work right. The key sequences -;; C-M-a and C-M-e are, however, bound directly to the CC Mode -;; functions, allowing optimization for large n. +;; The Emacs variables beginning-of-defun-function and end-of-defun-function +;; will be set so that commands like `mark-defun' and `narrow-to-defun' work +;; right. In older Emacsen, the key sequences C-M-a and C-M-e are, however, +;; bound directly to the CC Mode functions, allowing optimisation for large n. +;; From Emacs 23, this isn't necessary any more, since n is passed to the two +;; functions. (c-lang-defconst beginning-of-defun-function "Function to which beginning-of-defun-function will be set." t 'c-beginning-of-defun @@ -1754,7 +1764,7 @@ (c-lang-defconst c-type-start-kwds ;; All keywords that can start a type (i.e. are either a type prefix ;; or a complete type). - t (cl-delete-duplicates (append (c-lang-const c-primitive-type-kwds) + t (delete-duplicates (append (c-lang-const c-primitive-type-kwds) (c-lang-const c-type-prefix-kwds) (c-lang-const c-type-modifier-kwds)) :test 'string-equal)) @@ -1998,7 +2008,7 @@ ;; something is a type or just some sort of macro in front of the ;; declaration. They might be ambiguous with types or type ;; prefixes. - t (cl-delete-duplicates (append (c-lang-const c-class-decl-kwds) + t (delete-duplicates (append (c-lang-const c-class-decl-kwds) (c-lang-const c-brace-list-decl-kwds) (c-lang-const c-other-block-decl-kwds) (c-lang-const c-typedef-decl-kwds) @@ -2192,7 +2202,7 @@ pike '("array" "function" "int" "mapping" "multiset" "object" "program")) (c-lang-defconst c-paren-any-kwds - t (cl-delete-duplicates (append (c-lang-const c-paren-nontype-kwds) + t (delete-duplicates (append (c-lang-const c-paren-nontype-kwds) (c-lang-const c-paren-type-kwds)) :test 'string-equal)) @@ -2218,7 +2228,7 @@ (c-lang-defconst c-<>-sexp-kwds ;; All keywords that can be followed by an angle bracket sexp. - t (cl-delete-duplicates (append (c-lang-const c-<>-type-kwds) + t (delete-duplicates (append (c-lang-const c-<>-type-kwds) (c-lang-const c-<>-arglist-kwds)) :test 'string-equal)) @@ -2278,7 +2288,7 @@ (c-lang-defconst c-block-stmt-kwds ;; Union of `c-block-stmt-1-kwds' and `c-block-stmt-2-kwds'. - t (cl-delete-duplicates (append (c-lang-const c-block-stmt-1-kwds) + t (delete-duplicates (append (c-lang-const c-block-stmt-1-kwds) (c-lang-const c-block-stmt-2-kwds)) :test 'string-equal)) @@ -2382,7 +2392,7 @@ (c-lang-defconst c-expr-kwds ;; Keywords that can occur anywhere in expressions. Built from ;; `c-primary-expr-kwds' and all keyword operators in `c-operators'. - t (cl-delete-duplicates + t (delete-duplicates (append (c-lang-const c-primary-expr-kwds) (c-filter-ops (c-lang-const c-operator-list) t @@ -2486,7 +2496,7 @@ (c-lang-defconst c-keywords ;; All keywords as a list. - t (cl-delete-duplicates + t (delete-duplicates (c-lang-defconst-eval-immediately `(append ,@(mapcar (lambda (kwds-lang-const) `(c-lang-const ,kwds-lang-const)) @@ -2826,7 +2836,7 @@ (c-lang-defvar c-block-prefix-charset (c-lang-const c-block-prefix-charset)) (c-lang-defconst c-type-decl-prefix-key - "Regexp matching the declarator operators that might precede the + "Regexp matching any declarator operator that might precede the identifier in a declaration, e.g. the \"*\" in \"char *argv\". This regexp should match \"(\" if parentheses are valid in declarators. The end of the first submatch is taken as the end of the operator. @@ -2971,17 +2981,15 @@ (when (boundp (c-mode-symbol "font-lock-extra-types")) (c-mode-var "font-lock-extra-types"))) (regexp-strings - (apply 'nconc - (mapcar (lambda (re) - (when (string-match "[][.*+?^$\\]" re) - (list re))) - extra-types))) + (delq nil (mapcar (lambda (re) + (when (string-match "[][.*+?^$\\]" re) + re)) + extra-types))) (plain-strings - (apply 'nconc - (mapcar (lambda (re) - (unless (string-match "[][.*+?^$\\]" re) - (list re))) - extra-types)))) + (delq nil (mapcar (lambda (re) + (unless (string-match "[][.*+?^$\\]" re) + re)) + extra-types)))) (concat "\\<\\(" (c-concat-separated (append (list (c-make-keywords-re nil @@ -3025,7 +3033,8 @@ expression is considered to be a type." t (or (consp (c-lang-const c-<>-type-kwds)) (consp (c-lang-const c-<>-arglist-kwds))) - java t) + java t) ; 2008-10-19. This is crude. The syntax for java + ; generics is not yet coded in CC Mode. (c-lang-defvar c-recognize-<>-arglists (c-lang-const c-recognize-<>-arglists)) (c-lang-defconst c-enums-contain-decls @@ -3249,10 +3258,10 @@ ;; `c-lang-const' will expand to the evaluated ;; constant immediately in `macroexpand-all' ;; below. - (cl-mapcan + (mapcan (lambda (init) `(current-var ',(car init) - ,(car init) ,(macroexpand-all + ,(car init) ,(c--macroexpand-all (elt init 1)))) ;; Note: The following `append' copies the ;; first argument. That list is small, so === modified file 'lisp/progmodes/cc-menus.el' --- lisp/progmodes/cc-menus.el 2014-01-01 07:43:34 +0000 +++ lisp/progmodes/cc-menus.el 2014-09-25 18:32:58 +0000 @@ -45,6 +45,7 @@ (cc-bytecomp-defvar imenu-case-fold-search) (cc-bytecomp-defvar imenu-generic-expression) (cc-bytecomp-defvar imenu-create-index-function) +(cc-bytecomp-defun imenu-progress-message) \f ;; imenu integration @@ -361,7 +362,7 @@ p (1+ p)) (cond ;; Is CHAR part of a objc token? - ((and (not inargvar) ; Ignore if CHAR is part of an argument variable. + ((and (not inargvar) ; Ignore if CHAR is part of an argument variable. (eq 0 betweenparen) ; Ignore if CHAR is in parentheses. (or (and (<= ?a char) (<= char ?z)) (and (<= ?A char) (<= char ?Z)) === modified file 'lisp/progmodes/cc-mode.el' --- lisp/progmodes/cc-mode.el 2014-09-10 21:38:11 +0000 +++ lisp/progmodes/cc-mode.el 2014-09-25 20:30:37 +0000 @@ -97,7 +97,11 @@ ;; Silence the compiler. (cc-bytecomp-defvar adaptive-fill-first-line-regexp) ; Emacs +(cc-bytecomp-defun set-keymap-parents) ; XEmacs (cc-bytecomp-defun run-mode-hooks) ; Emacs 21.1 +(cc-bytecomp-defvar normal-erase-is-backspace) +(cc-bytecomp-defvar file-local-variables-alist) +(cc-bytecomp-defvar dir-local-variables-alist) ;; We set these variables during mode init, yet we don't require ;; font-lock. @@ -108,11 +112,6 @@ ;; with your version of Emacs, you are incompatible! (cc-external-require 'easymenu) -;; Autoload directive for emacsen that doesn't have an older CC Mode -;; version in the dist. -(autoload 'subword-mode "subword" - "Mode enabling subword movement and editing keys." t) - ;; Load cc-fonts first after font-lock is loaded, since it isn't ;; necessary until font locking is requested. ; (eval-after-load "font-lock" ; 2006-07-09: font-lock is now preloaded. @@ -185,8 +184,7 @@ (run-hooks 'c-initialization-hook) ;; Fix obsolete variables. (if (boundp 'c-comment-continuation-stars) - (setq c-block-comment-prefix - (symbol-value 'c-comment-continuation-stars))) + (setq c-block-comment-prefix c-comment-continuation-stars)) (add-hook 'change-major-mode-hook 'c-leave-cc-mode-mode) (setq c-initialization-ok t) ;; Connect up with Emacs's electric-indent-mode, for >= Emacs 24.4 @@ -380,7 +378,7 @@ ;; conflicts with OOBR ;;(define-key c-mode-base-map "\C-c\C-v" 'c-version) ;; (define-key c-mode-base-map "\C-c\C-y" 'c-toggle-hungry-state) Commented out by ACM, 2005-11-22. - (define-key c-mode-base-map "\C-c\C-w" 'subword-mode) + (define-key c-mode-base-map "\C-c\C-w" 'c-subword-mode) ) ;; We don't require the outline package, but we configure it a bit anyway. @@ -472,6 +470,14 @@ (defvar c-maybe-stale-found-type nil) (make-variable-buffer-local 'c-maybe-stale-found-type) +(defvar c-just-done-before-change nil) +(make-variable-buffer-local 'c-just-done-before-change) +;; This variable is set to t by `c-before-change' and to nil by +;; `c-after-change'. It is used to detect a spurious invocation of +;; `before-change-functions' directly following on from a correct one. This +;; happens in some Emacsen, for example when `basic-save-buffer' does (insert +;; ?\n) when `require-final-newline' is non-nil. + (defun c-basic-common-init (mode default-style) "Do the necessary initialization for the syntax handling routines and the line breaking/filling code. Intended to be used by other @@ -542,10 +548,11 @@ ;; Use this in Emacs 21+ to avoid meddling with the rear-nonsticky ;; property on each character. (when (boundp 'text-property-default-nonsticky) + (make-local-variable 'text-property-default-nonsticky) (mapc (lambda (tprop) (unless (assq tprop text-property-default-nonsticky) - (set (make-local-variable 'text-property-default-nonsticky) - (cons `(,tprop . t) text-property-default-nonsticky)))) + (setq text-property-default-nonsticky + (cons `(,tprop . t) text-property-default-nonsticky)))) '(syntax-table category c-type))) ;; In Emacs 21 and later it's possible to turn off the ad-hoc @@ -601,14 +608,15 @@ ;; Install the functions that ensure that various internal caches ;; don't become invalid due to buffer changes. - (when (featurep 'xemacs) - (make-local-hook 'before-change-functions) - (make-local-hook 'after-change-functions)) + (c--make-local-hook 'before-change-functions) (add-hook 'before-change-functions 'c-before-change nil t) + (setq c-just-done-before-change nil) + (c--make-local-hook 'after-change-functions) (add-hook 'after-change-functions 'c-after-change nil t) - (set (make-local-variable 'font-lock-extend-after-change-region-function) - 'c-extend-after-change-region)) ; Currently (2009-05) used by all - ; languages with #define (C, C++,; ObjC), and by AWK. + (when (boundp 'font-lock-extend-after-change-region-function) + (set (make-local-variable 'font-lock-extend-after-change-region-function) + 'c-extend-after-change-region))) ; Currently (2009-05) used by all + ; languages with #define (C, C++,; ObjC), and by AWK. (defun c-setup-doc-comment-style () "Initialize the variables that depend on the value of `c-doc-comment-style'." @@ -669,9 +677,11 @@ (or (c-cpp-define-name) (c-defun-name)))) (let ((rfn (assq mode c-require-final-newline))) (when rfn - (and (cdr rfn) - (set (make-local-variable 'require-final-newline) - mode-require-final-newline))))) + (if (boundp 'mode-require-final-newline) + (and (cdr rfn) + (set (make-local-variable 'require-final-newline) + mode-require-final-newline)) + (set (make-local-variable 'require-final-newline) (cdr rfn)))))) (defun c-count-cfss (lv-alist) ;; LV-ALIST is an alist like `file-local-variables-alist'. Count how many @@ -948,8 +958,11 @@ c-new-END (min (cdr new-bounds) (c-determine-+ve-limit 500 endd))) ;; Clear all old relevant properties. (c-clear-char-property-with-value c-new-BEG c-new-END 'syntax-table '(1)) - (c-clear-char-property-with-value c-new-BEG c-new-END 'category 'c-cpp-delimiter) - ;; FIXME!!! What about the "<" and ">" category properties? 2009-11-16 + + ;; CPP "comment" markers: + (if (eval-when-compile (memq 'category-properties c-emacs-features));Emacs. + (c-clear-char-property-with-value + c-new-BEG c-new-END 'category 'c-cpp-delimiter)) ;; Add needed properties to each CPP construct in the region. (goto-char c-new-BEG) @@ -967,8 +980,10 @@ (setq mbeg (point)) (if (> (c-syntactic-end-of-macro) mbeg) (progn - (c-neutralize-CPP-line mbeg (point)) - (c-set-cpp-delimiters mbeg (point))) + (c-neutralize-CPP-line mbeg (point)) ; "punctuation" properties + (if (eval-when-compile + (memq 'category-properties c-emacs-features)) ;Emacs. + (c-set-cpp-delimiters mbeg (point)))) ; "comment" markers (forward-line)) ; no infinite loop with, e.g., "#//" ))))) @@ -988,64 +1003,67 @@ ;; it/them from the cache. Don't worry about being inside a string ;; or a comment - "wrongly" removing a symbol from `c-found-types' ;; isn't critical. - (setq c-maybe-stale-found-type nil) - (save-restriction - (save-match-data - (widen) - (save-excursion - ;; Are we inserting/deleting stuff in the middle of an identifier? - (c-unfind-enclosing-token beg) - (c-unfind-enclosing-token end) - ;; Are we coalescing two tokens together, e.g. "fo o" -> "foo"? - (when (< beg end) - (c-unfind-coalesced-tokens beg end)) - ;; Are we (potentially) disrupting the syntactic context which - ;; makes a type a type? E.g. by inserting stuff after "foo" in - ;; "foo bar;", or before "foo" in "typedef foo *bar;"? - ;; - ;; We search for appropriate c-type properties "near" the change. - ;; First, find an appropriate boundary for this property search. - (let (lim - type type-pos - marked-id term-pos - (end1 - (or (and (eq (get-text-property end 'face) 'font-lock-comment-face) - (previous-single-property-change end 'face)) - end))) - (when (>= end1 beg) ; Don't hassle about changes entirely in comments. - ;; Find a limit for the search for a `c-type' property - (while - (and (/= (skip-chars-backward "^;{}") 0) - (> (point) (point-min)) - (memq (c-get-char-property (1- (point)) 'face) - '(font-lock-comment-face font-lock-string-face)))) - (setq lim (max (point-min) (1- (point)))) - - ;; Look for the latest `c-type' property before end1 - (when (and (> end1 (point-min)) - (setq type-pos - (if (get-text-property (1- end1) 'c-type) - end1 - (previous-single-property-change end1 'c-type nil lim)))) - (setq type (get-text-property (max (1- type-pos) lim) 'c-type)) - - (when (memq type '(c-decl-id-start c-decl-type-start)) - ;; Get the identifier, if any, that the property is on. - (goto-char (1- type-pos)) - (setq marked-id - (when (looking-at "\\(\\sw\\|\\s_\\)") - (c-beginning-of-current-token) - (buffer-substring-no-properties (point) type-pos))) - - (goto-char end1) - (skip-chars-forward "^;{}") ; FIXME!!! loop for comment, maybe - (setq lim (point)) - (setq term-pos - (or (next-single-property-change end 'c-type nil lim) lim)) - (setq c-maybe-stale-found-type - (list type marked-id - type-pos term-pos - (buffer-substring-no-properties type-pos term-pos) + (unless c-just-done-before-change ; guard against a spurious second + ; invocation of before-change-functions. + (setq c-just-done-before-change t) + (setq c-maybe-stale-found-type nil) + (save-restriction + (save-match-data + (widen) + (save-excursion + ;; Are we inserting/deleting stuff in the middle of an identifier? + (c-unfind-enclosing-token beg) + (c-unfind-enclosing-token end) + ;; Are we coalescing two tokens together, e.g. "fo o" -> "foo"? + (when (< beg end) + (c-unfind-coalesced-tokens beg end)) + ;; Are we (potentially) disrupting the syntactic context which + ;; makes a type a type? E.g. by inserting stuff after "foo" in + ;; "foo bar;", or before "foo" in "typedef foo *bar;"? + ;; + ;; We search for appropriate c-type properties "near" the change. + ;; First, find an appropriate boundary for this property search. + (let (lim + type type-pos + marked-id term-pos + (end1 + (or (and (eq (get-text-property end 'face) 'font-lock-comment-face) + (previous-single-property-change end 'face)) + end))) + (when (>= end1 beg) ; Don't hassle about changes entirely in comments. + ;; Find a limit for the search for a `c-type' property + (while + (and (/= (skip-chars-backward "^;{}") 0) + (> (point) (point-min)) + (memq (c-get-char-property (1- (point)) 'face) + '(font-lock-comment-face font-lock-string-face)))) + (setq lim (max (point-min) (1- (point)))) + + ;; Look for the latest `c-type' property before end1 + (when (and (> end1 (point-min)) + (setq type-pos + (if (get-text-property (1- end1) 'c-type) + end1 + (previous-single-property-change end1 'c-type nil lim)))) + (setq type (get-text-property (max (1- type-pos) lim) 'c-type)) + + (when (memq type '(c-decl-id-start c-decl-type-start)) + ;; Get the identifier, if any, that the property is on. + (goto-char (1- type-pos)) + (setq marked-id + (when (looking-at "\\(\\sw\\|\\s_\\)") + (c-beginning-of-current-token) + (buffer-substring-no-properties (point) type-pos))) + + (goto-char end1) + (skip-chars-forward "^;{}") ; FIXME!!! loop for comment, maybe + (setq lim (point)) + (setq term-pos + (or (c-next-single-property-change end 'c-type nil lim) lim)) + (setq c-maybe-stale-found-type + (list type marked-id + type-pos term-pos + (buffer-substring-no-properties type-pos term-pos) (buffer-substring-no-properties beg end))))))) (if c-get-state-before-change-functions @@ -1056,7 +1074,7 @@ ))) ;; The following must be done here rather than in `c-after-change' because ;; newly inserted parens would foul up the invalidation algorithm. - (c-invalidate-state-cache beg)) + (c-invalidate-state-cache beg))) (defvar c-in-after-change-fontification nil) (make-variable-buffer-local 'c-in-after-change-fontification) @@ -1077,6 +1095,7 @@ ;; This calls the language variable c-before-font-lock-functions, if non nil. ;; This typically sets `syntax-table' properties. + (setq c-just-done-before-change nil) (c-save-buffer-state (case-fold-search open-paren-in-column-0-is-defun-start) ;; When `combine-after-change-calls' is used we might get calls ;; with regions outside the current narrowing. This has been @@ -1097,11 +1116,12 @@ ;; C-y is capable of spuriously converting category properties ;; c-</>-as-paren-syntax and c-cpp-delimiter into hard syntax-table ;; properties. Remove these when it happens. - (c-clear-char-property-with-value beg end 'syntax-table - c-<-as-paren-syntax) - (c-clear-char-property-with-value beg end 'syntax-table - c->-as-paren-syntax) - (c-clear-char-property-with-value beg end 'syntax-table nil) + (when (eval-when-compile (memq 'category-properties c-emacs-features)) + (c-clear-char-property-with-value beg end 'syntax-table + c-<-as-paren-syntax) + (c-clear-char-property-with-value beg end 'syntax-table + c->-as-paren-syntax) + (c-clear-char-property-with-value beg end 'syntax-table nil)) (c-trim-found-types beg end old-len) ; maybe we don't need all of these. (c-invalidate-sws-region-after beg end) @@ -1235,10 +1255,10 @@ (make-local-variable 'font-lock-fontify-region-function) (setq font-lock-fontify-region-function 'c-font-lock-fontify-region) - (if (featurep 'xemacs) - (make-local-hook 'font-lock-mode-hook)) + (c--make-local-hook 'font-lock-mode-hook) (add-hook 'font-lock-mode-hook 'c-after-font-lock-init nil t)) +;; Emacs 22 and later. (defun c-extend-after-change-region (_beg _end _old-len) "Extend the region to be fontified, if necessary." ;; Note: the parameters are ignored here. This somewhat indirect @@ -1252,6 +1272,21 @@ ;; function. (cons c-new-BEG c-new-END)) +;; Emacs < 22 and XEmacs +(defmacro c-advise-fl-for-region (function) + `(defadvice ,function (before get-awk-region activate) + ;; Make sure that any string/regexp is completely font-locked. + (when c-buffer-is-cc-mode + (save-excursion + (ad-set-arg 1 c-new-END) ; end + (ad-set-arg 0 c-new-BEG))))) ; beg + +(unless (boundp 'font-lock-extend-after-change-region-function) + (c-advise-fl-for-region font-lock-after-change-function) + (c-advise-fl-for-region jit-lock-after-change) + (c-advise-fl-for-region lazy-lock-defer-rest-after-change) + (c-advise-fl-for-region lazy-lock-defer-line-after-change)) + ;; Connect up to `electric-indent-mode' (Emacs 24.4 and later). (defun c-electric-indent-mode-hook () ;; Emacs has en/disabled `electric-indent-mode'. Propagate this through to @@ -1322,6 +1357,7 @@ ;;;###autoload (add-to-list 'auto-mode-alist '("\\.i\\'" . c-mode)) ;;;###autoload (add-to-list 'auto-mode-alist '("\\.ii\\'" . c++-mode)) +(unless (fboundp 'prog-mode) (defalias 'prog-mode 'fundamental-mode)) ;;;###autoload (define-derived-mode c-mode prog-mode "C" === modified file 'lisp/progmodes/cc-styles.el' --- lisp/progmodes/cc-styles.el 2014-01-01 07:43:34 +0000 +++ lisp/progmodes/cc-styles.el 2014-09-25 18:44:14 +0000 @@ -645,7 +645,7 @@ (mapc func varsyms) ;; Hooks must be handled specially (if this-buf-only-p - (if (featurep 'xemacs) (make-local-hook 'c-special-indent-hook)) + (c--make-local-hook 'c-special-indent-hook) (with-no-warnings (make-variable-buffer-local 'c-special-indent-hook)) (setq c-style-variables-are-local-p t)) )) === modified file 'lisp/progmodes/cc-vars.el' --- lisp/progmodes/cc-vars.el 2014-01-01 07:43:34 +0000 +++ lisp/progmodes/cc-vars.el 2014-09-25 21:16:12 +0000 @@ -42,6 +42,9 @@ (cc-require 'cc-defs) +;; Silence the compiler. +(cc-bytecomp-defun get-char-table) ; XEmacs + (cc-eval-when-compile (require 'custom) (require 'widget)) @@ -185,14 +188,14 @@ `c-style-alist') when a CC Mode buffer is initialized. Otherwise, the value set here overrides the style system (there is a variable `c-old-style-variable-behavior' that changes this, though).")) - (typ (eval (plist-get args :type))) + (typ (eval (c-safe (plist-get args :type)))) (type (if (consp typ) typ (list typ))) (head (car type)) (tail (cdr type)) - (newt (append (unless (plist-get tail :tag) + (newt (append (unless (c-safe (plist-get tail :tag)) '(:tag "Override style settings")) - (unless (plist-get tail :value) - `(:value ,(eval val))) + (unless (c-safe (plist-get tail :value)) + `(:value ,val)) tail)) (aggregate `'(radio (const :tag "Use style settings" set-from-style) @@ -275,13 +278,18 @@ "*Controls the operation of the TAB key. If t, hitting TAB always just indents the current line. If nil, hitting TAB indents the current line if point is at the left margin or in the -line's indentation, otherwise it calls `c-insert-tab-function' to -insert a `real' tab character. If some other value (neither nil nor t), -then inserts a tab only within literals (comments and strings), but -always reindents the line. - -Note: the variable `c-comment-only-line-offset' also controls the -indentation of lines containing only comments." +line's indentation, otherwise it inserts a `real' tab character \(see +note\). If some other value (not nil or t), then tab is inserted only +within literals \(comments and strings), but the line is always +reindented. + +Note: The value of `indent-tabs-mode' will determine whether a real +tab character will be inserted, or the equivalent number of spaces. +When inserting a tab, actually the function stored in the variable +`c-insert-tab-function' is called. + +Note: indentation of lines containing only comments is also controlled +by the `c-comment-only-line-offset' variable." :type '(radio (const :tag "TAB key always indents, never inserts TAB" t) (const :tag "TAB key indents in left margin, otherwise inserts TAB" nil) @@ -456,7 +463,8 @@ :group 'c) (make-obsolete-variable 'c-comment-continuation-stars - 'c-block-comment-prefix "21.1") + 'c-block-comment-prefix + nil) ;; Although c-comment-continuation-stars is obsolete, we look at it in ;; some places in CC Mode anyway, so make the compiler ignore it @@ -920,7 +928,7 @@ (defcustom c-special-indent-hook nil "*Hook for user defined special indentation adjustments. This hook gets called after each line is indented by the mode. It is only -called if `c-syntactic-indentation' is non-nil." +called when `c-syntactic-indentation' is non-nil." :type 'hook :group 'c) @@ -1689,7 +1697,8 @@ ;; It isn't possible to specify a doc-string without specifying an ;; initial value with `defvar', so the following two variables have been ;; given doc-strings by setting the property `variable-documentation' -;; directly. It's really good not to have an initial value for +;; directly. C-h v will read this documentation only for versions of GNU +;; Emacs from 22.1. It's really good not to have an initial value for ;; variables like these that always should be dynamically bound, so it's ;; worth the inconvenience. ^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: Further CC-mode changes 2014-09-13 15:10 ` Alan Mackenzie 2014-09-13 19:24 ` Stefan Monnier @ 2014-09-15 20:24 ` Glenn Morris 2014-09-16 3:07 ` Stephen J. Turnbull 1 sibling, 1 reply; 41+ messages in thread From: Glenn Morris @ 2014-09-15 20:24 UTC (permalink / raw) To: Alan Mackenzie; +Cc: Stefan Monnier, emacs-devel Alan Mackenzie wrote: >> It's work I did, pro bono. Just enjoy it. > > No, you haven't. What's the equivalent of `syntax-propertize' in XEmacs, > or an old GNU Emacs? "Somebody" (tm) has to write a compatibility macro > which will look something like this: No, nobody has to do that. You've got limited time to work on cc-mode, and more issues than you can solve. If you choose to spend some of that time supporting old Emacs versions (and XEmacs by now is a very old Emacs version), then that is reducing the amount of time you can spend on eg improving C++11 support (to pick a non-random example). IMO this is a clear loss, so I hope you will reconsider your position on that. I imagine Stefan is one of the few people capable of modernizing/simplifying/standardizing cc-mode, so FWIW I strongly encourage you to accept the offer. ^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: Further CC-mode changes 2014-09-15 20:24 ` Further CC-mode changes Glenn Morris @ 2014-09-16 3:07 ` Stephen J. Turnbull 2014-09-16 13:39 ` Stefan Monnier 2014-09-16 14:22 ` David Kastrup 0 siblings, 2 replies; 41+ messages in thread From: Stephen J. Turnbull @ 2014-09-16 3:07 UTC (permalink / raw) To: Glenn Morris; +Cc: Alan Mackenzie, Stefan Monnier, emacs-devel Glenn Morris writes: > solve. If you choose to spend some of that time supporting old Emacs > versions (and XEmacs by now is a very old Emacs version), then that is > reducing the amount of time you can spend on eg improving C++11 support > (to pick a non-random example). IMO this is a clear loss, so I hope you > will reconsider your position on that. -1 ^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: Further CC-mode changes 2014-09-16 3:07 ` Stephen J. Turnbull @ 2014-09-16 13:39 ` Stefan Monnier 2014-09-16 14:22 ` David Kastrup 1 sibling, 0 replies; 41+ messages in thread From: Stefan Monnier @ 2014-09-16 13:39 UTC (permalink / raw) To: Stephen J. Turnbull; +Cc: emacs-devel, Alan Mackenzie >> solve. If you choose to spend some of that time supporting old Emacs >> versions (and XEmacs by now is a very old Emacs version), then that is >> reducing the amount of time you can spend on eg improving C++11 support >> (to pick a non-random example). IMO this is a clear loss, so I hope you >> will reconsider your position on that. > -1 IOW, the issue is not "should CC-mode drop support for XEmacs?", but "should CC-mode's maintainer spend his time preserving XEmacs compatibility?". While the indentation code is rather involved (and hence difficult for someone other than Alan to hack on), the code need for compatibility with a particular emacs is not particularly deep or tricky, so many more people can contribute to that. Stefan ^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: Further CC-mode changes 2014-09-16 3:07 ` Stephen J. Turnbull 2014-09-16 13:39 ` Stefan Monnier @ 2014-09-16 14:22 ` David Kastrup 2014-09-16 23:40 ` Stephen J. Turnbull 1 sibling, 1 reply; 41+ messages in thread From: David Kastrup @ 2014-09-16 14:22 UTC (permalink / raw) To: emacs-devel "Stephen J. Turnbull" <stephen@xemacs.org> writes: > Glenn Morris writes: > > > solve. If you choose to spend some of that time supporting old Emacs > > versions (and XEmacs by now is a very old Emacs version), then that is > > reducing the amount of time you can spend on eg improving C++11 support > > (to pick a non-random example). IMO this is a clear loss, so I hope you > > will reconsider your position on that. > > -1 I think it depends. "Gratuitous incompatibility" is one thing, but "refrain from relying on fixes, useful APIs etc that exist for years already" is another. The responsibility for keeping the core of XEmacs in good working shape, or rather the cost for _not_ keeping the core of XEmacs in good working shape should not be loaded off on Emacs developers. Why should we factually ignore years of work on making Emacs more useful? -- David Kastrup ^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: Further CC-mode changes 2014-09-16 14:22 ` David Kastrup @ 2014-09-16 23:40 ` Stephen J. Turnbull 2014-09-17 1:02 ` Stefan Monnier ` (2 more replies) 0 siblings, 3 replies; 41+ messages in thread From: Stephen J. Turnbull @ 2014-09-16 23:40 UTC (permalink / raw) To: David Kastrup; +Cc: emacs-devel David Kastrup writes: > I think it depends. "Gratuitous incompatibility" is one thing, but > "refrain from relying on fixes, useful APIs etc that exist for years > already" is another. *You* do understand the irony of that claim, don't you? But no, what it depends on is whether you use those versions or not. Two separate surveys of large (>100) corporate Emacsen populations taken in 2003 and 2007 showed that around 10% of users were using 10-year-old or older Emacsen. Even Microsoft has been taught that lesson. The trend in forward-looking projects is to "long term support" of various kinds, invariably involving multiple versions and even competing implementations, and even longer-term support is one of the things that keeps free software businesses profitable. I think it's ironic that when it comes to the XEmacs support Alan wants to provide, Glenn is all for "aggressive modernization" and devil take the hindmost, but when it comes to the same policy toward the git repo Eric wants to provide, he's the loudest of footdraggers. I think that is pretty paradigmatic of Emacs, and one of the reasons why Emacs is itself considered "unprogressive" by most programmers. ^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: Further CC-mode changes 2014-09-16 23:40 ` Stephen J. Turnbull @ 2014-09-17 1:02 ` Stefan Monnier 2014-09-17 1:48 ` Stephen J. Turnbull 2014-09-17 18:31 ` Glenn Morris 2014-09-17 5:24 ` Eli Zaretskii 2014-09-18 9:44 ` Emilio Lopes 2 siblings, 2 replies; 41+ messages in thread From: Stefan Monnier @ 2014-09-17 1:02 UTC (permalink / raw) To: Stephen J. Turnbull; +Cc: David Kastrup, emacs-devel > But no, what it depends on is whether you use those versions or not. > Two separate surveys of large (>100) corporate Emacsen populations > taken in 2003 and 2007 showed that around 10% of users were using > 10-year-old or older Emacsen. I have no illusion about that (although the general trend has changed slightly due to the constant security update needs). The issue is not "backward compatibility" but *how* to get it. Stefan ^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: Further CC-mode changes 2014-09-17 1:02 ` Stefan Monnier @ 2014-09-17 1:48 ` Stephen J. Turnbull 2014-09-17 5:22 ` David Kastrup 2014-09-17 18:31 ` Glenn Morris 1 sibling, 1 reply; 41+ messages in thread From: Stephen J. Turnbull @ 2014-09-17 1:48 UTC (permalink / raw) To: Stefan Monnier; +Cc: David Kastrup, emacs-devel Stefan Monnier writes: > The issue is not "backward compatibility" but *how* to get it. Evidently not for Glenn, David, and IIRC RMS, though. I think in fact you are in a minority in the Emacs leadership[1] when it comes to backwards compatibility. Footnotes: [1] leadership ~= vocal on emacs-devel, ie, in the sense of voicing opinions about which sensible people disagree, but should be heard. ^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: Further CC-mode changes 2014-09-17 1:48 ` Stephen J. Turnbull @ 2014-09-17 5:22 ` David Kastrup 2014-09-17 13:00 ` Stefan Monnier 0 siblings, 1 reply; 41+ messages in thread From: David Kastrup @ 2014-09-17 5:22 UTC (permalink / raw) To: Stephen J. Turnbull; +Cc: Stefan Monnier, emacs-devel "Stephen J. Turnbull" <stephen@xemacs.org> writes: > Stefan Monnier writes: > > > The issue is not "backward compatibility" but *how* to get it. > > Evidently not for Glenn, David, and IIRC RMS, though. I think in > fact you are in a minority in the Emacs leadership[1] when it comes > to backwards compatibility. You are mixing up two entirely different topics under the title of "backward" compatibility. One thing is how long user-provided code should be expected to continue working in new Emacs versions. How long should old interfaces leading to more cumbersome code continue to be provided? But that's not what we are talking about here _at_ _all_. Quite the contrary. The answer to that has more or less been resolved to "pretty long" and that makes the actual question even possible: And that question is: how long should new code intended for Emacs refrain from relying on new interfaces and new features which have been created for a reason? And the answer "15 years because XEmacs won't upgrade" is not satisfactory. At some point of time, people who are happy with a 15 year old Emacs variant will have to face updating either XEmacs, or backporting software they care for, or just using older versions of software on XEmacs. -- David Kastrup ^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: Further CC-mode changes 2014-09-17 5:22 ` David Kastrup @ 2014-09-17 13:00 ` Stefan Monnier 0 siblings, 0 replies; 41+ messages in thread From: Stefan Monnier @ 2014-09-17 13:00 UTC (permalink / raw) To: David Kastrup; +Cc: Stephen J. Turnbull, emacs-devel > And that question is: how long should new code intended for Emacs > refrain from relying on new interfaces and new features which have been > created for a reason? Actually, that's not really the question either. I think the questions Alan is facing are more along the lines of: - should I just keep using my old code which is compatible by a mix of "do it all by hand" plus "coerce the few packages on which I need to rely". - or should I start using the new interface, which integrates better with the rest of the system, but comes with some downsides: - the new system doesn't work quite like my old one, and I prefer my system (after all, *I* designed it, so it does exactly what I want). - since it doesn't work quite like my old one, I might introduce bugs. - the new one is not supported everywhere, so I have to add new compatibility code. In the short run, the first option (the one usually favored by Alan, AFAICT) is clearly better. Stefan ^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: Further CC-mode changes 2014-09-17 1:02 ` Stefan Monnier 2014-09-17 1:48 ` Stephen J. Turnbull @ 2014-09-17 18:31 ` Glenn Morris 2014-09-17 19:12 ` David Kastrup 1 sibling, 1 reply; 41+ messages in thread From: Glenn Morris @ 2014-09-17 18:31 UTC (permalink / raw) To: Stefan Monnier; +Cc: Stephen J. Turnbull, David Kastrup, emacs-devel >> Two separate surveys of large (>100) corporate Emacsen populations >> taken in 2003 and 2007 showed that around 10% of users were using >> 10-year-old or older Emacsen. I knew this by now very tired old statement would get trotted out. :) Obviously it doesn't matter what I think, and I don't expect it to change anyone's opinion, but based on Stephen's response I'll stop beating around the bush. The point was made 6 years ago, and things certainly have not improved since then: http://steve-yegge.blogspot.com/2008/04/xemacs-is-dead-long-live-xemacs.html But at this point, if you're using XEmacs you're actively damaging not only your long-term productivity, but mine as well. Maintaining compat code for ancient Emacs versions is a waste of effort, and in fact makes things worse for people using modern Emacs. https://www.openhub.net/p/emacs 4500 commits in the last year https://www.openhub.net/p/xemacs 48 commits in the last year Extend the sample to 5 years if you like, same result. Throw in SXEmacs too if you like, that had 35 commits last year. Yes, counting commits is a silly metric, but the result is the same by any metric. Bug reports closed in the last year? ~ 0 (?) versus 1000s. New features have been added in the last year (5 years)? I-don't-know versus see the 4000-line NEWS file. ^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: Further CC-mode changes 2014-09-17 18:31 ` Glenn Morris @ 2014-09-17 19:12 ` David Kastrup 0 siblings, 0 replies; 41+ messages in thread From: David Kastrup @ 2014-09-17 19:12 UTC (permalink / raw) To: Glenn Morris; +Cc: Stephen J. Turnbull, Stefan Monnier, emacs-devel Glenn Morris <rgm@gnu.org> writes: >>> Two separate surveys of large (>100) corporate Emacsen populations >>> taken in 2003 and 2007 showed that around 10% of users were using >>> 10-year-old or older Emacsen. > > I knew this by now very tired old statement would get trotted out. :) [...] I think you are missing one point in your repartee: Why would it make a difference to those people not updating their systems what requirements a current version of CC-mode has? -- David Kastrup ^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: Further CC-mode changes 2014-09-16 23:40 ` Stephen J. Turnbull 2014-09-17 1:02 ` Stefan Monnier @ 2014-09-17 5:24 ` Eli Zaretskii 2014-09-17 6:54 ` Stephen J. Turnbull 2014-09-18 9:44 ` Emilio Lopes 2 siblings, 1 reply; 41+ messages in thread From: Eli Zaretskii @ 2014-09-17 5:24 UTC (permalink / raw) To: Stephen J. Turnbull; +Cc: dak, emacs-devel > From: "Stephen J. Turnbull" <stephen@xemacs.org> > Date: Wed, 17 Sep 2014 08:40:25 +0900 > Cc: emacs-devel@gnu.org > > I think it's ironic that when it comes to the XEmacs support Alan > wants to provide, Glenn is all for "aggressive modernization" and > devil take the hindmost, but when it comes to the same policy toward > the git repo Eric wants to provide, he's the loudest of footdraggers. That's unfair to Glenn, and is evidently based on just 2 data points out of many more. So let me add 2 more from my failing memory: . Glenn also lobbied hard to remove the old MS-Windows configury (which I objected, and therefore it didn't happen yet) . Glenn suggested that the trunk relies on GNU Make, which did happen, and made many useful changes which that enabled I encourage you to browse the logs, because I'm sure you will find an overwhelming evidence that your conclusion is based on incorrect interpretation of a single incident. If you consider the inordinate amount of work Glenn personally invested in making bzr usage convenient in Emacs, you might come up with an alternative explanation to his alleged "footdragging". ^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: Further CC-mode changes 2014-09-17 5:24 ` Eli Zaretskii @ 2014-09-17 6:54 ` Stephen J. Turnbull 2014-09-17 7:20 ` Eli Zaretskii ` (2 more replies) 0 siblings, 3 replies; 41+ messages in thread From: Stephen J. Turnbull @ 2014-09-17 6:54 UTC (permalink / raw) To: Eli Zaretskii; +Cc: dak, emacs-devel Eli Zaretskii writes: > > From: "Stephen J. Turnbull" <stephen@xemacs.org> > > Date: Wed, 17 Sep 2014 08:40:25 +0900 > > Cc: emacs-devel@gnu.org > > > > I think it's ironic that when it comes to the XEmacs support Alan > > wants to provide, Glenn is all for "aggressive modernization" and > > devil take the hindmost, but when it comes to the same policy toward > > the git repo Eric wants to provide, he's the loudest of footdraggers. > > That's unfair to Glenn, and is evidently based on just 2 data points > out of many more. > > So let me add 2 more from my failing memory: > > . Glenn also lobbied hard to remove the old MS-Windows configury > (which I objected, and therefore it didn't happen yet) > > . Glenn suggested that the trunk relies on GNU Make, which did > happen, and made many useful changes which that enabled I consider those both to support my claim, which is that if it reduces the amount of work he needs to do to achieve a unit of Emacs development in the future, he's in favor of investing both his time, and users' time and inconvenience, in the change. If somebody else does the same, but it inconveniences him, he complains. That's *ironic*, no matter how dedicated Glenn may be to Emacs development. Of course I'm -1 on anything that makes it even harder for XEmacs to catch up to current reality. That shouldn't bother core Emacs people too much, although I'm glad it's a consideration for Alan and many other package developers. And you shouldn't be surprised that this is the point that piqued me enough to speak up. But ... My real point is that bzr has held Emacs back for long enough. Both Eric's obsession with the 36-24-36 conversion and Glenn's insistance that everything that is part of the bzr workflow be done for git *before* the switchover is executed are unfortunate. > If you consider the inordinate amount of work Glenn personally > invested in making bzr usage convenient in Emacs, you might come up > with an alternative explanation to his alleged "footdragging". Sure. The labor theory of value: if I worked so hard on it, it must be worth keeping. Thing is, bzr was a mistake from day 1, and it went mostly downhill from there. The consequent duplication of effort was not Eric's fault! ^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: Further CC-mode changes 2014-09-17 6:54 ` Stephen J. Turnbull @ 2014-09-17 7:20 ` Eli Zaretskii 2014-09-17 7:30 ` David Kastrup 2014-09-17 13:04 ` Stefan Monnier 2 siblings, 0 replies; 41+ messages in thread From: Eli Zaretskii @ 2014-09-17 7:20 UTC (permalink / raw) To: Stephen J. Turnbull; +Cc: dak, emacs-devel > From: "Stephen J. Turnbull" <stephen@xemacs.org> > Date: Wed, 17 Sep 2014 15:54:32 +0900 > Cc: dak@gnu.org, emacs-devel@gnu.org > > I consider those both to support my claim Why am I not surprised? > which is that if it reduces the amount of work he needs to do to > achieve a unit of Emacs development in the future, he's in favor of > investing both his time, and users' time and inconvenience, in the > change. If somebody else does the same, but it inconveniences him, > he complains. That's *ironic*, no matter how dedicated Glenn may be > to Emacs development. This is gross misrepresentation of Glenn's work and attitude, mixed with mislabeling a natural behavior of a project developer as "ironically" wrong. ^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: Further CC-mode changes 2014-09-17 6:54 ` Stephen J. Turnbull 2014-09-17 7:20 ` Eli Zaretskii @ 2014-09-17 7:30 ` David Kastrup 2014-09-17 13:04 ` Stefan Monnier 2 siblings, 0 replies; 41+ messages in thread From: David Kastrup @ 2014-09-17 7:30 UTC (permalink / raw) To: Stephen J. Turnbull; +Cc: Eli Zaretskii, emacs-devel "Stephen J. Turnbull" <stephen@xemacs.org> writes: > Of course I'm -1 on anything that makes it even harder for XEmacs to > catch up to current reality. That's where our views of what we are talking about differ. In my book, we are talking about changes that make it even more pressing (but not harder) for XEmacs to catch up to current reality. The whole point of extended backward compatibility upstream is to avoid the consequences of not catching up to reality downstream. > My real point is that bzr has held Emacs back for long enough. Both > Eric's obsession with the 36-24-36 conversion and Glenn's insistance > that everything that is part of the bzr workflow be done for git > *before* the switchover is executed are unfortunate. > > > If you consider the inordinate amount of work Glenn personally > > invested in making bzr usage convenient in Emacs, you might come up > > with an alternative explanation to his alleged "footdragging". > > Sure. The labor theory of value: if I worked so hard on it, it must > be worth keeping. Thing is, bzr was a mistake from day 1, and it went > mostly downhill from there. It didn't for Bazaar: it was the reason for a lot of scalability problems in Bazaar getting ironed out. Of course, doscovery of the wrinkles impacted Emacs development. That was expected. Supporting Bazaar was a political choice in order to keep with a version control system which was looking better suited for the political goals of the GNU projects. A lot of work was expected to make things work well. The technical side of Bazaar progressed to the state of "workable". The political side degressed to "barely workable" after a few years. Which makes it a lost investment. Which does not mean that all investments of labor in the view of political goals must be lost investments, or we would not be having a GNU project. > The consequent duplication of effort was not Eric's fault! The country of Oz has pronounced a travelling warning for strawmen on the Emacs developer list as they are in serious danger of being rounded up and beaten to death. -- David Kastrup ^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: Further CC-mode changes 2014-09-17 6:54 ` Stephen J. Turnbull 2014-09-17 7:20 ` Eli Zaretskii 2014-09-17 7:30 ` David Kastrup @ 2014-09-17 13:04 ` Stefan Monnier 2014-09-17 18:25 ` Glenn Morris 2014-09-18 5:20 ` Stephen J. Turnbull 2 siblings, 2 replies; 41+ messages in thread From: Stefan Monnier @ 2014-09-17 13:04 UTC (permalink / raw) To: Stephen J. Turnbull; +Cc: Eli Zaretskii, dak, emacs-devel > My real point is that bzr has held Emacs back for long enough. Both > Eric's obsession with the 36-24-36 conversion and Glenn's insistance > that everything that is part of the bzr workflow be done for git > *before* the switchover is executed are unfortunate. Huh? Why are they unfortunate? It's not like they're delaying the switchover (which is waiting for the 24.4 release). Stefan ^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: Further CC-mode changes 2014-09-17 13:04 ` Stefan Monnier @ 2014-09-17 18:25 ` Glenn Morris 2014-09-18 5:20 ` Stephen J. Turnbull 1 sibling, 0 replies; 41+ messages in thread From: Glenn Morris @ 2014-09-17 18:25 UTC (permalink / raw) To: Stefan Monnier; +Cc: Stephen J. Turnbull, dak, Eli Zaretskii, emacs-devel [Nice job shifting the discussion Stephen! :)] >> My real point is that bzr has held Emacs back for long enough. Both >> Eric's obsession with the 36-24-36 conversion and Glenn's insistance >> that everything that is part of the bzr workflow be done for git >> *before* the switchover is executed are unfortunate. I thought that the people who actually develop Emacs came up with a list of things to be taken care of before the switch. I'd like to make sure they all get taken care of, as we were promised, is all. ^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: Further CC-mode changes 2014-09-17 13:04 ` Stefan Monnier 2014-09-17 18:25 ` Glenn Morris @ 2014-09-18 5:20 ` Stephen J. Turnbull 1 sibling, 0 replies; 41+ messages in thread From: Stephen J. Turnbull @ 2014-09-18 5:20 UTC (permalink / raw) To: Stefan Monnier; +Cc: Eli Zaretskii, dak, emacs-devel Stefan Monnier writes: > > My real point is that bzr has held Emacs back for long enough. Both > > Eric's obsession with the 36-24-36 conversion and Glenn's insistance > > that everything that is part of the bzr workflow be done for git > > *before* the switchover is executed are unfortunate. > > Huh? Why are they unfortunate? It's not like they're delaying the > switchover (which is waiting for the 24.4 release). That is, they're not on the critical path now. Later? If you say not, I guess they're not, and I'm happy for Emacs. ^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: Further CC-mode changes 2014-09-16 23:40 ` Stephen J. Turnbull 2014-09-17 1:02 ` Stefan Monnier 2014-09-17 5:24 ` Eli Zaretskii @ 2014-09-18 9:44 ` Emilio Lopes 2 siblings, 0 replies; 41+ messages in thread From: Emilio Lopes @ 2014-09-18 9:44 UTC (permalink / raw) To: emacs-devel 2014-09-17 1:40 GMT+02:00 Stephen J. Turnbull <stephen@xemacs.org>: > But no, what it depends on is whether you use those versions or not. > Two separate surveys of large (>100) corporate Emacsen populations > taken in 2003 and 2007 showed that around 10% of users were using > 10-year-old or older Emacsen. Even Microsoft has been taught that > lesson. […] And from those "around 10% of users who were using 10-year-old or older Emacsen", how many of them update their CC-mode? Emílio ^ permalink raw reply [flat|nested] 41+ messages in thread
end of thread, other threads:[~2014-09-26 19:19 UTC | newest] Thread overview: 41+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2014-05-02 5:26 POC: customizable cc-mode keywords Daniel Colascione 2014-05-10 23:13 ` Daniel Colascione 2014-05-11 21:13 ` Alan Mackenzie 2014-05-11 21:23 ` Daniel Colascione 2014-05-16 17:52 ` Alan Mackenzie 2014-05-16 18:06 ` Daniel Colascione 2014-05-18 21:33 ` Alan Mackenzie 2014-05-18 22:28 ` Daniel Colascione 2014-05-19 2:25 ` Stefan Monnier 2014-05-25 18:08 ` Alan Mackenzie 2014-09-08 17:28 ` Stefan Monnier 2014-09-11 13:55 ` Further CC-mode changes Stefan Monnier 2014-09-12 23:59 ` Alan Mackenzie 2014-09-13 1:09 ` Ivan Andrus 2014-09-13 10:04 ` Alan Mackenzie 2014-09-13 3:04 ` Stefan Monnier 2014-09-13 15:10 ` Alan Mackenzie 2014-09-13 19:24 ` Stefan Monnier 2014-09-13 23:08 ` Syntax-propertize and CC-mode [Was: Further CC-mode changes] Alan Mackenzie 2014-09-14 4:04 ` Stefan Monnier 2014-09-16 17:30 ` Sync'ing cc-mode Stefan Monnier 2014-09-26 19:19 ` Stefan Monnier 2014-09-15 20:24 ` Further CC-mode changes Glenn Morris 2014-09-16 3:07 ` Stephen J. Turnbull 2014-09-16 13:39 ` Stefan Monnier 2014-09-16 14:22 ` David Kastrup 2014-09-16 23:40 ` Stephen J. Turnbull 2014-09-17 1:02 ` Stefan Monnier 2014-09-17 1:48 ` Stephen J. Turnbull 2014-09-17 5:22 ` David Kastrup 2014-09-17 13:00 ` Stefan Monnier 2014-09-17 18:31 ` Glenn Morris 2014-09-17 19:12 ` David Kastrup 2014-09-17 5:24 ` Eli Zaretskii 2014-09-17 6:54 ` Stephen J. Turnbull 2014-09-17 7:20 ` Eli Zaretskii 2014-09-17 7:30 ` David Kastrup 2014-09-17 13:04 ` Stefan Monnier 2014-09-17 18:25 ` Glenn Morris 2014-09-18 5:20 ` Stephen J. Turnbull 2014-09-18 9:44 ` Emilio Lopes
Code repositories for project(s) associated with this public inbox https://git.savannah.gnu.org/cgit/emacs.git This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).