GNU bug report logs - #5209
23.1.90; CC Mode version 5.31.8 does not indent properly when writing new C files

Previous Next

Packages: cc-mode, emacs;

Reported by: Steve Revilak <steve <at> srevilak.net>

Date: Sun, 13 Dec 2009 16:30:03 UTC

Severity: normal

Done: Steve Revilak <steve <at> srevilak.net>

Bug is archived. No further changes may be made.

Full log


View this message in rfc822 format

From: Alan Mackenzie <acm <at> muc.de>
To: Steve Revilak <steve <at> srevilak.net>, 5209 <at> debbugs.gnu.org
Cc: emacs-pretest-bug <at> gnu.org
Subject: bug#5209: 23.1.90; CC Mode version 5.31.8 does not indent properly when writing new C files
Date: Sun, 13 Dec 2009 20:33:11 +0000
Hi, Steve,

On Sun, Dec 13, 2009 at 11:22:10AM -0500, Steve Revilak wrote:

> STEPS TO REPRODUCE
> ------------------

> (1) Start emacs with the command line "emacs -nw -Q foo.c".

>     foo.c should be a new file, which does not exist prior to starting
>     emacs.

> (2) Type "#include <stdio.h>" and RETURN

> (3) Type RETURN to leave a blank line

> (4) type "static void add_one(int * x) {" and RETURN

> (5) type "*x += 1;" and RETURN

> (6) type "}" and RETURN (to close the function definition)

> NOTE: the statement written in step (5) is left-aligned to column
> zero.  The statement should be indented.

> (7) Place point in column zero of the line "*x += 1;".  Press TAB.

>     Before pressing TAB, "*x += 1;" is aligned to column zero.  After
>     pressing TAB, "*x += 1;" is still aligned to column zero.  TAB did
>     not indent the statement.

> (8) Type "C-x h TAB" (i.e., to select and re-indent the entire
>     buffer).

>     The minibuffer displays "Indenting region... done".  However, the
>     statement "*x += 1;" is still aligned to column zero.

> After step 8, buffer "foo.c" looks like this:
> ---------------------------------
> #include <stdio.h>

> static void add_one(int * x) {
> *x += 1;
> }
> ---------------------------------
> NOTE: the fourth line is not indented (but it should be).

First thing, thanks for such a simple and clear bug report.

There is a bug in `c-parse-state', one of the low-level functions in CC
mode, which generates and changes a cache of brace and paren positions.

Would you apply the following patch, and test it, please.  If anything is
still wrong, please let me know again.


*** cc-engine.orig.el	2009-12-13 19:43:27.268817800 +0000
--- cc-engine.el	2009-12-13 20:06:47.819901672 +0000
***************
*** 2231,2236 ****
--- 2231,2249 ----
  
  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  ;; Defuns which analyse the buffer, yet don't change `c-state-cache'.
+ (defun c-p1-not-in-p0-macro (p0 p1)
+   ;; Is P0 in a CPP construct and p1 not in it?
+   (save-restriction
+     (widen)
+     (save-excursion
+       (let ((p0-macro-begin
+ 	     (progn (goto-char p0) (and (c-beginning-of-macro) (point)))))
+ 	(and p0-macro-begin
+ 	     (not
+ 	      (eq p0-macro-begin
+ 		  (progn (goto-char p1) (and (c-beginning-of-macro) (point)))))
+ 	     )))))
+ 
  (defun c-get-fallback-scan-pos (here)
    ;; Return a start position for building `c-state-cache' from
    ;; scratch.  This will be at the top level, 2 defuns back.
***************
*** 2587,2593 ****
    ;; o - SCAN-BACK-POS, if not nil, indicates there may be a brace pair
    ;;   preceding POS which needs to be recorded in `c-state-cache'.  It is a
    ;;   position to scan backwards from.
!   ;; o - PPS-STATE is the parse-partial-sexp state at PPS-POINT.
    (save-restriction
      (narrow-to-region 1 (point-max))
      (save-excursion
--- 2600,2607 ----
    ;; o - SCAN-BACK-POS, if not nil, indicates there may be a brace pair
    ;;   preceding POS which needs to be recorded in `c-state-cache'.  It is a
    ;;   position to scan backwards from.
!   ;; o - PPS-STATE is the parse-partial-sexp state at PPS-POINT or nil if we
!   ;;   don't scan past PPS-POINT.
    (save-restriction
      (narrow-to-region 1 (point-max))
      (save-excursion
***************
*** 2624,2630 ****
  			   (< (point-max) c-state-old-cpp-end)))
  		  (point-max)
  		(min (point-max) c-state-old-cpp-beg)))
! 	(while (and c-state-cache (> (c-state-cache-top-lparen) upper-lim))
  	  (setq c-state-cache (cdr c-state-cache)))
  	;; If `upper-lim' is inside the last recorded brace pair, remove its
  	;; RBrace and indicate we'll need to search backwards for a previous
--- 2638,2645 ----
  			   (< (point-max) c-state-old-cpp-end)))
  		  (point-max)
  		(min (point-max) c-state-old-cpp-beg)))
! 	(while (and c-state-cache
! 		    (>= (c-state-cache-top-lparen) upper-lim))
  	  (setq c-state-cache (cdr c-state-cache)))
  	;; If `upper-lim' is inside the last recorded brace pair, remove its
  	;; RBrace and indicate we'll need to search backwards for a previous
***************
*** 2641,2647 ****
  	;; (car c-state-cache).  There can be no open parens/braces/brackets
  	;; between `good-pos'/`good-pos-actual-macro-start' and (point-max),
  	;; due to the interface spec to this function.
! 	(setq pos (if good-pos-actual-macro-end
  		      (1+ good-pos-actual-macro-end) ; get outside the macro as
  					; marked by a `category' text property.
  		    good-pos))
--- 2656,2663 ----
  	;; (car c-state-cache).  There can be no open parens/braces/brackets
  	;; between `good-pos'/`good-pos-actual-macro-start' and (point-max),
  	;; due to the interface spec to this function.
! 	(setq pos (if (and good-pos-actual-macro-start
! 			   (not (eq good-pos-actual-macro-start in-macro-start)))
  		      (1+ good-pos-actual-macro-end) ; get outside the macro as
  					; marked by a `category' text property.
  		    good-pos))
***************
*** 2701,2707 ****
  	  (setq c-state-cache (cons (cons pair-beg pos)
  				    c-state-cache)))
  
! 	(list pos scan-back-pos pps-state)))))
  
  (defun c-remove-stale-state-cache-backwards (here cache-pos)
    ;; Strip stale elements of `c-state-cache' by moving backwards through the
--- 2717,2723 ----
  	  (setq c-state-cache (cons (cons pair-beg pos)
  				    c-state-cache)))
  
! 	(list pos scan-back-pos pps-point-state)))))
  
  (defun c-remove-stale-state-cache-backwards (here cache-pos)
    ;; Strip stale elements of `c-state-cache' by moving backwards through the
***************
*** 2769,2777 ****
  	  (list (1+ pos) pos t)) ; return value.  We've just converted a brace
  			         ; pair entry into a { entry, so the caller
  			         ; needs to search for a brace pair before the
! 			         ; {.
  
!       ;; ;; `here' might be inside a literal.  Check for this.
        (setq lit (c-state-literal-at here)
  	    here-lit-start (or (car lit) here)
  	    here-lit-end (or (cdr lit) here))
--- 2785,2793 ----
  	  (list (1+ pos) pos t)) ; return value.  We've just converted a brace
  			         ; pair entry into a { entry, so the caller
  			         ; needs to search for a brace pair before the
! 			         ; {, hence the `pos' in second last place.
  
!       ;; `here' might be inside a literal.  Check for this.
        (setq lit (c-state-literal-at here)
  	    here-lit-start (or (car lit) here)
  	    here-lit-end (or (cdr lit) here))
***************
*** 2801,2812 ****
  		    (setq pos pa))))	; might signal
  	(if (setq ren (c-safe-scan-lists pos -1 -1 too-far-back))
  	    ;; CASE 3: After a }/)/] before `here''s BOL.
! 	    (list (1+ ren) (and dropped-cons pos) nil) ; Return value
  
  	  ;; CASE 4; Best of a bad job: BOL before `here-bol', or beginning of
  	  ;; literal containing it.
  	  (setq good-pos (c-state-lit-beg (c-point 'bopl here-bol)))
! 	  (list good-pos (and dropped-cons good-pos) nil))))))
  
  
  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
--- 2817,2836 ----
  		    (setq pos pa))))	; might signal
  	(if (setq ren (c-safe-scan-lists pos -1 -1 too-far-back))
  	    ;; CASE 3: After a }/)/] before `here''s BOL.
! 	    (list (1+ ren)
! 		  (or (and (c-p1-not-in-p0-macro here c-state-cache-good-pos)
! 			   here)
! 		      (and dropped-cons pos))
! 		  nil) ; Return value
  
  	  ;; CASE 4; Best of a bad job: BOL before `here-bol', or beginning of
  	  ;; literal containing it.
  	  (setq good-pos (c-state-lit-beg (c-point 'bopl here-bol)))
! 	  (list good-pos
! 		(or (and (c-p1-not-in-p0-macro here c-state-cache-good-pos)
! 			 here)
! 		    (and dropped-cons good-pos))
! 		nil))))))
  
  
  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


-- 
Alan Mackenzie (Nuremberg, Germany).



This bug report was last modified 15 years and 143 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.