From unknown Fri Jun 20 07:13:00 2025 Content-Disposition: inline Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 X-Mailer: MIME-tools 5.509 (Entity 5.509) Content-Type: text/plain; charset=utf-8 From: bug#28050 <28050@debbugs.gnu.org> To: bug#28050 <28050@debbugs.gnu.org> Subject: Status: CC Mode 5.33 (C/*l); indentation of array and enum in GNU style isn't right Reply-To: bug#28050 <28050@debbugs.gnu.org> Date: Fri, 20 Jun 2025 14:13:00 +0000 retitle 28050 CC Mode 5.33 (C/*l); indentation of array and enum in GNU sty= le isn't right reassign 28050 cc-mode submitter 28050 Mohammed Sadiq severity 28050 normal thanks From debbugs-submit-bounces@debbugs.gnu.org Fri Aug 11 13:22:52 2017 Received: (at submit) by debbugs.gnu.org; 11 Aug 2017 17:22:52 +0000 Received: from localhost ([127.0.0.1]:55947 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1dgDe8-0005Js-68 for submit@debbugs.gnu.org; Fri, 11 Aug 2017 13:22:52 -0400 Received: from us2-ob4-7.mailhostbox.com ([199.79.62.66]:37611) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1dgDe6-0005Jk-3N for submit@debbugs.gnu.org; Fri, 11 Aug 2017 13:22:51 -0400 Received: from rose (unknown [117.249.193.42]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) (Authenticated sender: sadiq@sadiqpk.org) by us2.outbound.mailhostbox.com (Postfix) with ESMTPSA id 0EE1B1C15B5 for ; Fri, 11 Aug 2017 17:22:41 +0000 (GMT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sadiqpk.org; s=20160628; t=1502472164; bh=KbIysoNFX09yKQqbR64xwx15uWBIeBDehcyIj4QzZ1Q=; h=From:To:Subject:Date; b=JURpGSYYzPPj0Y5lAcVV10KfYEtSHJvWmOuF+ByO5Hm3iMEznmjR03+YqNdLihu1S bhSO82ThMHhPBydZoN16w4xAQh1HFHAClFC0LG9taw0K86DgyfUkKbSGuzBgHbu40t 9Bj8fzNY+zx64izRYBhhQWOhjOcElVVhyfxI3Guw= From: Mohammed Sadiq To: submit@debbugs.gnu.org Subject: CC Mode 5.33 (C/*l); indentation of array and enum in GNU style isn't right X-Debbugs-Package: cc-mode Date: Fri, 11 Aug 2017 22:50:02 +0530 Message-ID: <871soiggxp.fsf@rose> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-CMAE-Score: 0 X-CMAE-Analysis: v=2.2 cv=EPx26xRC c=1 sm=1 tr=0 a=yHQRXb9K0b9XaUK9GDPCgw==:117 a=yHQRXb9K0b9XaUK9GDPCgw==:17 a=IkcTkHD0fZMA:10 a=ZaYFdioFuIm4U0tRfMEA:9 a=QEXdDO2ut3YA:10 X-Spam-Score: -0.0 (/) X-Debbugs-Envelope-To: submit X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -0.0 (/) For the following code, the indentation of the code isn't right for GNU style (C-x h TAB after writing the code): /* Output after default (auto)indentation in GNU Emacs (TAB is used sometim= es) */ char *words[] =3D { "good", "better", "best" }; The GNU style is (as done by the program GNU indent): /* They should be indented with 2 spaces (and not TABs) char *words[] =3D { "good", "better", "best" }; Tabs are also add for indentation when defining enums: typedef enum { GOOD, BETTER, BEST } test; The following might be better (2 spaces, and no TABs): typedef enum { GOOD, BETTER, BEST } test; Emacs : GNU Emacs 26.0.50 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.22= .11) of 2017-08-11 Package: CC Mode 5.33 (C/*l) Buffer Style: gnu c-emacs-features: (pps-extended-state col-0-paren posix-char-classes gen-st= ring-delim gen-comment-delim syntax-properties 1-bit) current state: =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D (setq c-basic-offset 2 c-comment-only-line-offset '(0 . 0) c-indent-comment-alist '((anchored-comment column . 0) (end-block space . = 1) (cpp-end-block space . 2)) c-indent-comments-syntactically-p nil c-block-comment-prefix "" c-comment-prefix-regexp '((pike-mode . "//+!?\\|\\**") (awk-mode . "#+") (other . "//+\\|\\**")) c-doc-comment-style '((java-mode . javadoc) (pike-mode . autodoc) (c-mode . gtkdoc)) c-cleanup-list '(scope-operator) c-hanging-braces-alist '((substatement-open before after) (arglist-cont-nonempty)) c-hanging-colons-alist nil c-hanging-semi&comma-criteria '(c-semi&comma-inside-parenlist) c-backslash-column 48 c-backslash-max-column 72 c-special-indent-hook '(c-gnu-impose-minimum) c-label-minimum-indentation 1 c-offsets-alist '((inexpr-class . +) (inexpr-statement . +) (lambda-intro-cont . +) (inlambda . c-lineup-inexpr-block) (template-args-cont c-lineup-template-args +) (incomposition . +) (inmodule . +) (innamespace . +) (inextern-lang . +) (composition-close . 0) (module-close . 0) (namespace-close . 0) (extern-lang-close . 0) (composition-open . 0) (module-open . 0) (namespace-open . 0) (extern-lang-open . 0) (objc-method-call-cont c-lineup-ObjC-method-call-colons c-lineup-ObjC-method-call + ) (objc-method-args-cont . c-lineup-ObjC-method-args) (objc-method-intro . [0]) (friend . 0) (cpp-define-intro c-lineup-cpp-define +) (cpp-macro-cont . +) (cpp-macro . [0]) (inclass . +) (stream-op . c-lineup-streamop) (arglist-cont-nonempty c-lineup-gcc-asm-reg c-lineup-arglist ) (arglist-cont c-lineup-gcc-asm-reg 0) (comment-intro c-lineup-knr-region-comment c-lineup-comment) (catch-clause . 0) (else-clause . 0) (do-while-closure . 0) (access-label . -) (case-label . 0) (substatement . +) (statement-case-intro . +) (statement . 0) (brace-entry-open . 0) (brace-list-entry . c-lineup-under-anchor) (brace-list-close . 0) (block-close . 0) (block-open . 0) (inher-cont . c-lineup-multi-inher) (inher-intro . +) (member-init-cont . c-lineup-multi-inher) (member-init-intro . +) (annotation-var-cont . +) (annotation-top-cont . 0) (topmost-intro . 0) (knr-argdecl . 0) (func-decl-cont . +) (inline-close . 0) (class-close . 0) (class-open . 0) (defun-block-intro . +) (defun-close . 0) (defun-open . 0) (c . c-lineup-C-comments) (string . c-lineup-dont-change) (topmost-intro-cont first c-lineup-topmost-intro-cont c-lineup-gnu-DEFUN-intro-cont ) (brace-list-intro . c-lineup-arglist-intro-after-paren) (brace-list-open . +) (inline-open . 0) (arglist-close . c-lineup-arglist) (arglist-intro . c-lineup-arglist-intro-after-paren) (statement-cont . +) (statement-case-open . +) (label . 0) (substatement-label . 0) (substatement-open . +) (knr-argdecl-intro . 5) (statement-block-intro . +) ) c-buffer-is-cc-mode 'c-mode c-tab-always-indent t c-syntactic-indentation t c-syntactic-indentation-in-macros t c-ignore-auto-fill '(string cpp code) c-auto-align-backslashes t c-backspace-function 'backward-delete-char-untabify c-delete-function 'delete-char c-electric-pound-behavior nil c-default-style '((java-mode . "java") (awk-mode . "awk") (other . "gnu")) c-enable-xemacs-performance-kludge-p nil c-old-style-variable-behavior nil defun-prompt-regexp nil tab-width 8 comment-column 32 parse-sexp-ignore-comments t parse-sexp-lookup-properties t auto-fill-function nil comment-multi-line t comment-start-skip "\\(//+\\|/\\*+\\)\\s *" fill-prefix nil fill-column 70 paragraph-start "[ ]*\\(//+\\|\\**\\)[ ]*$\\|^\f" adaptive-fill-mode t adaptive-fill-regexp "[ ]*\\(//+\\|\\**\\)[ ]*\\([ ]*\\([-=E2=80=93!|#%= ;>*=C2=B7=E2=80=A2=E2=80=A3=E2=81=83=E2=97=A6]+[ ]*\\)*\\)" ) From debbugs-submit-bounces@debbugs.gnu.org Sat Sep 22 15:35:23 2018 Received: (at 28050) by debbugs.gnu.org; 22 Sep 2018 19:35:23 +0000 Received: from localhost ([127.0.0.1]:49888 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1g3ngZ-0002VS-8p for submit@debbugs.gnu.org; Sat, 22 Sep 2018 15:35:23 -0400 Received: from colin.muc.de ([193.149.48.1]:59751 helo=mail.muc.de) by debbugs.gnu.org with smtp (Exim 4.84_2) (envelope-from ) id 1g3ngW-0002VI-Oz for 28050@debbugs.gnu.org; Sat, 22 Sep 2018 15:35:21 -0400 Received: (qmail 40438 invoked by uid 3782); 22 Sep 2018 19:35:19 -0000 Received: from acm.muc.de (p5B147403.dip0.t-ipconnect.de [91.20.116.3]) by colin.muc.de (tmda-ofmipd) with ESMTP; Sat, 22 Sep 2018 21:35:18 +0200 Received: (qmail 12881 invoked by uid 1000); 22 Sep 2018 19:30:59 -0000 Date: Sat, 22 Sep 2018 19:30:59 +0000 To: Mohammed Sadiq Subject: Re: bug#28050: CC Mode 5.33 (C/*l); indentation of array and enum in GNU style isn't right Message-ID: <20180922193059.GA12536@ACM> References: <871soiggxp.fsf@rose> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: <871soiggxp.fsf@rose> User-Agent: Mutt/1.10.1 (2018-07-13) X-Delivery-Agent: TMDA/1.1.12 (Macallan) From: Alan Mackenzie X-Primary-Address: acm@muc.de X-Spam-Score: -0.0 (/) X-Debbugs-Envelope-To: 28050 Cc: 28050@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) Hello, Mohammed. It's been over a year since you reported the bug below. I'm top-posting this, so that you see exactly what you wrote, it being so long ago. Sorry about this delay. Are you still interested in this bug? This has been a difficult bug to solve, not for the cases you gave, e.g.: typedef enum { GOOD, BETTER, BEST }; but the case in which the first element inside the braces is on the same line as the opening brace: typedef enum {GOOD, BETTER, BEST }; , which surely ought to be indented as above (I'm using a c-basic-offset of 4 for clarity in the examples), and _not_ like this: typedef enum {GOOD, BETTER, BEST }; . However, Emacs bug #24431 from Matthias Meulien, complained about the exact opposite. His case was that the following C++ was mis-aligned: set_line(line_t{point_t{0.4, 0.2}, point_t{0.2, 0.5}}); // wrong identation , and that the second line should line up with the "point_t" in the first line. I "fixed" this bug, hence the trouble with GOOD, BETTER, and BEST. My trouble with bug #24431 was I didn't realise that that was a special case. What makes it so was the opening paren after "set_line", a bit of DWIM ("Do what I mean"). I think I've now (almost) got this sorted out. I'm applying the following rules to brace lists in "gnu" style and several other styles: 1. When the first entry is on the next line after the brace, it will be indented by c-basic-offset ("+"), as will the following entries. 2. When the first entry is on the _same_ line as the brace, the following entries are normally indented by c-basic-offset. 3. As an exception to 2., if the line with the opening brace and first entry has a "(" or another "{" earlier on IN THE LINE, the second and subsequent entries are lined up under the first entry: set_line(line_t{point_t{0.4, 0.2}, point_t{0.2, 0.5}}); 4. As a further exception to 2, when a variable of a struct, union, class, .... type is being declared like in the following example, the second and subsequent entries are indented c-basic-offset from THE VARIABLE, not from the start of the declaration: 1. struct STR { 2. int i; float f; 3. } str_1 = /* ; */ {1, 1.7}, 4. str_2 = {2, 5. 3.1 <================================ 6. }; Critical here is that the brace block of "struct STR" is present, and one or more variables of this type are declared at the same place. The "3.1" on line 5 is indented from the "str_2" on line 4, NOT from the anchor point which is "struct" on line 1. However, the changes to implement these rules have produced a patch a little under 600 lines long. :-( These changes are not quite finished: some doc strings need writing, and some new line-up functions need to be documented in the CC Mode manual. However, other than that it is ready. Are you still interested in this bug? If so, would you be prepared to apply this ~600 line patch, compile it, and test it? If so, I would be grateful. :-) If so 2, would you please tell me in your reply which CC Mode sources you are using (I'm a bit sloppy with version numbers). Are you using the standalone CC Mode from sourceforge, or the version distributed together with Emacs 26? Knowing this would help me prepare the patch for the version of CC Mode you're actually using. -- Alan Mackenzie (Nuremberg, Germany). On Fri, Aug 11, 2017 at 22:50:02 +0530, Mohammed Sadiq wrote: > For the following code, the indentation of the code isn't right for GNU > style (C-x h TAB after writing the code): > /* Output after default (auto)indentation in GNU Emacs (TAB is used sometimes) */ > char *words[] = { > "good", > "better", > "best" > }; > The GNU style is (as done by the program GNU indent): > /* They should be indented with 2 spaces (and not TABs) > char *words[] = { > "good", > "better", > "best" > }; > Tabs are also add for indentation when defining enums: > typedef enum { > GOOD, > BETTER, > BEST > } test; > The following might be better (2 spaces, and no TABs): > typedef enum { > GOOD, > BETTER, > BEST > } test; > Emacs : GNU Emacs 26.0.50 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.22.11) > of 2017-08-11 > Package: CC Mode 5.33 (C/*l) > Buffer Style: gnu > c-emacs-features: (pps-extended-state col-0-paren posix-char-classes gen-string-delim gen-comment-delim syntax-properties 1-bit) > current state: > ============== > (setq > c-basic-offset 2 > c-comment-only-line-offset '(0 . 0) > c-indent-comment-alist '((anchored-comment column . 0) (end-block space . 1) > (cpp-end-block space . 2)) > c-indent-comments-syntactically-p nil > c-block-comment-prefix "" > c-comment-prefix-regexp '((pike-mode . "//+!?\\|\\**") (awk-mode . "#+") > (other . "//+\\|\\**")) > c-doc-comment-style '((java-mode . javadoc) (pike-mode . autodoc) > (c-mode . gtkdoc)) > c-cleanup-list '(scope-operator) > c-hanging-braces-alist '((substatement-open before after) > (arglist-cont-nonempty)) > c-hanging-colons-alist nil > c-hanging-semi&comma-criteria '(c-semi&comma-inside-parenlist) > c-backslash-column 48 > c-backslash-max-column 72 > c-special-indent-hook '(c-gnu-impose-minimum) > c-label-minimum-indentation 1 > c-offsets-alist '((inexpr-class . +) > (inexpr-statement . +) > (lambda-intro-cont . +) > (inlambda . c-lineup-inexpr-block) > (template-args-cont c-lineup-template-args +) > (incomposition . +) > (inmodule . +) > (innamespace . +) > (inextern-lang . +) > (composition-close . 0) > (module-close . 0) > (namespace-close . 0) > (extern-lang-close . 0) > (composition-open . 0) > (module-open . 0) > (namespace-open . 0) > (extern-lang-open . 0) > (objc-method-call-cont > c-lineup-ObjC-method-call-colons > c-lineup-ObjC-method-call > + > ) > (objc-method-args-cont . c-lineup-ObjC-method-args) > (objc-method-intro . [0]) > (friend . 0) > (cpp-define-intro c-lineup-cpp-define +) > (cpp-macro-cont . +) > (cpp-macro . [0]) > (inclass . +) > (stream-op . c-lineup-streamop) > (arglist-cont-nonempty > c-lineup-gcc-asm-reg > c-lineup-arglist > ) > (arglist-cont c-lineup-gcc-asm-reg 0) > (comment-intro c-lineup-knr-region-comment c-lineup-comment) > (catch-clause . 0) > (else-clause . 0) > (do-while-closure . 0) > (access-label . -) > (case-label . 0) > (substatement . +) > (statement-case-intro . +) > (statement . 0) > (brace-entry-open . 0) > (brace-list-entry . c-lineup-under-anchor) > (brace-list-close . 0) > (block-close . 0) > (block-open . 0) > (inher-cont . c-lineup-multi-inher) > (inher-intro . +) > (member-init-cont . c-lineup-multi-inher) > (member-init-intro . +) > (annotation-var-cont . +) > (annotation-top-cont . 0) > (topmost-intro . 0) > (knr-argdecl . 0) > (func-decl-cont . +) > (inline-close . 0) > (class-close . 0) > (class-open . 0) > (defun-block-intro . +) > (defun-close . 0) > (defun-open . 0) > (c . c-lineup-C-comments) > (string . c-lineup-dont-change) > (topmost-intro-cont > first > c-lineup-topmost-intro-cont > c-lineup-gnu-DEFUN-intro-cont > ) > (brace-list-intro . c-lineup-arglist-intro-after-paren) > (brace-list-open . +) > (inline-open . 0) > (arglist-close . c-lineup-arglist) > (arglist-intro . c-lineup-arglist-intro-after-paren) > (statement-cont . +) > (statement-case-open . +) > (label . 0) > (substatement-label . 0) > (substatement-open . +) > (knr-argdecl-intro . 5) > (statement-block-intro . +) > ) > c-buffer-is-cc-mode 'c-mode > c-tab-always-indent t > c-syntactic-indentation t > c-syntactic-indentation-in-macros t > c-ignore-auto-fill '(string cpp code) > c-auto-align-backslashes t > c-backspace-function 'backward-delete-char-untabify > c-delete-function 'delete-char > c-electric-pound-behavior nil > c-default-style '((java-mode . "java") (awk-mode . "awk") (other . "gnu")) > c-enable-xemacs-performance-kludge-p nil > c-old-style-variable-behavior nil > defun-prompt-regexp nil > tab-width 8 > comment-column 32 > parse-sexp-ignore-comments t > parse-sexp-lookup-properties t > auto-fill-function nil > comment-multi-line t > comment-start-skip "\\(//+\\|/\\*+\\)\\s *" > fill-prefix nil > fill-column 70 > paragraph-start "[ ]*\\(//+\\|\\**\\)[ ]*$\\|^\f" > adaptive-fill-mode t > adaptive-fill-regexp "[ ]*\\(//+\\|\\**\\)[ ]*\\([ ]*\\([-–!|#%;>*·•‣⁃◦]+[ ]*\\)*\\)" > ) > ------------------------------------------------------------------------------ > Check out the vibrant tech community on one of the world's most > engaging tech sites, Slashdot.org! http://sdm.link/slashdot From debbugs-submit-bounces@debbugs.gnu.org Tue Sep 25 15:37:18 2018 Received: (at 28050) by debbugs.gnu.org; 25 Sep 2018 19:37:18 +0000 Received: from localhost ([127.0.0.1]:54039 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1g4t93-0000qa-LJ for submit@debbugs.gnu.org; Tue, 25 Sep 2018 15:37:18 -0400 Received: from colin.muc.de ([193.149.48.1]:16828 helo=mail.muc.de) by debbugs.gnu.org with smtp (Exim 4.84_2) (envelope-from ) id 1g4t91-0000qM-Bs for 28050@debbugs.gnu.org; Tue, 25 Sep 2018 15:37:16 -0400 Received: (qmail 24459 invoked by uid 3782); 25 Sep 2018 19:37:13 -0000 Received: from acm.muc.de (p5B147FF7.dip0.t-ipconnect.de [91.20.127.247]) by colin.muc.de (tmda-ofmipd) with ESMTP; Tue, 25 Sep 2018 21:37:12 +0200 Received: (qmail 25989 invoked by uid 1000); 25 Sep 2018 19:32:21 -0000 Date: Tue, 25 Sep 2018 19:32:21 +0000 To: Mohammed Sadiq Subject: Re: bug#28050: CC Mode 5.33 (C/*l); indentation of array and enum in GNU style isn't right Message-ID: <20180925193221.GA25925@ACM> References: <871soiggxp.fsf@rose> <20180922193059.GA12536@ACM> <1c9eca6d5c0e9b5dfb7d9c65443e6cca@sadiqpk.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <1c9eca6d5c0e9b5dfb7d9c65443e6cca@sadiqpk.org> User-Agent: Mutt/1.10.1 (2018-07-13) X-Delivery-Agent: TMDA/1.1.12 (Macallan) From: Alan Mackenzie X-Primary-Address: acm@muc.de X-Spam-Score: -0.0 (/) X-Debbugs-Envelope-To: 28050 Cc: 28050@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) Hello, Mohammed. On Sun, Sep 23, 2018 at 05:47:29 +0530, Mohammed Sadiq wrote: > On 2018-09-23 01:00, Alan Mackenzie wrote: > Hi, > > It's been over a year since you reported the bug below. I'm > > top-posting this, so that you see exactly what you wrote, it being so > > long ago. Sorry about this delay. Are you still interested in this > > bug? > > This has been a difficult bug to solve, not for the cases you gave, > > e.g.: > > typedef enum { > > GOOD, > > BETTER, > > BEST > > }; > I think I filed a bug for all of them to be miss-indented (Not just the > first item) Sorry, I believe you did indeed. > ie, this: > typedef enum { > GOOD, > BAD, > NICE, > }; > typedef enum {GOOD, > BETTER, > BEST > }; > [ ... ] > > However, the changes to implement these rules have produced a patch a > > little under 600 lines long. :-( These changes are not quite > > finished: some doc strings need writing, and some new line-up > > functions need to be documented in the CC Mode manual. However, > > other than that it is ready. > > Are you still interested in this bug? If so, would you be prepared to > > apply this ~600 line patch, compile it, and test it? If so, I would be > Sure I'm interested. I have been using the following in my .dir-locals > as a fix for this: > ((nil . ((fill-column . 80))) > (c-mode . ((c-file-style . "GNU") > (c-file-offsets > (brace-list-intro . +))))) > > grateful. :-) If so 2, would you please tell me in your reply which > > CC Mode sources you are using (I'm a bit sloppy with version > > numbers). > I'm using the builtin cc-mode in GNU Emacs 27.x (from git master branch) OK. Here's (part of) the patch. I haven't included the amendment to the CC Mode manual for now, but I doubt that will bother you too much. Would you please follow the following directions carefully: it's all too easy to end up with a mixture of old and new (I've done that several times): 1. Please apply the patch to the files in ..../emacs/lisp/progmodes, then byte compile CC Mode in its entirety. Something like $ emacs -Q -batch -f batch-byte-compile lisp/progmodes/cc-*.el will do it. Then please do either: 2a. Move the newly generated .elc files to where your Emacs finds its CC Mode, e.g. ..../emacs/lisp/progmodes. Then restart Emacs. OR 2b. (Assuming your initialisation files don't load a particular other version of CC Mode) restart your Emacs using -L, like this: $ emacs -L path/to/new/CC/Mode . This should ensure that the old CC Mode doesn't prevent the new one loading fully. Please then remove your workaround from .dir-locals, and test the new CC Mode with your real source code. Please let me know how well it works, telling me about any problems you might still find. Thanks! diff -r e38b65ad9145 cc-align.el --- a/cc-align.el Mon Aug 27 20:23:23 2018 +0000 +++ b/cc-align.el Tue Sep 25 19:01:56 2018 +0000 @@ -1086,6 +1086,130 @@ (vector (+ (current-column) c-basic-offset)))) (vector 0))))) +(defun c-lineup-2nd-brace-entry-in-arglist (langelem) + "Lineup the second entry of a brace block under the first, when the first +line is also contained in an arglist or an enclosing brace ON THAT LINE. + +I.e. handle something like the following: + + set_line (line_t {point_t{0.4, 0.2}, + point_t{0.2, 0.5}, <---- brace-list-intro + .....}); + ^ enclosing parenthesis. + +The middle line of that example will have a syntactic context +with three syntactic symbols, arglist-cont-nonempty, brace-list-intro, and +brace-list-entry. + +This function is intended for use in a list. If the construct +being analyzed isn't like the preceding, the function returns nil. +Otherwise it returns the function `c-lineup-arglist-intro-after-paren', which +the caller then uses to perform indentation. + +Works with brace-list-intro." + ;; brace-list-intro and brace-list-entry are both present for the second + ;; entry of the list when the first entry is on the same line as the opening + ;; brace. + (and (assq 'brace-list-intro c-syntactic-context) + (assq 'brace-list-entry c-syntactic-context) + (or (assq 'arglist-cont-nonempty c-syntactic-context) ; "(" earlier on + ; the line. + (save-excursion ; "{" earlier on the line + (goto-char (c-langelem-pos + (assq 'brace-list-intro c-syntactic-context))) + (and + (eq (c-backward-token-2 + 1 nil + (c-point 'bol (c-langelem-pos + (assq 'brace-list-entry + c-syntactic-context)))) + 0) + (eq (char-after) ?{)))) + 'c-lineup-arglist-intro-after-paren)) + +(defun c-lineup-class-decl-init-+ (langelem) + "Line up the second entry of a class (etc.) initializer c-basic-offset +characters in from the identifier when: +\(i) The type is a class, struct, union, etc. (but not an enum); +\(ii) There is a brace block in the type declaration, specifying it; and +\(iii) The first element of the initializer is on the same line as its opening +brace. + +I.e. we have a construct like this: + + struct STR { + int i; float f; + } str_1 = {1, 1.7}, + str_2 = {2, + 3.1 <---- brace-list-intro + }; + <--> <---- c-basic-offset + +Note that the syntactic context of the brace-list-intro line also has a +syntactic element with the symbol brace-list-entry. + +This function is intended for use in a list. If the above structure isn't +present, this function returns nil, allowing a different offset specification +to indent the line. + +Works with: brace-list-intro." + (and (assq 'brace-list-intro c-syntactic-context) + (assq 'brace-list-entry c-syntactic-context) + (let ((init-pos (c-point 'boi (c-langelem-pos + (assq 'brace-list-entry + c-syntactic-context)))) + ) + (save-excursion + (goto-char (c-langelem-pos (assq 'brace-list-intro + c-syntactic-context))) + (and + (c-forward-class-decl) + (not (c-do-declarators init-pos t nil nil nil)) + (eq (point) init-pos) + (vector (+ (current-column) c-basic-offset))))))) + +(defun c-lineup-class-decl-init-after-brace (langelem) + "Line up the second entry of a class (etc.) initializer after its opening +brace when: +\(i) The type is a class, struct, union, etc. (but not an enum); +\(ii) There is a brace block in the type declaration, specifying it; and +\(iii) The first element of the initializer is on the same line as its opening +brace. + +I.e. we have a construct like this: + + struct STR { + int i; float f; + } str_1 = {1, 1.7}, + str_2 = {2, + 3.1 <---- brace-list-intro + }; + +Note that the syntactic context of the brace-list-intro line also has a +syntactic element with the symbol brace-list-entry. Also note that this +function works by returning the symbol `c-lineup-arglist-intro-after-paren', +which the caller then uses to perform the indentation. + +This function is intended for use in a list. If the above structure isn't +present, this function returns nil, allowing a different offset specification +to indent the line. + +Works with: brace-list-intro." + (and (assq 'brace-list-intro c-syntactic-context) + (assq 'brace-list-entry c-syntactic-context) + (let ((init-pos (c-point 'boi (c-langelem-pos + (assq 'brace-list-entry + c-syntactic-context)))) + ) + (save-excursion + (goto-char (c-langelem-pos (assq 'brace-list-intro + c-syntactic-context))) + (and + (c-forward-class-decl) + (not (c-do-declarators init-pos t nil nil nil)) + (eq (point) init-pos) + 'c-lineup-arglist-intro-after-paren))))) + (defun c-lineup-cpp-define (_langelem) "Line up macro continuation lines according to the indentation of the construct preceding the macro. E.g.: diff -r e38b65ad9145 cc-engine.el --- a/cc-engine.el Mon Aug 27 20:23:23 2018 +0000 +++ b/cc-engine.el Tue Sep 25 19:01:56 2018 +0000 @@ -7936,49 +7936,28 @@ (or res (goto-char here)) res)) +(defun c-forward-class-decl () + "From the beginning of a struct/union, etc. move forward to +after the brace block which defines it, leaving point at the +start of the next token and returning pointt. On failure leave +point unchanged and return nil." + (let ((here (point))) + (if + (and + (looking-at c-class-key) + (eq (c-forward-token-2) 0) + (c-on-identifier) + (eq (c-forward-token-2) 0) + (eq (char-after) ?{) + (c-go-list-forward)) + (progn + (c-forward-syntactic-ws) + (point)) + (goto-char here) + nil))) ;; Handling of large scale constructs like statements and declarations. -;; Macro used inside `c-forward-decl-or-cast-1'. It ought to be a -;; defsubst or perhaps even a defun, but it contains lots of free -;; variables that refer to things inside `c-forward-decl-or-cast-1'. -(defmacro c-fdoc-shift-type-backward (&optional short) - ;; `c-forward-decl-or-cast-1' can consume an arbitrary length list - ;; of types when parsing a declaration, which means that it - ;; sometimes consumes the identifier in the declaration as a type. - ;; This is used to "backtrack" and make the last type be treated as - ;; an identifier instead. - `(progn - ,(unless short - ;; These identifiers are bound only in the inner let. - '(setq identifier-type at-type - identifier-start type-start - got-parens nil - got-identifier t - got-suffix t - got-suffix-after-parens id-start - paren-depth 0)) - - (if (setq at-type (if (eq backup-at-type 'prefix) - t - backup-at-type)) - (setq type-start backup-type-start - id-start backup-id-start) - (setq type-start start-pos - id-start start-pos)) - - ;; When these flags already are set we've found specifiers that - ;; unconditionally signal these attributes - backtracking doesn't - ;; change that. So keep them set in that case. - (or at-type-decl - (setq at-type-decl backup-at-type-decl)) - (or maybe-typeless - (setq maybe-typeless backup-maybe-typeless)) - - ,(unless short - ;; This identifier is bound only in the inner let. - '(setq start id-start)))) - (defun c-forward-declarator (&optional limit accept-anon) ;; Assuming point is at the start of a declarator, move forward over it, ;; leaving point at the next token after it (e.g. a ) or a ; or a ,). @@ -8131,6 +8110,171 @@ (goto-char here) nil))) +(defun c-do-declarators (limit list not-top comma-prop cdd-function) + "Assuming point is at the start of a comma separated list of declarators, +apply CDD-FUNCTION to each declarator (when LIST is non-nil) or just the +first declarator (when LIST is nil). When CDD-FUNCTION is nil, no +function is applied. + +CDD-FUNCTION is supplied with 6 arguments: +0. The start position of the declarator's identifier; +1. The end position of this identifier; +\[Note: if there is no identifier, as in int (*);, both of these are nil.] +2. The position of the next token after the declarator (CLARIFY!!!). +3. NOT-TOP; +4. Non-nil if the identifier is of a function. +5. When there is an initialization following the declarator (such as \"= +....\" or \"( ....\".), the character which introduces this initialization, +otherwise nil. + +Additionally, if COMMA-PROP is non-nil, mark the separating commas with +this value of the c-type property, when LIST is non-nil. + +Stop at or before LIMIT (which may NOT be nil). + +If NOT-TOP is non-nil, we are not at the top-level (\"top-level\" includes +being directly inside a class or namespace, etc.). + +Nil is always returned. The function leaves point at the delimiter after +the last declarator it processes. FIXME!!! Check this (2018-09-21) + +This function might do hidden buffer changes." + (let + ((pos (point)) next-pos id-start id-end + decl-res got-func got-type got-init + c-last-identifier-range exhausted result) + + ;; The following `while' fontifies a single declarator id each time round. + ;; It loops only when LIST is non-nil. + (while + (and (not exhausted) + (setq decl-res (c-forward-declarator limit))) + (setq next-pos (point) + id-start (car decl-res) + id-end (cadr decl-res) + got-func (and (eq (char-after) ?\() + (or (not (c-major-mode-is 'c++-mode)) + (not not-top) + (car (cddr (cddr decl-res))) ; Id is in + ; parens, etc. + (save-excursion + (forward-char) + (c-forward-syntactic-ws) + (looking-at "[*&]"))) + (not (car (cddr decl-res))) + (or (not (c-major-mode-is 'c++-mode)) + (save-excursion + (let (c-last-identifier-range) + (forward-char) + (c-forward-syntactic-ws) + (catch 'is-function + (while + (progn + (if (eq (char-after) ?\)) + (throw 'is-function t)) + (setq got-type (c-forward-type)) + (cond + ((null got-type) + (throw 'is-function nil)) + ((not (eq got-type 'maybe)) + (throw 'is-function t))) + (c-forward-declarator nil t) + (eq (char-after) ?,)) + (forward-char) + (c-forward-syntactic-ws)) + t))))) + got-init (and (cadr (cddr decl-res)) + (char-after))) + + ;; Jump past any initializer or function prototype to see if + ;; there's a ',' to continue at. + (cond (got-func + ;; Skip a parenthesized initializer (C++) or a function + ;; prototype. + (if (c-go-list-forward (point) limit) ; over the parameter list. + (c-forward-syntactic-ws limit) + (setq exhausted t))) ; unbalanced parens + + (got-init ; "=" sign OR opening "(", "[", or "{" + ;; Skip an initializer expression. If we're at a '=' + ;; then accept a brace list directly after it to cope + ;; with array initializers. Otherwise stop at braces + ;; to avoid going past full function and class blocks. + (if (and (if (and (eq got-init ?=) + (= (c-forward-token-2 1 nil limit) 0) + (looking-at "{")) + (c-go-list-forward (point) limit) + t) + ;; FIXME: Should look for c-decl-end markers here; + ;; we might go far into the following declarations + ;; in e.g. ObjC mode (see e.g. methods-4.m). + (c-syntactic-re-search-forward "[;,{]" limit 'move t)) + (backward-char) + (setq exhausted t) + )) + + (t (c-forward-syntactic-ws limit))) + + (if cdd-function + (funcall cdd-function id-start id-end next-pos not-top got-func + got-init)) + + ;; If a ',' is found we set pos to the next declarator and iterate. + (if (and list (< (point) limit) (looking-at ",")) + (progn + (when comma-prop + (c-put-char-property (point) 'c-type comma-prop)) + (when list + (forward-char) + (c-forward-syntactic-ws limit) + (setq pos (point)))) + (setq exhausted t))) + + (if (> (point) pos) + t + (goto-char pos) + nil))) + +;; Macro used inside `c-forward-decl-or-cast-1'. It ought to be a +;; defsubst or perhaps even a defun, but it contains lots of free +;; variables that refer to things inside `c-forward-decl-or-cast-1'. +(defmacro c-fdoc-shift-type-backward (&optional short) + ;; `c-forward-decl-or-cast-1' can consume an arbitrary length list + ;; of types when parsing a declaration, which means that it + ;; sometimes consumes the identifier in the declaration as a type. + ;; This is used to "backtrack" and make the last type be treated as + ;; an identifier instead. + `(progn + ,(unless short + ;; These identifiers are bound only in the inner let. + '(setq identifier-type at-type + identifier-start type-start + got-parens nil + got-identifier t + got-suffix t + got-suffix-after-parens id-start + paren-depth 0)) + + (if (setq at-type (if (eq backup-at-type 'prefix) + t + backup-at-type)) + (setq type-start backup-type-start + id-start backup-id-start) + (setq type-start start-pos + id-start start-pos)) + + ;; When these flags already are set we've found specifiers that + ;; unconditionally signal these attributes - backtracking doesn't + ;; change that. So keep them set in that case. + (or at-type-decl + (setq at-type-decl backup-at-type-decl)) + (or maybe-typeless + (setq maybe-typeless backup-maybe-typeless)) + + ,(unless short + ;; This identifier is bound only in the inner let. + '(setq start id-start)))) + (defun c-forward-decl-or-cast-1 (preceding-token-end context last-cast-end) ;; Move forward over a declaration or a cast if at the start of one. ;; The point is assumed to be at the start of some token. Nil is @@ -10608,12 +10752,17 @@ ))) (defun c-inside-bracelist-p (containing-sexp paren-state accept-in-paren) - ;; return the buffer position of the beginning of the brace list - ;; statement if we're inside a brace list, otherwise return nil. - ;; CONTAINING-SEXP is the buffer pos of the innermost containing - ;; paren. PAREN-STATE is the remainder of the state of enclosing - ;; braces. ACCEPT-IN-PAREN is non-nil iff we will accept as a brace - ;; list a brace directly enclosed in a parenthesis. + ;; return the buffer position of the beginning of the brace list statement + ;; if CONTAINING-SEXP is inside a brace list, otherwise return nil. + ;; + ;; CONTAINING-SEXP is the buffer pos of the innermost containing paren. NO + ;; IT ISN'T!!! [This function is badly designed, and probably needs + ;; reformulating without its first argument, and the critical position being + ;; at point.] + ;; + ;; PAREN-STATE is the remainder of the state of enclosing braces. + ;; ACCEPT-IN-PAREN is non-nil iff we will accept as a brace list a brace + ;; directly enclosed in a parenthesis. ;; ;; The "brace list" here is recognized solely by its context, not by ;; its contents. @@ -10733,7 +10882,8 @@ (defun c-looking-at-statement-block () ;; Point is at an opening brace. If this is a statement block (i.e. the ;; elements in the block are terminated by semicolons, or the block is - ;; empty, or the block contains a keyword) return t. Otherwise, return nil. + ;; empty, or the block contains a keyword) return non-nil. Otherwise, + ;; return nil. (let ((here (point))) (prog1 (if (c-go-list-forward) @@ -11237,7 +11387,7 @@ (if (and (eq step-type 'same) (/= paren-pos (point))) - (let (inexpr) + (let (inexpr bspec) (cond ((save-excursion (goto-char paren-pos) @@ -11259,6 +11409,13 @@ (c-looking-at-statement-block)) (c-add-syntax 'defun-block-intro nil) (c-add-syntax 'brace-list-intro nil))) + ((save-excursion + (goto-char paren-pos) + (setq bspec (c-looking-at-or-maybe-in-bracelist + containing-sexp containing-sexp)) + (and (consp bspec) + (eq (cdr bspec) 'in-paren))) + (c-add-syntax 'brace-list-intro (car bspec))) (t (c-add-syntax 'defun-block-intro nil)))) (c-add-syntax 'statement-block-intro nil))) @@ -13082,7 +13239,7 @@ Cannot combine relative offset %S with absolute %S in `%s' method" (car offset) symbol res val method) (setq res (vector (funcall method (aref res 0) - (aref val 0))))))) + (aref val 0))))))) (setq offset (cdr offset))) res)) @@ -13126,7 +13283,7 @@ nil)))) (if (or (null res) (integerp res) - (and (vectorp res) (= (length res) 1) (integerp (aref res 0)))) + (and (vectorp res) (>= (length res) 1) (integerp (aref res 0)))) res (c-benign-error "Error evaluating offset %S for %s: Got invalid value %S" offset symbol res) @@ -13149,12 +13306,11 @@ (if c-strict-syntax-p (c-benign-error "No offset found for syntactic symbol %s" symbol)) (setq offset 0)) - (if (vectorp offset) - offset - (or (and (numberp offset) offset) - (and (symbolp offset) (symbol-value offset)) - 0)) - )) + (cond + ((or (vectorp offset) (numberp offset)) + offset) + ((and (symbolp offset) (symbol-value offset))) + (t 0)))) (defun c-get-offset (langelem) ;; This is a compatibility wrapper for `c-calc-offset' in case diff -r e38b65ad9145 cc-fonts.el --- a/cc-fonts.el Mon Aug 27 20:23:23 2018 +0000 +++ b/cc-fonts.el Tue Sep 25 19:01:56 2018 +0000 @@ -1029,114 +1029,41 @@ ;;(message "c-font-lock-declarators from %s to %s" (point) limit) (c-fontify-types-and-refs - ((pos (point)) next-pos id-start - decl-res - id-face got-type got-init - c-last-identifier-range - (separator-prop (if types 'c-decl-type-start 'c-decl-id-start))) - - ;; The following `while' fontifies a single declarator id each time round. - ;; It loops only when LIST is non-nil. - (while - (and pos (setq decl-res (c-forward-declarator))) - (setq next-pos (point) - id-start (car decl-res) - id-face (if (and (eq (char-after) ?\() - (or (not (c-major-mode-is 'c++-mode)) - (not not-top) - (car (cddr (cddr decl-res))) ; Id is in - ; parens, etc. - (save-excursion - (forward-char) - (c-forward-syntactic-ws) - (looking-at "[*&]"))) - (not (car (cddr decl-res))) - (or (not (c-major-mode-is 'c++-mode)) - (save-excursion - (let (c-last-identifier-range) - (forward-char) - (c-forward-syntactic-ws) - (catch 'is-function - (while - (progn - (if (eq (char-after) ?\)) - (throw 'is-function t)) - (setq got-type (c-forward-type)) - (cond - ((null got-type) - (throw 'is-function nil)) - ((not (eq got-type 'maybe)) - (throw 'is-function t))) - (c-forward-declarator nil t) - (eq (char-after) ?,)) - (forward-char) - (c-forward-syntactic-ws)) - t))))) - 'font-lock-function-name-face - 'font-lock-variable-name-face) - got-init (and (cadr (cddr decl-res)) ; got-init - (char-after))) - - (if types - ;; Register and fontify the identifier as a type. - (let ((c-promote-possible-types t)) - (goto-char id-start) - (c-forward-type)) - ;; Fontify the last symbol in the identifier if it isn't fontified - ;; already. The check is necessary only in certain cases where this - ;; function is used "sloppily", e.g. in `c-simple-decl-matchers'. - (when (and c-last-identifier-range - (not (get-text-property (car c-last-identifier-range) - 'face))) - (c-put-font-lock-face (car c-last-identifier-range) - (cdr c-last-identifier-range) - id-face))) - - (goto-char next-pos) - (setq pos nil) ; So as to terminate the enclosing `while' form. - (if (and template-class - (eq got-init ?=) ; C++ ""? - (c-forward-token-2 1 nil limit) ; Over "=" - (let ((c-promote-possible-types t)) - (c-forward-type t))) ; Over "Y" - (setq list nil)) ; Shouldn't be needed. We can't have a list, here. - - (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. - (if (c-safe (c-forward-sexp 1) t) ; over the parameter list. - (c-forward-syntactic-ws limit) - (goto-char limit))) ; unbalanced parens - - (got-init ; "=" sign OR opening "(", "[", or "{" - ;; Skip an initializer expression. If we're at a '=' - ;; then accept a brace list directly after it to cope - ;; with array initializers. Otherwise stop at braces - ;; to avoid going past full function and class blocks. - (and (if (and (eq got-init ?=) - (= (c-forward-token-2 1 nil limit) 0) - (looking-at "{")) - (c-safe (c-forward-sexp) t) ; over { .... } - t) - (< (point) limit) - ;; FIXME: Should look for c-decl-end markers here; - ;; we might go far into the following declarations - ;; in e.g. ObjC mode (see e.g. methods-4.m). - (c-syntactic-re-search-forward "[;,{]" limit 'move t) - (backward-char))) - - (t (c-forward-syntactic-ws limit))) - - ;; If a ',' is found we set pos to the next declarator and iterate. - (when (and (< (point) limit) (looking-at ",")) - (c-put-char-property (point) 'c-type separator-prop) - (forward-char) - (c-forward-syntactic-ws limit) - (setq pos (point)))))) ; acts to make the `while' form continue. - nil) + () + (c-do-declarators + limit list not-top + (if types 'c-decl-type-start 'c-decl-id-start) + (lambda (id-start id-end end-pos not-top is-function init-char) + (if types + ;; Register and fontify the identifier as a type. + (let ((c-promote-possible-types t)) + (goto-char id-start) + (c-forward-type)) + ;; The following doesn't work properly (yet, 2018-09-22). + ;; (c-put-font-lock-face id-start id-end + ;; (if is-function + ;; 'font-lock-function-name-face + ;; 'font-lock-variable-name-face)) + (when (and c-last-identifier-range + (not (get-text-property (car c-last-identifier-range) + 'face))) + ;; We use `c-last-identifier-range' rather than `id-start' and + ;; `id-end', since the latter two can be erroneous. E.g. in + ;; "~Foo", `id-start' is at the tilde. This is a bug in + ;; `c-forward-declarator'. + (c-put-font-lock-face (car c-last-identifier-range) + (cdr c-last-identifier-range) + (if is-function + 'font-lock-function-name-face + 'font-lock-variable-name-face)))) + (and template-class + (eq init-char ?=) ; C++ ""? + (progn + (goto-char end-pos) + (c-forward-token-2 1 nil limit) ; Over "=" + (let ((c-promote-possible-types t)) + (c-forward-type t)))))) + nil)) (defun c-get-fontification-context (match-pos not-front-decl &optional toplev) ;; Return a cons (CONTEXT . RESTRICTED-<>-ARGLISTS) for MATCH-POS. diff -r e38b65ad9145 cc-langs.el --- a/cc-langs.el Mon Aug 27 20:23:23 2018 +0000 +++ b/cc-langs.el Tue Sep 25 19:01:56 2018 +0000 @@ -3221,7 +3221,8 @@ "\\|" "\\.\\.\\." "\\|" - "[*(&]" +; "[*(&]" + "[*(&~]" "\\|" (c-lang-const c-type-decl-prefix-key) "\\|" diff -r e38b65ad9145 cc-mode.el --- a/cc-mode.el Mon Aug 27 20:23:23 2018 +0000 +++ b/cc-mode.el Tue Sep 25 19:01:56 2018 +0000 @@ -1781,7 +1781,20 @@ (while ;; Go to a less nested declaration each time round this loop. (and - (c-syntactic-skip-backward "^;{}" bod-lim t) +;;;; OLD STOUGH, 2018-09-22 + ;(c-syntactic-skip-backward "^;{}" bod-lim t) +;;;; NEW STOUGH, 2018-09-22 + (let (pseudo) + (while + (progn + (c-syntactic-skip-backward "^;{}" bod-lim t) + (and (eq (char-before) ?}) + (save-excursion + (backward-char) + (setq pseudo (c-cheap-inside-bracelist-p (c-parse-state)))))) + (goto-char pseudo)) + t) +;;;; END OF NEW STOUGH (> (point) bod-lim) (progn (c-forward-syntactic-ws) (setq bo-decl (point)) diff -r e38b65ad9145 cc-styles.el --- a/cc-styles.el Mon Aug 27 20:23:23 2018 +0000 +++ b/cc-styles.el Tue Sep 25 19:01:56 2018 +0000 @@ -73,7 +73,9 @@ (arglist-close . c-lineup-arglist) (inline-open . 0) (brace-list-open . +) - (brace-list-intro . c-lineup-arglist-intro-after-paren) + (brace-list-intro . (first + c-lineup-2nd-brace-entry-in-arglist + c-lineup-class-decl-init-+ +)) (topmost-intro-cont . (first c-lineup-topmost-intro-cont c-lineup-gnu-DEFUN-intro-cont)))) @@ -100,6 +102,9 @@ (label . 0) (statement-cont . +) (inline-open . 0) + (brace-list-intro . (first + c-lineup-2nd-brace-entry-in-arglist + c-lineup-class-decl-init-+ +)) (inexpr-class . 0)))) ("stroustrup" @@ -109,6 +114,9 @@ (substatement-open . 0) (substatement-label . 0) (label . 0) + (brace-list-intro . (first + c-lineup-2nd-brace-entry-in-arglist + c-lineup-class-decl-init-+ +)) (statement-cont . +)))) ("whitesmith" @@ -199,6 +207,9 @@ (c-offsets-alist . ((substatement-open . 0) (inextern-lang . 0) (arglist-intro . +) + (brace-list-intro . (first + c-lineup-2nd-brace-entry-in-arglist + c-lineup-class-decl-init-+ +)) (knr-argdecl-intro . +))) (c-hanging-braces-alist . ((brace-list-open) (brace-list-intro) @@ -224,6 +235,9 @@ (statement-cont . +) (arglist-intro . c-lineup-arglist-intro-after-paren) (arglist-close . c-lineup-arglist) + (brace-list-intro . (first + c-lineup-2nd-brace-entry-in-arglist + c-lineup-class-decl-init-+ +)) (access-label . 0) (inher-cont . c-lineup-java-inher) (func-decl-cont . c-lineup-java-throws)))) diff -r e38b65ad9145 cc-vars.el --- a/cc-vars.el Mon Aug 27 20:23:23 2018 +0000 +++ b/cc-vars.el Tue Sep 25 19:01:56 2018 +0000 @@ -1117,7 +1117,7 @@ ;; Anchor pos: At the brace list decl start(*). (brace-list-intro . +) ;; Anchor pos: At the brace list decl start(*). - (brace-list-entry . c-lineup-under-anchor) + (brace-list-entry . 0) ;; Anchor pos: At the first non-ws char after the open paren if ;; the first token is on the same line, otherwise boi at that ;; token. > [ ... ] > Thanks -- Alan Mackenzie (Nuremberg, Germany). From debbugs-submit-bounces@debbugs.gnu.org Thu Sep 27 07:09:46 2018 Received: (at 28050) by debbugs.gnu.org; 27 Sep 2018 11:09:46 +0000 Received: from localhost ([127.0.0.1]:55929 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1g5UB0-0001C3-Ky for submit@debbugs.gnu.org; Thu, 27 Sep 2018 07:09:46 -0400 Received: from relay4-d.mail.gandi.net ([217.70.183.196]:38909) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1g5UAy-0001Bu-Qz for 28050@debbugs.gnu.org; Thu, 27 Sep 2018 07:09:45 -0400 Received: from webmail.gandi.net (webmail2.sd4.0x35.net [10.200.201.2]) (Authenticated sender: sadiq@sadiqpk.org) by relay4-d.mail.gandi.net (Postfix) with ESMTPA id 933B5E000A; Thu, 27 Sep 2018 11:09:43 +0000 (UTC) MIME-Version: 1.0 Content-Type: text/plain; charset=US-ASCII; format=flowed Content-Transfer-Encoding: 7bit Date: Thu, 27 Sep 2018 16:39:43 +0530 From: Mohammed Sadiq To: Alan Mackenzie Subject: Re: bug#28050: CC Mode 5.33 (C/*l); indentation of array and enum in GNU style isn't right In-Reply-To: <20180925193221.GA25925@ACM> References: <871soiggxp.fsf@rose> <20180922193059.GA12536@ACM> <1c9eca6d5c0e9b5dfb7d9c65443e6cca@sadiqpk.org> <20180925193221.GA25925@ACM> Message-ID: X-Sender: sadiq@sadiqpk.org User-Agent: Roundcube Webmail/1.1.2 X-Spam-Score: -0.7 (/) X-Debbugs-Envelope-To: 28050 Cc: 28050@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.7 (-) > On Sun, Sep 23, 2018 at 05:47:29 +0530, Mohammed Sadiq wrote: >> On 2018-09-23 01:00, Alan Mackenzie wrote: > diff -r e38b65ad9145 cc-align.el > --- a/cc-align.el Mon Aug 27 20:23:23 2018 +0000 > +++ b/cc-align.el Tue Sep 25 19:01:56 2018 +0000 [ ... ] Sorry the patch isn't applying the emacs master branch. And I'm now busy with some work to manually merge each change. It would be nice if you can rebase the patch over emacs master. Or is the patch against cc-mode from sourceforge? If you are busy too, please wait. I shall try again as I have time. I wish this to be fixed in 27.x. Thanks From debbugs-submit-bounces@debbugs.gnu.org Thu Sep 27 16:24:31 2018 Received: (at 28050) by debbugs.gnu.org; 27 Sep 2018 20:24:31 +0000 Received: from localhost ([127.0.0.1]:56974 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1g5cpq-0002Ur-E0 for submit@debbugs.gnu.org; Thu, 27 Sep 2018 16:24:31 -0400 Received: from colin.muc.de ([193.149.48.1]:33255 helo=mail.muc.de) by debbugs.gnu.org with smtp (Exim 4.84_2) (envelope-from ) id 1g5cpl-0002Ud-Fu for 28050@debbugs.gnu.org; Thu, 27 Sep 2018 16:24:28 -0400 Received: (qmail 5429 invoked by uid 3782); 27 Sep 2018 20:24:24 -0000 Received: from acm.muc.de (p5B147350.dip0.t-ipconnect.de [91.20.115.80]) by colin.muc.de (tmda-ofmipd) with ESMTP; Thu, 27 Sep 2018 22:24:23 +0200 Received: (qmail 16454 invoked by uid 1000); 27 Sep 2018 20:19:09 -0000 Date: Thu, 27 Sep 2018 20:19:09 +0000 To: Mohammed Sadiq Subject: Re: bug#28050: CC Mode 5.33 (C/*l); indentation of array and enum in GNU style isn't right Message-ID: <20180927201908.GB4015@ACM> References: <871soiggxp.fsf@rose> <20180922193059.GA12536@ACM> <1c9eca6d5c0e9b5dfb7d9c65443e6cca@sadiqpk.org> <20180925193221.GA25925@ACM> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="82I3+IH0IqGh5yIs" Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.10.1 (2018-07-13) X-Delivery-Agent: TMDA/1.1.12 (Macallan) From: Alan Mackenzie X-Primary-Address: acm@muc.de X-Spam-Score: -0.0 (/) X-Debbugs-Envelope-To: 28050 Cc: 28050@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) --82I3+IH0IqGh5yIs Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Hello, Mohammed On Thu, Sep 27, 2018 at 16:39:43 +0530, Mohammed Sadiq wrote: > > On Sun, Sep 23, 2018 at 05:47:29 +0530, Mohammed Sadiq wrote: > >> On 2018-09-23 01:00, Alan Mackenzie wrote: > > diff -r e38b65ad9145 cc-align.el > > --- a/cc-align.el Mon Aug 27 20:23:23 2018 +0000 > > +++ b/cc-align.el Tue Sep 25 19:01:56 2018 +0000 > [ ... ] > Sorry the patch isn't applying the emacs master branch. I'm sorry, too. Maybe including the patch inline wasn't such a brilliant idea. > And I'm now busy with some work to manually merge each change. > It would be nice if you can rebase the patch over emacs master. > Or is the patch against cc-mode from sourceforge? Could you try instead the attached patch file? Although the line numbers don't quite correspond with the Emacs master, it applies cleanly to Emacs master for me. Yes, I made the patch basically for the standalone CC Mode, but amended it to apply to the CC Mode in Emacs. > If you are busy too, please wait. I shall try again as I have > time. I wish this to be fixed in 27.x. This WILL be fixed for Emacs 27. :-) > Thanks Thank you for all the trouble you are taking. -- Alan Mackenzie (Nuremberg, Germany). --82I3+IH0IqGh5yIs Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="diff.20180927.diff" diff -r e38b65ad9145 cc-align.el --- a/cc-align.el Mon Aug 27 20:23:23 2018 +0000 +++ b/cc-align.el Thu Sep 27 19:58:29 2018 +0000 @@ -1086,6 +1086,130 @@ (vector (+ (current-column) c-basic-offset)))) (vector 0))))) +(defun c-lineup-2nd-brace-entry-in-arglist (_langelem) + "Lineup the second entry of a brace block under the first, when the first +line is also contained in an arglist or an enclosing brace ON THAT LINE. + +I.e. handle something like the following: + + set_line (line_t {point_t{0.4, 0.2}, + point_t{0.2, 0.5}, <---- brace-list-intro + .....}); + ^ enclosing parenthesis. + +The middle line of that example will have a syntactic context +with three syntactic symbols, arglist-cont-nonempty, brace-list-intro, and +brace-list-entry. + +This function is intended for use in a list. If the construct +being analyzed isn't like the preceding, the function returns nil. +Otherwise it returns the function `c-lineup-arglist-intro-after-paren', which +the caller then uses to perform indentation. + +Works with brace-list-intro." + ;; brace-list-intro and brace-list-entry are both present for the second + ;; entry of the list when the first entry is on the same line as the opening + ;; brace. + (and (assq 'brace-list-intro c-syntactic-context) + (assq 'brace-list-entry c-syntactic-context) + (or (assq 'arglist-cont-nonempty c-syntactic-context) ; "(" earlier on + ; the line. + (save-excursion ; "{" earlier on the line + (goto-char (c-langelem-pos + (assq 'brace-list-intro c-syntactic-context))) + (and + (eq (c-backward-token-2 + 1 nil + (c-point 'bol (c-langelem-pos + (assq 'brace-list-entry + c-syntactic-context)))) + 0) + (eq (char-after) ?{)))) + 'c-lineup-arglist-intro-after-paren)) + +(defun c-lineup-class-decl-init-+ (_langelem) + "Line up the second entry of a class (etc.) initializer c-basic-offset +characters in from the identifier when: +\(i) The type is a class, struct, union, etc. (but not an enum); +\(ii) There is a brace block in the type declaration, specifying it; and +\(iii) The first element of the initializer is on the same line as its opening +brace. + +I.e. we have a construct like this: + + struct STR { + int i; float f; + } str_1 = {1, 1.7}, + str_2 = {2, + 3.1 <---- brace-list-intro + }; + <--> <---- c-basic-offset + +Note that the syntactic context of the brace-list-intro line also has a +syntactic element with the symbol brace-list-entry. + +This function is intended for use in a list. If the above structure isn't +present, this function returns nil, allowing a different offset specification +to indent the line. + +Works with: brace-list-intro." + (and (assq 'brace-list-intro c-syntactic-context) + (assq 'brace-list-entry c-syntactic-context) + (let ((init-pos (c-point 'boi (c-langelem-pos + (assq 'brace-list-entry + c-syntactic-context)))) + ) + (save-excursion + (goto-char (c-langelem-pos (assq 'brace-list-intro + c-syntactic-context))) + (and + (c-forward-class-decl) + (not (c-do-declarators init-pos t nil nil nil)) + (eq (point) init-pos) + (vector (+ (current-column) c-basic-offset))))))) + +(defun c-lineup-class-decl-init-after-brace (_langelem) + "Line up the second entry of a class (etc.) initializer after its opening +brace when: +\(i) The type is a class, struct, union, etc. (but not an enum); +\(ii) There is a brace block in the type declaration, specifying it; and +\(iii) The first element of the initializer is on the same line as its opening +brace. + +I.e. we have a construct like this: + + struct STR { + int i; float f; + } str_1 = {1, 1.7}, + str_2 = {2, + 3.1 <---- brace-list-intro + }; + +Note that the syntactic context of the brace-list-intro line also has a +syntactic element with the symbol brace-list-entry. Also note that this +function works by returning the symbol `c-lineup-arglist-intro-after-paren', +which the caller then uses to perform the indentation. + +This function is intended for use in a list. If the above structure isn't +present, this function returns nil, allowing a different offset specification +to indent the line. + +Works with: brace-list-intro." + (and (assq 'brace-list-intro c-syntactic-context) + (assq 'brace-list-entry c-syntactic-context) + (let ((init-pos (c-point 'boi (c-langelem-pos + (assq 'brace-list-entry + c-syntactic-context)))) + ) + (save-excursion + (goto-char (c-langelem-pos (assq 'brace-list-intro + c-syntactic-context))) + (and + (c-forward-class-decl) + (not (c-do-declarators init-pos t nil nil nil)) + (eq (point) init-pos) + 'c-lineup-arglist-intro-after-paren))))) + (defun c-lineup-cpp-define (_langelem) "Line up macro continuation lines according to the indentation of the construct preceding the macro. E.g.: diff -r e38b65ad9145 cc-engine.el --- a/cc-engine.el Mon Aug 27 20:23:23 2018 +0000 +++ b/cc-engine.el Thu Sep 27 19:58:29 2018 +0000 @@ -7936,49 +7936,28 @@ (or res (goto-char here)) res)) +(defun c-forward-class-decl () + "From the beginning of a struct/union, etc. move forward to +after the brace block which defines it, leaving point at the +start of the next token and returning point. On failure leave +point unchanged and return nil." + (let ((here (point))) + (if + (and + (looking-at c-class-key) + (eq (c-forward-token-2) 0) + (c-on-identifier) + (eq (c-forward-token-2) 0) + (eq (char-after) ?{) + (c-go-list-forward)) + (progn + (c-forward-syntactic-ws) + (point)) + (goto-char here) + nil))) ;; Handling of large scale constructs like statements and declarations. -;; Macro used inside `c-forward-decl-or-cast-1'. It ought to be a -;; defsubst or perhaps even a defun, but it contains lots of free -;; variables that refer to things inside `c-forward-decl-or-cast-1'. -(defmacro c-fdoc-shift-type-backward (&optional short) - ;; `c-forward-decl-or-cast-1' can consume an arbitrary length list - ;; of types when parsing a declaration, which means that it - ;; sometimes consumes the identifier in the declaration as a type. - ;; This is used to "backtrack" and make the last type be treated as - ;; an identifier instead. - `(progn - ,(unless short - ;; These identifiers are bound only in the inner let. - '(setq identifier-type at-type - identifier-start type-start - got-parens nil - got-identifier t - got-suffix t - got-suffix-after-parens id-start - paren-depth 0)) - - (if (setq at-type (if (eq backup-at-type 'prefix) - t - backup-at-type)) - (setq type-start backup-type-start - id-start backup-id-start) - (setq type-start start-pos - id-start start-pos)) - - ;; When these flags already are set we've found specifiers that - ;; unconditionally signal these attributes - backtracking doesn't - ;; change that. So keep them set in that case. - (or at-type-decl - (setq at-type-decl backup-at-type-decl)) - (or maybe-typeless - (setq maybe-typeless backup-maybe-typeless)) - - ,(unless short - ;; This identifier is bound only in the inner let. - '(setq start id-start)))) - (defun c-forward-declarator (&optional limit accept-anon) ;; Assuming point is at the start of a declarator, move forward over it, ;; leaving point at the next token after it (e.g. a ) or a ; or a ,). @@ -8131,6 +8110,175 @@ (goto-char here) nil))) +(defun c-do-declarators + (cdd-limit cdd-list cdd-not-top cdd-comma-prop cdd-function) + "Assuming point is at the start of a comma separated list of declarators, +apply CDD-FUNCTION to each declarator (when CDD-LIST is non-nil) or just the +first declarator (when CDD-LIST is nil). When CDD-FUNCTION is nil, no +function is applied. + +CDD-FUNCTION is supplied with 6 arguments: +0. The start position of the declarator's identifier; +1. The end position of this identifier; +\[Note: if there is no identifier, as in int (*);, both of these are nil.] +2. The position of the next token after the declarator (CLARIFY!!!). +3. CDD-NOT-TOP; +4. Non-nil if the identifier is of a function. +5. When there is an initialization following the declarator (such as \"= +....\" or \"( ....\".), the character which introduces this initialization, +otherwise nil. + +Additionally, if CDD-COMMA-PROP is non-nil, mark the separating commas with +this value of the c-type property, when CDD-LIST is non-nil. + +Stop at or before CDD-LIMIT (which may NOT be nil). + +If CDD-NOT-TOP is non-nil, we are not at the top-level (\"top-level\" includes +being directly inside a class or namespace, etc.). + +Nil is always returned. The function leaves point at the delimiter after +the last declarator it processes. FIXME!!! Check this (2018-09-21) + +This function might do hidden buffer changes." + ;; N.B.: We use the "cdd-" prefix in this routine to try to prevent + ;; confusion with possible reference to common variable names from within + ;; CDD-FUNCTION. + (let + ((cdd-pos (point)) cdd-next-pos cdd-id-start cdd-id-end + cdd-decl-res cdd-got-func cdd-got-type cdd-got-init + c-last-identifier-range cdd-exhausted) + + ;; The following `while' fontifies a single declarator id each time round. + ;; It loops only when CDD-LIST is non-nil. + (while + (and (not cdd-exhausted) + (setq cdd-decl-res (c-forward-declarator cdd-limit))) + (setq cdd-next-pos (point) + cdd-id-start (car cdd-decl-res) + cdd-id-end (cadr cdd-decl-res) + cdd-got-func (and (eq (char-after) ?\() + (or (not (c-major-mode-is 'c++-mode)) + (not cdd-not-top) + (car (cddr (cddr cdd-decl-res))) ; Id is in + ; parens, etc. + (save-excursion + (forward-char) + (c-forward-syntactic-ws) + (looking-at "[*&]"))) + (not (car (cddr cdd-decl-res))) + (or (not (c-major-mode-is 'c++-mode)) + (save-excursion + (let (c-last-identifier-range) + (forward-char) + (c-forward-syntactic-ws) + (catch 'is-function + (while + (progn + (if (eq (char-after) ?\)) + (throw 'is-function t)) + (setq cdd-got-type (c-forward-type)) + (cond + ((null cdd-got-type) + (throw 'is-function nil)) + ((not (eq cdd-got-type 'maybe)) + (throw 'is-function t))) + (c-forward-declarator nil t) + (eq (char-after) ?,)) + (forward-char) + (c-forward-syntactic-ws)) + t))))) + cdd-got-init (and (cadr (cddr cdd-decl-res)) + (char-after))) + + ;; Jump past any initializer or function prototype to see if + ;; there's a ',' to continue at. + (cond (cdd-got-func + ;; Skip a parenthesized initializer (C++) or a function + ;; prototype. + (if (c-go-list-forward (point) cdd-limit) ; over the parameter list. + (c-forward-syntactic-ws cdd-limit) + (setq cdd-exhausted t))) ; unbalanced parens + + (cdd-got-init ; "=" sign OR opening "(", "[", or "{" + ;; Skip an initializer expression. If we're at a '=' + ;; then accept a brace list directly after it to cope + ;; with array initializers. Otherwise stop at braces + ;; to avoid going past full function and class blocks. + (if (and (if (and (eq cdd-got-init ?=) + (= (c-forward-token-2 1 nil cdd-limit) 0) + (looking-at "{")) + (c-go-list-forward (point) cdd-limit) + t) + ;; FIXME: Should look for c-decl-end markers here; + ;; we might go far into the following declarations + ;; in e.g. ObjC mode (see e.g. methods-4.m). + (c-syntactic-re-search-forward "[;,{]" cdd-limit 'move t)) + (backward-char) + (setq cdd-exhausted t) + )) + + (t (c-forward-syntactic-ws cdd-limit))) + + (if cdd-function + (funcall cdd-function cdd-id-start cdd-id-end cdd-next-pos + cdd-not-top cdd-got-func cdd-got-init)) + + ;; If a ',' is found we set cdd-pos to the next declarator and iterate. + (if (and cdd-list (< (point) cdd-limit) (looking-at ",")) + (progn + (when cdd-comma-prop + (c-put-char-property (point) 'c-type cdd-comma-prop)) + (when cdd-list + (forward-char) + (c-forward-syntactic-ws cdd-limit) + (setq cdd-pos (point)))) + (setq cdd-exhausted t))) + + (if (> (point) cdd-pos) + t + (goto-char cdd-pos) + nil))) + +;; Macro used inside `c-forward-decl-or-cast-1'. It ought to be a +;; defsubst or perhaps even a defun, but it contains lots of free +;; variables that refer to things inside `c-forward-decl-or-cast-1'. +(defmacro c-fdoc-shift-type-backward (&optional short) + ;; `c-forward-decl-or-cast-1' can consume an arbitrary length list + ;; of types when parsing a declaration, which means that it + ;; sometimes consumes the identifier in the declaration as a type. + ;; This is used to "backtrack" and make the last type be treated as + ;; an identifier instead. + `(progn + ,(unless short + ;; These identifiers are bound only in the inner let. + '(setq identifier-type at-type + identifier-start type-start + got-parens nil + got-identifier t + got-suffix t + got-suffix-after-parens id-start + paren-depth 0)) + + (if (setq at-type (if (eq backup-at-type 'prefix) + t + backup-at-type)) + (setq type-start backup-type-start + id-start backup-id-start) + (setq type-start start-pos + id-start start-pos)) + + ;; When these flags already are set we've found specifiers that + ;; unconditionally signal these attributes - backtracking doesn't + ;; change that. So keep them set in that case. + (or at-type-decl + (setq at-type-decl backup-at-type-decl)) + (or maybe-typeless + (setq maybe-typeless backup-maybe-typeless)) + + ,(unless short + ;; This identifier is bound only in the inner let. + '(setq start id-start)))) + (defun c-forward-decl-or-cast-1 (preceding-token-end context last-cast-end) ;; Move forward over a declaration or a cast if at the start of one. ;; The point is assumed to be at the start of some token. Nil is @@ -10608,12 +10756,17 @@ ))) (defun c-inside-bracelist-p (containing-sexp paren-state accept-in-paren) - ;; return the buffer position of the beginning of the brace list - ;; statement if we're inside a brace list, otherwise return nil. - ;; CONTAINING-SEXP is the buffer pos of the innermost containing - ;; paren. PAREN-STATE is the remainder of the state of enclosing - ;; braces. ACCEPT-IN-PAREN is non-nil iff we will accept as a brace - ;; list a brace directly enclosed in a parenthesis. + ;; return the buffer position of the beginning of the brace list statement + ;; if CONTAINING-SEXP is inside a brace list, otherwise return nil. + ;; + ;; CONTAINING-SEXP is the buffer pos of the innermost containing paren. NO + ;; IT ISN'T!!! [This function is badly designed, and probably needs + ;; reformulating without its first argument, and the critical position being + ;; at point.] + ;; + ;; PAREN-STATE is the remainder of the state of enclosing braces. + ;; ACCEPT-IN-PAREN is non-nil iff we will accept as a brace list a brace + ;; directly enclosed in a parenthesis. ;; ;; The "brace list" here is recognized solely by its context, not by ;; its contents. @@ -10733,7 +10886,8 @@ (defun c-looking-at-statement-block () ;; Point is at an opening brace. If this is a statement block (i.e. the ;; elements in the block are terminated by semicolons, or the block is - ;; empty, or the block contains a keyword) return t. Otherwise, return nil. + ;; empty, or the block contains a keyword) return non-nil. Otherwise, + ;; return nil. (let ((here (point))) (prog1 (if (c-go-list-forward) @@ -11237,7 +11391,7 @@ (if (and (eq step-type 'same) (/= paren-pos (point))) - (let (inexpr) + (let (inexpr bspec) (cond ((save-excursion (goto-char paren-pos) @@ -11259,6 +11413,13 @@ (c-looking-at-statement-block)) (c-add-syntax 'defun-block-intro nil) (c-add-syntax 'brace-list-intro nil))) + ((save-excursion + (goto-char paren-pos) + (setq bspec (c-looking-at-or-maybe-in-bracelist + containing-sexp containing-sexp)) + (and (consp bspec) + (eq (cdr bspec) 'in-paren))) + (c-add-syntax 'brace-list-intro (car bspec))) (t (c-add-syntax 'defun-block-intro nil)))) (c-add-syntax 'statement-block-intro nil))) @@ -13126,7 +13287,7 @@ nil)))) (if (or (null res) (integerp res) - (and (vectorp res) (= (length res) 1) (integerp (aref res 0)))) + (and (vectorp res) (>= (length res) 1) (integerp (aref res 0)))) res (c-benign-error "Error evaluating offset %S for %s: Got invalid value %S" offset symbol res) @@ -13149,12 +13310,11 @@ (if c-strict-syntax-p (c-benign-error "No offset found for syntactic symbol %s" symbol)) (setq offset 0)) - (if (vectorp offset) - offset - (or (and (numberp offset) offset) - (and (symbolp offset) (symbol-value offset)) - 0)) - )) + (cond + ((or (vectorp offset) (numberp offset)) + offset) + ((and (symbolp offset) (symbol-value offset))) + (t 0)))) (defun c-get-offset (langelem) ;; This is a compatibility wrapper for `c-calc-offset' in case diff -r e38b65ad9145 cc-fonts.el --- a/cc-fonts.el Mon Aug 27 20:23:23 2018 +0000 +++ b/cc-fonts.el Thu Sep 27 19:58:29 2018 +0000 @@ -1029,114 +1029,41 @@ ;;(message "c-font-lock-declarators from %s to %s" (point) limit) (c-fontify-types-and-refs - ((pos (point)) next-pos id-start - decl-res - id-face got-type got-init - c-last-identifier-range - (separator-prop (if types 'c-decl-type-start 'c-decl-id-start))) - - ;; The following `while' fontifies a single declarator id each time round. - ;; It loops only when LIST is non-nil. - (while - (and pos (setq decl-res (c-forward-declarator))) - (setq next-pos (point) - id-start (car decl-res) - id-face (if (and (eq (char-after) ?\() - (or (not (c-major-mode-is 'c++-mode)) - (not not-top) - (car (cddr (cddr decl-res))) ; Id is in - ; parens, etc. - (save-excursion - (forward-char) - (c-forward-syntactic-ws) - (looking-at "[*&]"))) - (not (car (cddr decl-res))) - (or (not (c-major-mode-is 'c++-mode)) - (save-excursion - (let (c-last-identifier-range) - (forward-char) - (c-forward-syntactic-ws) - (catch 'is-function - (while - (progn - (if (eq (char-after) ?\)) - (throw 'is-function t)) - (setq got-type (c-forward-type)) - (cond - ((null got-type) - (throw 'is-function nil)) - ((not (eq got-type 'maybe)) - (throw 'is-function t))) - (c-forward-declarator nil t) - (eq (char-after) ?,)) - (forward-char) - (c-forward-syntactic-ws)) - t))))) - 'font-lock-function-name-face - 'font-lock-variable-name-face) - got-init (and (cadr (cddr decl-res)) ; got-init - (char-after))) - - (if types - ;; Register and fontify the identifier as a type. - (let ((c-promote-possible-types t)) - (goto-char id-start) - (c-forward-type)) - ;; Fontify the last symbol in the identifier if it isn't fontified - ;; already. The check is necessary only in certain cases where this - ;; function is used "sloppily", e.g. in `c-simple-decl-matchers'. - (when (and c-last-identifier-range - (not (get-text-property (car c-last-identifier-range) - 'face))) - (c-put-font-lock-face (car c-last-identifier-range) - (cdr c-last-identifier-range) - id-face))) - - (goto-char next-pos) - (setq pos nil) ; So as to terminate the enclosing `while' form. - (if (and template-class - (eq got-init ?=) ; C++ ""? - (c-forward-token-2 1 nil limit) ; Over "=" - (let ((c-promote-possible-types t)) - (c-forward-type t))) ; Over "Y" - (setq list nil)) ; Shouldn't be needed. We can't have a list, here. - - (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. - (if (c-safe (c-forward-sexp 1) t) ; over the parameter list. - (c-forward-syntactic-ws limit) - (goto-char limit))) ; unbalanced parens - - (got-init ; "=" sign OR opening "(", "[", or "{" - ;; Skip an initializer expression. If we're at a '=' - ;; then accept a brace list directly after it to cope - ;; with array initializers. Otherwise stop at braces - ;; to avoid going past full function and class blocks. - (and (if (and (eq got-init ?=) - (= (c-forward-token-2 1 nil limit) 0) - (looking-at "{")) - (c-safe (c-forward-sexp) t) ; over { .... } - t) - (< (point) limit) - ;; FIXME: Should look for c-decl-end markers here; - ;; we might go far into the following declarations - ;; in e.g. ObjC mode (see e.g. methods-4.m). - (c-syntactic-re-search-forward "[;,{]" limit 'move t) - (backward-char))) - - (t (c-forward-syntactic-ws limit))) - - ;; If a ',' is found we set pos to the next declarator and iterate. - (when (and (< (point) limit) (looking-at ",")) - (c-put-char-property (point) 'c-type separator-prop) - (forward-char) - (c-forward-syntactic-ws limit) - (setq pos (point)))))) ; acts to make the `while' form continue. - nil) + () + (c-do-declarators + limit list not-top + (if types 'c-decl-type-start 'c-decl-id-start) + (lambda (id-start id-end end-pos not-top is-function init-char) + (if types + ;; Register and fontify the identifier as a type. + (let ((c-promote-possible-types t)) + (goto-char id-start) + (c-forward-type)) + ;; The following doesn't work properly (yet, 2018-09-22). + ;; (c-put-font-lock-face id-start id-end + ;; (if is-function + ;; 'font-lock-function-name-face + ;; 'font-lock-variable-name-face)) + (when (and c-last-identifier-range + (not (get-text-property (car c-last-identifier-range) + 'face))) + ;; We use `c-last-identifier-range' rather than `id-start' and + ;; `id-end', since the latter two can be erroneous. E.g. in + ;; "~Foo", `id-start' is at the tilde. This is a bug in + ;; `c-forward-declarator'. + (c-put-font-lock-face (car c-last-identifier-range) + (cdr c-last-identifier-range) + (if is-function + 'font-lock-function-name-face + 'font-lock-variable-name-face)))) + (and template-class + (eq init-char ?=) ; C++ ""? + (progn + (goto-char end-pos) + (c-forward-token-2 1 nil limit) ; Over "=" + (let ((c-promote-possible-types t)) + (c-forward-type t)))))) + nil)) (defun c-get-fontification-context (match-pos not-front-decl &optional toplev) ;; Return a cons (CONTEXT . RESTRICTED-<>-ARGLISTS) for MATCH-POS. diff -r e38b65ad9145 cc-langs.el --- a/cc-langs.el Mon Aug 27 20:23:23 2018 +0000 +++ b/cc-langs.el Thu Sep 27 19:58:29 2018 +0000 @@ -3221,7 +3221,8 @@ "\\|" "\\.\\.\\." "\\|" - "[*(&]" +; "[*(&]" + "[*(&~]" "\\|" (c-lang-const c-type-decl-prefix-key) "\\|" diff -r e38b65ad9145 cc-mode.el --- a/cc-mode.el Mon Aug 27 20:23:23 2018 +0000 +++ b/cc-mode.el Thu Sep 27 19:58:29 2018 +0000 @@ -1781,7 +1781,20 @@ (while ;; Go to a less nested declaration each time round this loop. (and - (c-syntactic-skip-backward "^;{}" bod-lim t) +;;;; OLD STOUGH, 2018-09-22 + ;(c-syntactic-skip-backward "^;{}" bod-lim t) +;;;; NEW STOUGH, 2018-09-22 + (let (pseudo) + (while + (progn + (c-syntactic-skip-backward "^;{}" bod-lim t) + (and (eq (char-before) ?}) + (save-excursion + (backward-char) + (setq pseudo (c-cheap-inside-bracelist-p (c-parse-state)))))) + (goto-char pseudo)) + t) +;;;; END OF NEW STOUGH (> (point) bod-lim) (progn (c-forward-syntactic-ws) (setq bo-decl (point)) diff -r e38b65ad9145 cc-styles.el --- a/cc-styles.el Mon Aug 27 20:23:23 2018 +0000 +++ b/cc-styles.el Thu Sep 27 19:58:29 2018 +0000 @@ -73,7 +73,9 @@ (arglist-close . c-lineup-arglist) (inline-open . 0) (brace-list-open . +) - (brace-list-intro . c-lineup-arglist-intro-after-paren) + (brace-list-intro . (first + c-lineup-2nd-brace-entry-in-arglist + c-lineup-class-decl-init-+ +)) (topmost-intro-cont . (first c-lineup-topmost-intro-cont c-lineup-gnu-DEFUN-intro-cont)))) @@ -100,6 +102,9 @@ (label . 0) (statement-cont . +) (inline-open . 0) + (brace-list-intro . (first + c-lineup-2nd-brace-entry-in-arglist + c-lineup-class-decl-init-+ +)) (inexpr-class . 0)))) ("stroustrup" @@ -109,6 +114,9 @@ (substatement-open . 0) (substatement-label . 0) (label . 0) + (brace-list-intro . (first + c-lineup-2nd-brace-entry-in-arglist + c-lineup-class-decl-init-+ +)) (statement-cont . +)))) ("whitesmith" @@ -199,6 +207,9 @@ (c-offsets-alist . ((substatement-open . 0) (inextern-lang . 0) (arglist-intro . +) + (brace-list-intro . (first + c-lineup-2nd-brace-entry-in-arglist + c-lineup-class-decl-init-+ +)) (knr-argdecl-intro . +))) (c-hanging-braces-alist . ((brace-list-open) (brace-list-intro) @@ -224,6 +235,9 @@ (statement-cont . +) (arglist-intro . c-lineup-arglist-intro-after-paren) (arglist-close . c-lineup-arglist) + (brace-list-intro . (first + c-lineup-2nd-brace-entry-in-arglist + c-lineup-class-decl-init-+ +)) (access-label . 0) (inher-cont . c-lineup-java-inher) (func-decl-cont . c-lineup-java-throws)))) diff -r e38b65ad9145 cc-vars.el --- a/cc-vars.el Mon Aug 27 20:23:23 2018 +0000 +++ b/cc-vars.el Thu Sep 27 19:58:29 2018 +0000 @@ -1117,7 +1117,7 @@ ;; Anchor pos: At the brace list decl start(*). (brace-list-intro . +) ;; Anchor pos: At the brace list decl start(*). - (brace-list-entry . c-lineup-under-anchor) + (brace-list-entry . 0) ;; Anchor pos: At the first non-ws char after the open paren if ;; the first token is on the same line, otherwise boi at that ;; token. --82I3+IH0IqGh5yIs-- From debbugs-submit-bounces@debbugs.gnu.org Tue Mar 12 15:17:09 2019 Received: (at 28050-done) by debbugs.gnu.org; 12 Mar 2019 19:17:09 +0000 Received: from localhost ([127.0.0.1]:40601 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1h3mte-00006r-SV for submit@debbugs.gnu.org; Tue, 12 Mar 2019 15:17:09 -0400 Received: from colin.muc.de ([193.149.48.1]:59422 helo=mail.muc.de) by debbugs.gnu.org with smtp (Exim 4.84_2) (envelope-from ) id 1h3mtd-00006i-6Z for 28050-done@debbugs.gnu.org; Tue, 12 Mar 2019 15:17:06 -0400 Received: (qmail 12134 invoked by uid 3782); 12 Mar 2019 19:17:03 -0000 Received: from acm.muc.de (p4FE15C43.dip0.t-ipconnect.de [79.225.92.67]) by colin.muc.de (tmda-ofmipd) with ESMTP; Tue, 12 Mar 2019 20:17:01 +0100 Received: (qmail 20408 invoked by uid 1000); 12 Mar 2019 19:16:54 -0000 Date: Tue, 12 Mar 2019 19:16:54 +0000 To: Mohammed Sadiq Subject: Re: bug#28050: CC Mode 5.33 (C/*l); indentation of array and enum in GNU style isn't right Message-ID: <20190312191654.GA20392@ACM> References: <871soiggxp.fsf@rose> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <871soiggxp.fsf@rose> User-Agent: Mutt/1.10.1 (2018-07-13) X-Delivery-Agent: TMDA/1.1.12 (Macallan) From: Alan Mackenzie X-Primary-Address: acm@muc.de X-Spam-Score: -0.0 (/) X-Debbugs-Envelope-To: 28050-done Cc: 28050-done@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) Hello, Mohammed and Emacs. I've just committed a fix to this bug to master. On Fri, Aug 11, 2017 at 22:50:02 +0530, Mohammed Sadiq wrote: > For the following code, the indentation of the code isn't right for GNU > style (C-x h TAB after writing the code): > /* Output after default (auto)indentation in GNU Emacs (TAB is used sometimes) */ > char *words[] = { > "good", > "better", > "best" > }; > The GNU style is (as done by the program GNU indent): > /* They should be indented with 2 spaces (and not TABs) > char *words[] = { > "good", > "better", > "best" > }; > Tabs are also add for indentation when defining enums: > typedef enum { > GOOD, > BETTER, > BEST > } test; > The following might be better (2 spaces, and no TABs): > typedef enum { > GOOD, > BETTER, > BEST > } test; > Emacs : GNU Emacs 26.0.50 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.22.11) > of 2017-08-11 > Package: CC Mode 5.33 (C/*l) > Buffer Style: gnu > c-emacs-features: (pps-extended-state col-0-paren posix-char-classes gen-string-delim gen-comment-delim syntax-properties 1-bit) -- Alan Mackenzie (Nuremberg, Germany). From unknown Fri Jun 20 07:13:00 2025 Received: (at fakecontrol) by fakecontrolmessage; To: internal_control@debbugs.gnu.org From: Debbugs Internal Request Subject: Internal Control Message-Id: bug archived. Date: Wed, 10 Apr 2019 11:24:05 +0000 User-Agent: Fakemail v42.6.9 # This is a fake control message. # # The action: # bug archived. thanks # This fakemail brought to you by your local debbugs # administrator