From: Alan M. <ac...@mu...> - 2011-12-11 12:05:25
|
Hi, Hannu. On Fri, Oct 21, 2011 at 04:01:06PM +0300, Hannu Koivisto wrote: > Hi, > With the latest CVS version of CC Mode as of this writing running > in Emacs 24.0.50.1, the following code in foo.c file and a buffer > of that file in c-mode, you'll get the indentation you see below: > #ifndef G > #define G(symbol) pieni_ ## symbol > #endif > typedef struct G(foobar) *G(foobar_t); > typedef int lahna; > Perhaps interestingly the "typedef int lahna;" is indented > correctly if I switch to c++-mode instead; it seems that the > typedef looks like a k&r function definition if the macro is not > understood. I don't know if CC mode even tries to grok macros. Please try out the following patch and let me know what you think. It introduces a toggle to disable K&R parsing. You do this by C-c C-k or M-x c-toggle-knr. (Note: the patched CC Mode must be the first CC Mode loaded into the running Emacs for C-c C-k to work. I haven't found how to get round this, yet.) There is another indicator 'k' on the mode line, so that you will normally see "C/lk" before disabling it. There is also a new chapter in the manual about this. A few incidental things have been tidied up along the way. Here's the patch: *** orig/cc-cmds.el 2011-12-09 16:44:59.000000000 +0000 --- cc-cmds.el 2011-12-11 11:37:23.000000000 +0000 *************** *** 257,263 **** ;; Minor mode functions. (defun c-update-modeline () ! (let ((fmt (format "/%s%s%s%s" (if c-electric-flag "l" "") (if (and c-electric-flag c-auto-newline) "a" "") --- 257,263 ---- ;; Minor mode functions. (defun c-update-modeline () ! (let ((fmt (format "/%s%s%s%s%s" (if c-electric-flag "l" "") (if (and c-electric-flag c-auto-newline) "a" "") *************** *** 267,273 **** (boundp 'c-subword-mode) (symbol-value 'c-subword-mode)) "w" ! ""))) (bare-mode-name (if (string-match "\\(^[^/]*\\)/" mode-name) (substring mode-name (match-beginning 1) (match-end 1)) mode-name))) --- 267,274 ---- (boundp 'c-subword-mode) (symbol-value 'c-subword-mode)) "w" ! "") ! (if (and c-recognize-knr-p c-knr-flag) "k" ""))) (bare-mode-name (if (string-match "\\(^[^/]*\\)/" mode-name) (substring mode-name (match-beginning 1) (match-end 1)) mode-name))) *************** *** 324,329 **** --- 325,345 ---- (defalias 'c-toggle-auto-state 'c-toggle-auto-newline) (make-obsolete 'c-toggle-auto-state 'c-toggle-auto-newline nil) + (defun c-toggle-knr (&optional arg) + "Toggle recognition of K&R style function definitions. + Optional numeric ARG, if supplied, turns on auto-newline when + positive, turns it off when negative, and just toggles it when zero or + left out. + + This feature can only be enabled for languages, e.g. C, which + implement K&R function definitions." + (interactive "P") + (if c-recognize-knr-p + (progn + (setq c-knr-flag (c-calculate-state arg c-knr-flag)) + (c-update-modeline)) + (message "K&R style headers don't exist in the current major mode"))) + (defun c-toggle-hungry-state (&optional arg) "Toggle hungry-delete-key feature. Optional numeric ARG, if supplied, turns on hungry-delete when *************** *** 1426,1432 **** (save-excursion (and (c-syntactic-re-search-forward "[;{]" nil t t) (or (eq (char-before) ?\{) ! (and c-recognize-knr-p ;; Might have stopped on the ;; ';' in a K&R argdecl. In ;; that case the declaration --- 1442,1448 ---- (save-excursion (and (c-syntactic-re-search-forward "[;{]" nil t t) (or (eq (char-before) ?\{) ! (and (c-knr-enabled) ;; Might have stopped on the ;; ';' in a K&R argdecl. In ;; that case the declaration *** orig/cc-defs.el 2011-12-09 16:44:59.000000000 +0000 --- cc-defs.el 2011-12-09 17:31:52.000000000 +0000 *************** *** 1214,1219 **** --- 1214,1223 ---- ;; when the files are compiled in a certain order within the same ;; session. + (defsubst c-knr-enabled () + ;; t when K&R constructs are recognized, nil otherwise. + (and c-recognize-knr-p c-knr-flag)) + (defsubst c-end-of-defun-1 () ;; Replacement for end-of-defun that use c-beginning-of-defun-1. (let ((start (point))) *** orig/cc-engine.el 2011-12-09 16:44:59.000000000 +0000 --- cc-engine.el 2011-12-10 17:47:53.000000000 +0000 *************** *** 189,194 **** --- 189,199 ---- ;; (defvar c-submode-indicators nil) ;; (make-variable-buffer-local 'c-submode-indicators) + ;; Is K&R mode currently enabled? (Only meaningful for modes where + ;; c-recognize-knr-p is non-nil.) + (defvar c-knr-flag t) + (make-variable-buffer-local 'c-knr-flag) + (defun c-calculate-state (arg prevstate) ;; Calculate the new state of PREVSTATE, t or nil, based on arg. If ;; arg is nil or zero, toggle the state. If arg is negative, turn *************** *** 6795,6801 **** ;; 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 '<>) --- 6800,6806 ---- ;; 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-knr-enabled)) (not c-recognize-paren-inits)) (memq at-type '(known found)))) ((eq context '<>) *************** *** 7821,7827 **** move tentative-move)) (goto-char beg)) ! (when c-recognize-knr-p (let ((fallback-pos (point)) knr-argdecl-start) ;; Handle K&R argdecls. Back up after the "statement" jumped ;; over by `c-beginning-of-statement-1', unless it was the --- 7826,7832 ---- move tentative-move)) (goto-char beg)) ! (when (c-knr-enabled) (let ((fallback-pos (point)) knr-argdecl-start) ;; Handle K&R argdecls. Back up after the "statement" jumped ;; over by `c-beginning-of-statement-1', unless it was the *************** *** 7897,7903 **** (catch 'return (c-search-decl-header-end) ! (when (and c-recognize-knr-p (eq (char-before) ?\;) (c-in-knr-argdecl start)) ;; Stopped at the ';' in a K&R argdecl section which is --- 7902,7908 ---- (catch 'return (c-search-decl-header-end) ! (when (and (c-knr-enabled) (eq (char-before) ?\;) (c-in-knr-argdecl start)) ;; Stopped at the ';' in a K&R argdecl section which is *************** *** 9427,9433 **** (c-add-syntax 'member-init-cont (point)))) ;; CASE 5B.2: K&R arg decl intro ! ((and c-recognize-knr-p (c-in-knr-argdecl lim)) (c-beginning-of-statement-1 lim) (c-add-syntax 'knr-argdecl-intro (c-point 'boi)) --- 9432,9438 ---- (c-add-syntax 'member-init-cont (point)))) ;; CASE 5B.2: K&R arg decl intro ! ((and (c-knr-enabled) (c-in-knr-argdecl lim)) (c-beginning-of-statement-1 lim) (c-add-syntax 'knr-argdecl-intro (c-point 'boi)) *************** *** 9662,9668 **** paren-state)) ;; CASE 5H: we could be looking at subsequent knr-argdecls ! ((and c-recognize-knr-p (not containing-sexp) ; can't be knr inside braces. (not (eq char-before-ip ?})) (save-excursion --- 9667,9673 ---- paren-state)) ;; CASE 5H: we could be looking at subsequent knr-argdecls ! ((and (c-knr-enabled) (not containing-sexp) ; can't be knr inside braces. (not (eq char-before-ip ?})) (save-excursion *** orig/cc-fonts.el 2011-12-09 16:44:59.000000000 +0000 --- cc-fonts.el 2011-12-10 10:04:59.000000000 +0000 *************** *** 1291,1296 **** --- 1291,1307 ---- (type (setq context 'arglist c-restricted-<>-arglists t)) + ;; A comma separated list in braces (an enum?) + ((let* ((paren-state + (save-excursion + (goto-char match-pos) + (c-parse-state))) + (enclosing-paren-pos + (c-most-enclosing-brace paren-state))) + (and enclosing-paren-pos + (eq (char-after enclosing-paren-pos) ?\{))) + (setq context nil + c-restricted-<>-arglists t)) ((if inside-macro (< match-pos max-type-decl-end-before-token) (< match-pos max-type-decl-end)) *************** *** 1400,1407 **** ;; is there, then fontify the declarators accordingly. (let ((decl-search-lim (max (- (point) 50000) (point-min))) paren-state bod-res encl-pos is-typedef ! c-recognize-knr-p) ; Strictly speaking, bogus, but it ! ; speeds up lisp.h tremendously. (save-excursion (setq bod-res (car (c-beginning-of-decl-1 decl-search-lim))) (if (and (eq bod-res 'same) --- 1411,1417 ---- ;; is there, then fontify the declarators accordingly. (let ((decl-search-lim (max (- (point) 50000) (point-min))) paren-state bod-res encl-pos is-typedef ! c-knr-flag) (save-excursion (setq bod-res (car (c-beginning-of-decl-1 decl-search-lim))) (if (and (eq bod-res 'same) *** orig/cc-mode.el 2011-12-09 16:44:59.000000000 +0000 --- cc-mode.el 2011-12-09 17:38:05.000000000 +0000 *************** *** 361,366 **** --- 361,367 ---- (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-k" 'c-toggle-knr) (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) *** orig/cc-mode.texi 2011-12-09 16:44:59.000000000 +0000 --- cc-mode.texi 2011-12-11 11:28:42.000000000 +0000 *************** *** 241,246 **** --- 241,247 ---- * Indentation Engine Basics:: * Customizing Indentation:: * Custom Macros:: + * K&R Function Headers:: * Odds and Ends:: * Sample .emacs File:: * Performance Issues:: *************** *** 317,323 **** * Literal Symbols:: * Multiline Macro Symbols:: * Objective-C Method Symbols:: ! * Java Symbols:: * Statement Block Symbols:: * K&R Symbols:: --- 318,324 ---- * Literal Symbols:: * Multiline Macro Symbols:: * Objective-C Method Symbols:: ! * Java Symbols:: * Statement Block Symbols:: * K&R Symbols:: *************** *** 1063,1069 **** string literals, the new line gets the same indentation as the previous nonempty line.@footnote{You can change this default by setting the @code{string} syntactic symbol (@pxref{Syntactic Symbols} ! and @pxref{Customizing Indentation})}. @table @asis @item @kbd{M-q} (@code{c-fill-paragraph}) --- 1064,1070 ---- string literals, the new line gets the same indentation as the previous nonempty line.@footnote{You can change this default by setting the @code{string} syntactic symbol (@pxref{Syntactic Symbols} ! and @pxref{Customizing Indentation}).}. @table @asis @item @kbd{M-q} (@code{c-fill-paragraph}) *************** *** 1162,1172 **** structure. Otherwise, a line is simply indented to the same level as the previous one and @kbd{@key{TAB}} adjusts the indentation in steps of `c-basic-offset'. @end table Full details on how these minor modes work are at @ref{Electric Keys}, @ref{Auto-newlines}, @ref{Hungry WS Deletion}, @ref{Subword Movement}, ! and @ref{Indentation Engine Basics}. You can toggle each of these minor modes on and off, and you can configure @ccmode{} so that it starts up with your favourite --- 1163,1176 ---- structure. Otherwise, a line is simply indented to the same level as the previous one and @kbd{@key{TAB}} adjusts the indentation in steps of `c-basic-offset'. + @item K&R mode + When enabled, CC Mode parses old fashioned ''K&R'' function + declarations. This minor mode applies only to C Mode. @end table Full details on how these minor modes work are at @ref{Electric Keys}, @ref{Auto-newlines}, @ref{Hungry WS Deletion}, @ref{Subword Movement}, ! @ref{Indentation Engine Basics}, and @ref{K&R Function Headers}. You can toggle each of these minor modes on and off, and you can configure @ccmode{} so that it starts up with your favourite *************** *** 1177,1186 **** @ccmode{} displays the current state of the first four of these minor modes on the mode line by appending letters to the major mode's name, one letter for each enabled minor mode - @samp{l} for electric mode, ! @samp{a} for auto-newline mode, @samp{h} for hungry delete mode, and ! @samp{w} for subword mode. If all these modes were enabled, you'd see ! @samp{C/lahw}@footnote{The @samp{C} would be replaced with the name of ! the language in question for the other languages @ccmode{} supports.}. Here are the commands to toggle these modes: --- 1181,1191 ---- @ccmode{} displays the current state of the first four of these minor modes on the mode line by appending letters to the major mode's name, one letter for each enabled minor mode - @samp{l} for electric mode, ! @samp{a} for auto-newline mode, @samp{h} for hungry delete mode, ! @samp{w} for subword mode, and @samp{k} for K&R mode. If all these ! modes were enabled, you'd see @samp{C/lahwk}@footnote{The @samp{C} ! would be replaced with the name of the language in question for the ! other languages @ccmode{} supports.}. Here are the commands to toggle these modes: *************** *** 1209,1224 **** @findex toggle-auto-hungry-state (c-) Toggle both auto-newline and hungry delete minor modes. ! @item @kbd{C-c C-w} (@code{M-x c-subword-mode}) @kindex C-c C-w @findex c-subword-mode @findex subword-mode (c-) ! Toggle subword mode. @item @kbd{M-x c-toggle-syntactic-indentation} @findex c-toggle-syntactic-indentation @findex toggle-syntactic-indentation (c-) ! Toggle syntactic-indentation mode. @end table Common to all the toggle functions above is that if they are called --- 1214,1235 ---- @findex toggle-auto-hungry-state (c-) Toggle both auto-newline and hungry delete minor modes. ! @item @kbd{C-c C-w} (@code{c-subword-mode}) @kindex C-c C-w @findex c-subword-mode @findex subword-mode (c-) ! Toggle subword minor mode. @item @kbd{M-x c-toggle-syntactic-indentation} @findex c-toggle-syntactic-indentation @findex toggle-syntactic-indentation (c-) ! Toggle syntactic-indentation minor mode. ! ! @item @kbd{C-c C-k} (@code{c-toggle-knr}) ! @kindex C-c C-k ! @findex c-toggle-knr ! @findex toggle-knr (c-) ! Toggle K&R minor mode. @end table Common to all the toggle functions above is that if they are called *************** *** 4263,4269 **** * Literal Symbols:: * Multiline Macro Symbols:: * Objective-C Method Symbols:: ! * Java Symbols:: * Statement Block Symbols:: * K&R Symbols:: @end menu --- 4274,4280 ---- * Literal Symbols:: * Multiline Macro Symbols:: * Objective-C Method Symbols:: ! * Java Symbols:: * Statement Block Symbols:: * K&R Symbols:: @end menu *************** *** 4497,4503 **** that closes the inner substatement block, and is therefore given the syntax @code{block-close}@footnote{@code{block-open} is used only for ``free-standing'' blocks, and is somewhat rare (@pxref{Literal ! Symbols} for an example.)}. Line 13 is treated the same way. @ssindex substatement Lines 6 and 9 are also substatements of conditionals, but since they --- 4508,4514 ---- that closes the inner substatement block, and is therefore given the syntax @code{block-close}@footnote{@code{block-open} is used only for ``free-standing'' blocks, and is somewhat rare (@pxref{Literal ! Symbols} for an example).}. Line 13 is treated the same way. @ssindex substatement Lines 6 and 9 are also substatements of conditionals, but since they *************** *** 6606,6612 **** @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! @node Custom Macros, Odds and Ends, Customizing Indentation, Top @comment node-name, next, previous, up @chapter Customizing Macros @cindex macros --- 6617,6623 ---- @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! @node Custom Macros, K&R Function Headers, Customizing Indentation, Top @comment node-name, next, previous, up @chapter Customizing Macros @cindex macros *************** *** 6751,6757 **** @end defun @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! @node Odds and Ends, Sample .emacs File, Custom Macros, Top @comment node-name, next, previous, up @chapter Odds and Ends @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! --- 6762,6809 ---- @end defun @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! @node K&R Function Headers, Odds and Ends, Custom Macros, Top ! @comment node-name, next, previous, up ! @chapter K&R Function Headers ! @cindex K&R function headers ! @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! ! In the original C language, the types of parameters in function ! headers were written outside the parentheses which enclosed the ! parameter names. Such a construct is now known as a @dfn{K&R function ! header}@footnote{named after the authors of the first book on C, Brian ! Kernighan and Dennis Ritchie.} and typically looks like this: ! ! @example ! int foo (baz, bar) ! int baz; ! int *bar; ! @{ ! .... ! @} ! @end example ! ! Although K&R headers are obsolete, there are still a fair number of ! them in old code. C Mode parses these headers reasonably well, but ! this parsing sometimes causes performance problems. Also, in some ! cases declarations are wrongly interpreted, particularly when they use ! macros. ! ! You can now prevent K&R parsing in a C Mode buffer by disabling K&R ! minor mode (with @kbd{C-c C-k}, @pxref{Minor Modes}). To disable it ! automatically for all C Mode buffers, put the following code in your ! @file{.emacs}: ! ! @example ! (add-hook 'c-mode-hook ! (lambda () (c-toggle-knr -1))) ! @end example ! ! Note that this chapter applies only to C Mode; the other @ccmode{} ! languages don't have K&R function headers. ! ! @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! @node Odds and Ends, Sample .emacs File, K&R Function Headers, Top @comment node-name, next, previous, up @chapter Odds and Ends @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! *************** *** 6793,6799 **** anchoring position to indent the line in that case. @end defopt - @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! @node Sample .emacs File, Performance Issues, Odds and Ends, Top @comment node-name, next, previous, up --- 6845,6850 ---- > -- > Hannu -- Alan Mackenzie (Nuremberg, Germany). |