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.
Message #10 received at submit <at> emacsbugs.donarmstrong.com (full text, mbox):
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: Re: 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).
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.