X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/bdf36482bbea390390ae7ab1461b14b807c4fb1f..8d9cc0b7ea1893059df8788129998e9a71ec07f3:/lisp/progmodes/cc-cmds.el diff --git a/lisp/progmodes/cc-cmds.el b/lisp/progmodes/cc-cmds.el index 8b2f5e57f8..48fa7d99f5 100644 --- a/lisp/progmodes/cc-cmds.el +++ b/lisp/progmodes/cc-cmds.el @@ -1,9 +1,11 @@ ;;; cc-cmds.el --- user level commands for CC Mode -;; Copyright (C) 1985, 1987, 1992-2003, 2004, 2005, 2006 Free Software -;; Foundation, Inc. +;; Copyright (C) 1985, 1987, 1992, 1993, 1994, 1995, 1996, 1997, 1998, +;; 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 +;; Free Software Foundation, Inc. -;; Authors: 1998- Martin Stjernholm +;; Authors: 2003- Alan Mackenzie +;; 1998- Martin Stjernholm ;; 1992-1999 Barry A. Warsaw ;; 1987 Dave Detlefs and Stewart Clamen ;; 1985 Richard M. Stallman @@ -16,7 +18,7 @@ ;; GNU Emacs is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) +;; the Free Software Foundation; either version 3, or (at your option) ;; any later version. ;; GNU Emacs is distributed in the hope that it will be useful, @@ -52,6 +54,7 @@ (cc-bytecomp-defun c-forward-subword) (cc-bytecomp-defun c-backward-subword) +;; Indentation / Display syntax functions (defvar c-fix-backslashes t) (defun c-indent-line (&optional syntax quiet ignore-point-pos) @@ -75,8 +78,10 @@ indentation change \(in columns)." (save-excursion (beginning-of-line) (looking-at (if line-cont-backslash - "\\(\\s *\\)\\\\$" - "\\(\\s *\\)$"))) + ;; Don't use "\\s " - ^L doesn't count as WS + ;; here + "\\([ \t]*\\)\\\\$" + "\\([ \t]*\\)$"))) (<= (point) (match-end 1))) ;; Delete all whitespace after point if there's only whitespace ;; on the line, so that any code that does back-to-indentation @@ -251,6 +256,7 @@ With universal argument, inserts the analysis as a comment on that line." (forward-line))))) +;; Minor mode functions. (defun c-update-modeline () (let ((fmt (format "/%s%s%s%s" (if c-electric-flag "l" "") @@ -271,7 +277,7 @@ With universal argument, inserts the analysis as a comment on that line." ;; fmt)) (setq mode-name (if (> (length fmt) 1) - (concat bare-mode-name fmt) + (concat bare-mode-name fmt) bare-mode-name)) (force-mode-line-update))) @@ -536,7 +542,7 @@ inside a literal or a macro, nothing special happens." ;; shut this up too (c-echo-syntactic-information-p nil) symb-newlines) ; e.g. (substatement-open . (after)) - + (setq symb-newlines ;; Do not try to insert newlines around a special ;; (Pike-style) brace list. @@ -842,13 +848,17 @@ is inhibited." (eq literal 'c) (memq 'comment-close-slash c-cleanup-list) (eq last-command-char ?/) + (looking-at (concat "[ \t]*\\(" + (regexp-quote comment-end) "\\)?$")) ; (eq c-block-comment-ender "*/") ; C-style comments ALWAYS end in */ (save-excursion - (back-to-indentation) - (looking-at (concat c-current-comment-prefix "[ \t]*$")))) - (end-of-line) - (delete-horizontal-space) - (or (eq (char-before) ?*) (insert-char ?* 1))) ; Do I need a t (retain sticky properties) here? + (save-restriction + (narrow-to-region (point-min) (point)) + (back-to-indentation) + (looking-at (concat c-current-comment-prefix "[ \t]*$"))))) + (delete-region (progn (forward-line 0) (point)) + (progn (end-of-line) (point))) + (insert-char ?* 1)) ; the / comes later. ; Do I need a t (retain sticky properties) here? (setq indentp (and (not arg) c-syntactic-indentation @@ -1252,7 +1262,11 @@ newline cleanups are done if appropriate; see the variable `c-cleanup-list'." (backward-char) (skip-chars-backward " \t") (setq beg (point)) - (c-save-buffer-state () (c-on-identifier)))) + (and (c-save-buffer-state () (c-on-identifier)) + ;; Don't add a space into #define FOO().... + (not (and (c-beginning-of-macro) + (c-forward-over-cpp-define-id) + (eq (point) beg)))))) (save-excursion (delete-region beg end) (goto-char beg) @@ -1307,6 +1321,7 @@ keyword on the line, the keyword is not inserted inside a literal, and (delete-char -2))))) +;; "nomenclature" functions + c-scope-operator. (defun c-forward-into-nomenclature (&optional arg) "Compatibility alias for `c-forward-subword'." (interactive "p") @@ -1327,6 +1342,172 @@ No indentation or other \"electric\" behavior is performed." (interactive "*") (insert-and-inherit "::")) + +;; Movement (etc.) by defuns. +(defun c-in-function-trailer-p (&optional lim) + ;; Return non-nil if point is between the closing brace and the semicolon of + ;; a brace construct which needs a semicolon, e.g. within the "variables" + ;; portion of a declaration like "struct foo {...} bar ;". + ;; + ;; Return the position of the main declaration. Otherwise, return nil. + ;; Point is assumed to be at the top level and outside of any macro or + ;; literal. + ;; + ;; If LIM is non-nil, it is the bound on a the backward search for the + ;; beginning of the declaration. + ;; + ;; This function might do hidden buffer changes. + (and c-opt-block-decls-with-vars-key + (save-excursion + (c-syntactic-skip-backward "^;}" lim) + (let ((eo-block (point)) + bod) + (and (eq (char-before) ?\}) + (eq (car (c-beginning-of-decl-1 lim)) 'previous) + (setq bod (point)) + ;; Look for struct or union or ... If we find one, it might + ;; be the return type of a function, or the like. Exclude + ;; this case. + (c-syntactic-re-search-forward + (concat "[;=\(\[{]\\|\\(" + c-opt-block-decls-with-vars-key + "\\)") + eo-block t t t) + (match-beginning 1) ; Is there a "struct" etc., somewhere? + (not (eq (char-before) ?_)) + (c-syntactic-re-search-forward "[;=\(\[{]" eo-block t t t) + (eq (char-before) ?\{) + bod))))) + +(defun c-where-wrt-brace-construct () + ;; Determine where we are with respect to functions (or other brace + ;; constructs, included in the term "function" in the rest of this comment). + ;; Point is assumed to be outside any macro or literal. + ;; This is used by c-\(begining\|end\)-of-defun. + ;; + ;; Return one of these symbols: + ;; at-header : we're at the start of a function's header. + ;; in-header : we're inside a function's header, this extending right + ;; up to the brace. This bit includes any k&r declarations. + ;; in-block : we're inside a function's brace block. + ;; in-trailer : we're in the area between the "}" and ";" of something + ;; like "struct foo {...} bar, baz;". + ;; at-function-end : we're just after the closing brace (or semicolon) that + ;; terminates the function. + ;; outwith-function: we're not at or in any function. Being inside a + ;; non-brace construct also counts as 'outwith-function'. + ;; + ;; This function might do hidden buffer changes. + (save-excursion + (let* (kluge-start + decl-result brace-decl-p + (start (point)) + (paren-state (c-parse-state)) + (least-enclosing (c-least-enclosing-brace paren-state))) + + (cond + ((and least-enclosing + (eq (char-after least-enclosing) ?\{)) + 'in-block) + ((c-in-function-trailer-p) + 'in-trailer) + ((and (not least-enclosing) + (consp paren-state) + (consp (car paren-state)) + (eq start (cdar paren-state))) + 'at-function-end) + (t + ;; Find the start of the current declaration. NOTE: If we're in the + ;; variables after a "struct/eval" type block, we don't get to the + ;; real declaration here - we detect and correct for this later. + + ;;If we're in the parameters' parens, move back out of them. + (if least-enclosing (goto-char least-enclosing)) + ;; Kluge so that c-beginning-of-decl-1 won't go back if we're already + ;; at a declaration. + (if (or (and (eolp) (not (eobp))) ; EOL is matched by "\\s>" + (not (looking-at +"\\([;#]\\|\\'\\|\\s(\\|\\s)\\|\\s\"\\|\\s\\\\|\\s$\\|\\s<\\|\\s>\\|\\s!\\)"))) + (forward-char)) + (setq kluge-start (point)) + (setq decl-result + (car (c-beginning-of-decl-1 + ;; NOTE: If we're in a K&R region, this might be the start + ;; of a parameter declaration, not the actual function. + (and least-enclosing ; LIMIT for c-b-of-decl-1 + (c-safe-position least-enclosing paren-state))))) + + ;; Has the declaration we've gone back to got braces? + (setq brace-decl-p + (save-excursion + (and (c-syntactic-re-search-forward "[;{]" nil t t) + (or (eq (char-before) ?\{) + (and c-recognize-knr-p + ;; Might have stopped on the + ;; ';' in a K&R argdecl. In + ;; that case the declaration + ;; should contain a block. + (c-in-knr-argdecl)))))) + + (cond + ((= (point) kluge-start) ; might be BOB or unbalanced parens. + 'outwith-function) + ((eq decl-result 'same) + (if brace-decl-p + (if (eq (point) start) + 'at-header + 'in-header) + 'outwith-function)) + ((eq decl-result 'previous) + (if (and (not brace-decl-p) + (c-in-function-trailer-p)) + 'at-function-end + 'outwith-function)) + (t (error + "c-where-wrt-brace-construct: c-beginning-of-decl-1 returned %s" + decl-result)))))))) + +(defun c-backward-to-nth-BOF-{ (n where) + ;; Skip to the opening brace of the Nth function before point. If + ;; point is inside a function, this counts as the first. Point must be + ;; outside any comment/string or macro. + ;; + ;; N must be strictly positive. + ;; WHERE describes the position of point, one of the symbols `at-header', + ;; `in-header', `in-block', `in-trailer', `at-function-end', + ;; `outwith-function' as returned by c-where-wrt-brace-construct. + ;; + ;; If we run out of functions, leave point at BOB. Return zero on success, + ;; otherwise the number of {s still to go. + ;; + ;; This function may do hidden buffer changes + (cond + ;; What we do to go back the first defun depends on where we start. + ((bobp)) + ((eq where 'in-block) + (goto-char (c-least-enclosing-brace (c-parse-state))) + (setq n (1- n))) + ((eq where 'in-header) + (c-syntactic-re-search-forward "{") + (backward-char) + (setq n (1- n))) + ((memq where '(at-header outwith-function at-function-end in-trailer)) + (c-syntactic-skip-backward "^}") + (when (eq (char-before) ?\}) + (backward-sexp) + (setq n (1- n)))) + (t (error "Unknown `where' %s in c-backward-to-nth-EOF-{" where))) + + ;; Each time round the loop, go back to a "{" at the outermost level. + (while (and (> n 0) (not (bobp))) + (c-parse-state) ; This call speeds up the following one + ; by a factor of ~6. Hmmm. 2006/4/5. + (c-syntactic-skip-backward "^}") + (when (eq (char-before) ?\}) + (backward-sexp) + (setq n (1- n)))) + n) + (defun c-beginning-of-defun (&optional arg) "Move backward to the beginning of a defun. Every top level declaration that contains a brace paren block is @@ -1343,88 +1524,97 @@ defun." (interactive "p") (or arg (setq arg 1)) - (if (< arg 0) - (when (c-end-of-defun (- arg)) - (c-save-buffer-state nil (c-forward-syntactic-ws)) - t) - - (c-save-buffer-state (paren-state lim pos) - (catch 'exit - (while (> arg 0) - ;; Note: Partial code duplication in `c-end-of-defun' and - ;; `c-declaration-limits'. - - (setq paren-state (c-parse-state)) - (unless (c-safe - (goto-char (c-least-enclosing-brace paren-state)) - ;; If we moved to the outermost enclosing paren - ;; then we can use c-safe-position to set the - ;; limit. Can't do that otherwise since the - ;; earlier paren pair on paren-state might very - ;; well be part of the declaration we should go - ;; to. - (setq lim (c-safe-position (point) paren-state)) - t) - ;; At top level. Make sure we aren't inside a literal. - (setq pos (c-literal-limits - (c-safe-position (point) paren-state))) - (if pos (goto-char (car pos)))) - - (while (let ((start (point))) - (c-beginning-of-decl-1 lim) - (if (= (point) start) - ;; Didn't move. Might be due to bob or unbalanced - ;; parens. Try to continue if it's the latter. - (unless (c-safe (goto-char - (c-down-list-backward (point)))) - ;; Didn't work, so it's bob then. - (goto-char (point-min)) - (throw 'exit nil))) + (c-save-buffer-state + (beginning-of-defun-function end-of-defun-function + (start (point)) + where paren-state pos) - (save-excursion - ;; Check if the declaration contains a brace - ;; block. If not, we try another one. - (setq pos (point)) - (not (and (c-syntactic-re-search-forward "[;{]" nil t t) - (or (eq (char-before) ?{) - (and c-recognize-knr-p - ;; Might have stopped on the - ;; ';' in a K&R argdecl. In - ;; that case the declaration - ;; should contain a block. - (c-in-knr-argdecl pos))))))) - (setq lim nil)) - - ;; Check if `c-beginning-of-decl-1' put us after the block - ;; in a declaration that doesn't end there. We're searching - ;; back and forth over the block here, which can be - ;; expensive. - (setq pos (point)) - (if (and c-opt-block-decls-with-vars-key - (progn - (c-backward-syntactic-ws) - (eq (char-before) ?})) - (eq (car (c-beginning-of-decl-1)) - 'previous) - (save-excursion - (c-end-of-decl-1) - (> (point) pos))) - nil - (goto-char pos)) - - (setq pos (point)) - ;; Try to be line oriented; position point at the closest - ;; preceding boi that isn't inside a comment, but if we hit - ;; the previous declaration then we use the current point - ;; instead. - (while (and (/= (point) (c-point 'boi)) - (c-backward-single-comment))) - (if (/= (point) (c-point 'boi)) - (goto-char pos)) - - (setq arg (1- arg))))) - (c-keep-region-active) - (= arg 0))) + ;; Move back out of any macro/comment/string we happen to be in. + (c-beginning-of-macro) + (setq pos (c-literal-limits)) + (if pos (goto-char (car pos))) + + (setq where (c-where-wrt-brace-construct)) + + (if (< arg 0) + ;; Move forward to the closing brace of a function. + (progn + (if (memq where '(at-function-end outwith-function)) + (setq arg (1+ arg))) + (if (< arg 0) + (setq arg (c-forward-to-nth-EOF-} (- arg) where))) + ;; Move forward to the next opening brace.... + (when (and (= arg 0) + (c-syntactic-re-search-forward "{" nil 'eob)) + (backward-char) + ;; ... and backward to the function header. + (c-beginning-of-decl-1) + t)) + + ;; Move backward to the opening brace of a function. + (when (and (> arg 0) + (eq (setq arg (c-backward-to-nth-BOF-{ arg where)) 0)) + + ;; Go backward to this function's header. + (c-beginning-of-decl-1) + + (setq pos (point)) + ;; We're now there, modulo comments and whitespace. + ;; Try to be line oriented; position point at the closest + ;; preceding boi that isn't inside a comment, but if we hit + ;; the previous declaration then we use the current point + ;; instead. + (while (and (/= (point) (c-point 'boi)) + (c-backward-single-comment))) + (if (/= (point) (c-point 'boi)) + (goto-char pos))) + + (c-keep-region-active) + (= arg 0)))) + +(defun c-forward-to-nth-EOF-} (n where) + ;; Skip to the closing brace of the Nth function after point. If + ;; point is inside a function, this counts as the first. Point must be + ;; outside any comment/string or macro. + ;; + ;; N must be strictly positive. + ;; WHERE describes the position of point, one of the symbols `at-header', + ;; `in-header', `in-block', `in-trailer', `at-function-end', + ;; `outwith-function' as returned by c-where-wrt-brace-construct. + ;; + ;; If we run out of functions, leave point at EOB. Return zero on success, + ;; otherwise the number of }s still to go. + ;; + ;; This function may do hidden buffer changes. + + (cond + ;; What we do to go forward over the first defun depends on where we + ;; start. We go to the closing brace of that defun, even when we go + ;; backwards to it (in a "struct foo {...} bar ;"). + ((eobp)) + ((eq where 'in-block) + (goto-char (c-least-enclosing-brace (c-parse-state))) + (forward-sexp) + (setq n (1- n))) + ((eq where 'in-trailer) + (c-syntactic-skip-backward "^}") + (setq n (1- n))) + ((memq where '(at-function-end outwith-function at-header in-header)) + (when (c-syntactic-re-search-forward "{" nil 'eob) + (backward-char) + (forward-sexp) + (setq n (1- n)))) + (t (error "c-forward-to-nth-EOF-}: `where' is %s" where))) + + ;; Each time round the loop, go forward to a "}" at the outermost level. + (while (and (> n 0) (not (eobp))) + ;(c-parse-state) ; This call speeds up the following one by a factor + ; of ~6. Hmmm. 2006/4/5. + (when (c-syntactic-re-search-forward "{" nil 'eob) + (backward-char) + (forward-sexp)) + (setq n (1- n))) + n) (defun c-end-of-defun (&optional arg) "Move forward to the end of a top level declaration. @@ -1434,82 +1624,54 @@ beginning or end of buffer. An end of a defun occurs right after the close-parenthesis that matches the open-parenthesis that starts a defun; see `beginning-of-defun'." - (interactive "p") (or arg (setq arg 1)) - (if (< arg 0) - (when (c-beginning-of-defun (- arg)) - (c-save-buffer-state nil (c-backward-syntactic-ws)) - t) - - (c-save-buffer-state (paren-state lim pos) - (catch 'exit - (while (> arg 0) - ;; Note: Partial code duplication in `c-beginning-of-defun' - ;; and `c-declaration-limits'. - - (setq paren-state (c-parse-state)) - (unless (c-safe - (goto-char (c-least-enclosing-brace paren-state)) - ;; If we moved to the outermost enclosing paren - ;; then we can use c-safe-position to set the - ;; limit. Can't do that otherwise since the - ;; earlier paren pair on paren-state might very - ;; well be part of the declaration we should go - ;; to. - (setq lim (c-safe-position (point) paren-state)) - t) - ;; At top level. Make sure we aren't inside a literal. - (setq pos (car-safe (c-literal-limits - (c-safe-position (point) paren-state)))) - (if pos (goto-char pos))) - - ;; Have to move to the start first so that `c-end-of-decl-1' - ;; has the correct start position. - (setq pos (point)) - (when (memq (car (c-beginning-of-decl-1 lim)) - '(previous macro)) - ;; We moved back over the previous defun or a macro. Move - ;; to the next token; it's the start of the next - ;; declaration. We can also be directly after the block - ;; in a `c-opt-block-decls-with-vars-key' declaration, but - ;; then we won't move significantly far here. - (goto-char pos) - (c-forward-token-2 0)) - - (while (let ((start (point))) - (c-end-of-decl-1) - (if (= (point) start) - ;; Didn't move. Might be due to eob or unbalanced - ;; parens. Try to continue if it's the latter. - (if (c-safe (goto-char (c-up-list-forward (point)))) - t - ;; Didn't work, so it's eob then. - (goto-char (point-max)) - (throw 'exit nil)) - - (save-excursion - ;; Check if the declaration contains a brace - ;; block. If not, we try another one. - (setq pos (point)) - (goto-char start) - (not (c-syntactic-re-search-forward "{" pos t t)))))) - - (setq pos (point)) - ;; Try to be line oriented; position point after the next - ;; newline that isn't inside a comment, but if we hit the - ;; next declaration then we use the current point instead. - (while (and (not (bolp)) - (not (looking-at "\\s *$")) - (c-forward-single-comment))) - (cond ((bolp)) - ((looking-at "\\s *$") - (forward-line 1)) - (t - (goto-char pos))) + (c-save-buffer-state + (beginning-of-defun-function end-of-defun-function + (start (point)) + where paren-state pos) + + ;; Move back out of any macro/comment/string we happen to be in. + (c-beginning-of-macro) + (setq pos (c-literal-limits)) + (if pos (goto-char (car pos))) + + (setq where (c-where-wrt-brace-construct)) + + (if (< arg 0) + ;; Move backwards to the } of a function + (progn + (if (memq where '(at-header outwith-function)) + (setq arg (1+ arg))) + (if (< arg 0) + (setq arg (c-backward-to-nth-BOF-{ (- arg) where))) + (if (= arg 0) + (c-syntactic-skip-backward "^}"))) + + ;; Move forward to the } of a function + (if (> arg 0) + (setq arg (c-forward-to-nth-EOF-} arg where)))) + + ;; Do we need to move forward from the brace to the semicolon? + (when (eq arg 0) + (if (c-in-function-trailer-p) ; after "}" of struct/enum, etc. + (c-syntactic-re-search-forward ";")) + + (setq pos (point)) + ;; We're there now, modulo comments and whitespace. + ;; Try to be line oriented; position point after the next + ;; newline that isn't inside a comment, but if we hit the + ;; next declaration then we use the current point instead. + (while (and (not (bolp)) + (not (looking-at "\\s *$")) + (c-forward-single-comment))) + (cond ((bolp)) + ((looking-at "\\s *$") + (forward-line 1)) + (t + (goto-char pos)))) - (setq arg (1- arg))))) (c-keep-region-active) (= arg 0))) @@ -1645,6 +1807,7 @@ function does not require the declaration to contain a brace block." (push-mark (cdr decl-limits) nil t)))) +;; Movement by statements. (defun c-in-comment-line-prefix-p () ;; Point is within a comment. Is it also within a comment-prefix? ;; Space at BOL which precedes a comment-prefix counts as part of it. @@ -1661,12 +1824,12 @@ function does not require the declaration to contain a brace block." (defun c-narrow-to-comment-innards (range) ;; Narrow to the "inside" of the comment (block) defined by range, as ;; follows: - ;; + ;; ;; A c-style block comment has its opening "/*" and its closing "*/" (if ;; present) removed. A c++-style line comment retains its opening "//" but ;; has any final NL removed. If POINT is currently outwith these innards, ;; move it to the appropriate boundary. - ;; + ;; ;; This narrowing simplifies the sentence movement functions, since it ;; eliminates awkward things at the boundaries of the comment (block). ;; @@ -1694,7 +1857,7 @@ function does not require the declaration to contain a brace block." ;; of the comment and return T. ;; ;; The BOS is either text which follows a regexp match of sentence-end, - ;; or text which is a beginning of "paragraph". + ;; or text which is a beginning of "paragraph". ;; Comment-prefixes are treated like WS when calculating BOSes or BOPs. ;; ;; This code was adapted from GNU Emacs's forward-sentence in paragraphs.el. @@ -2104,7 +2267,7 @@ function does not require the declaration to contain a brace block." ((looking-at c-string-limit-regexp) ; Just gone back over a string terminator? (goto-char last) (throw 'done '(t . literal))) - + ;; Nothing special: go back word characters. (t (skip-syntax-backward "w_")) ; Speedup only. )))))) @@ -2136,7 +2299,7 @@ function does not require the declaration to contain a brace block." ;; As a clarification of "after the end-of-statement", if a comment or ;; whitespace follows a completed AWK statement, that statement is treated ;; as ending just after the last non-ws character before the comment. - ;; + ;; ;; Note that this function moves within either preprocessor commands ;; (macros) or normal code, but not both within the same invocation. ;; @@ -2427,7 +2590,6 @@ sentence motion in or near comments and multiline strings." (if (/= count 0) (setq count (1- count)))) (c-keep-region-active)))) - ;; set up electric character functions to work with pending-del, @@ -2454,6 +2616,7 @@ sentence motion in or near comments and multiline strings." (put 'c-electric-delete-forward 'pending-delete 'supersede) ; pending-del +;; Inserting/indenting comments (defun c-calc-comment-indent (entry) ;; This function might do hidden buffer changes. (if (symbolp entry) @@ -2549,6 +2712,7 @@ See `c-indent-comment-alist' for a description." (current-column)))) +;; Movement by CPP conditionals. (defun c-up-conditional (count) "Move back to the containing preprocessor conditional, leaving mark behind. A prefix argument acts as a repeat count. With a negative argument, @@ -2560,7 +2724,7 @@ forward." (interactive "p") (c-forward-conditional (- count) -1) (c-keep-region-active)) - + (defun c-up-conditional-with-else (count) "Move back to the containing preprocessor conditional, including \"#else\". Just like `c-up-conditional', except it also stops at \"#else\" @@ -2782,7 +2946,7 @@ prefix argument is equivalent to -1. (defun c-indent-exp (&optional shutup-p) "Indent each line in the balanced expression following point syntactically. -If optional SHUTUP-P is non-nil, no errors are signalled if no +If optional SHUTUP-P is non-nil, no errors are signaled if no balanced expression is found." (interactive "*P") (let ((here (point-marker)) @@ -3597,7 +3761,7 @@ command to conveniently insert and align the necessary backslashes." ;; Note that this function does not do any hidden buffer changes. (let (fill - ;; beg and end limits the region to narrow. end is a marker. + ;; beg and end limit the region to narrow. end is a marker. beg end ;; tmp-pre and tmp-post mark strings that are temporarily ;; inserted at the start and end of the region. tmp-pre is a @@ -3611,7 +3775,7 @@ command to conveniently insert and align the necessary backslashes." hang-ender-stuck ;; auto-fill-spaces is the exact sequence of whitespace between a ;; comment's last word and the comment ender, temporarily replaced - ;; with 'x's before calling FUN when FILL-PARAGRAPH is nil. + ;; with 'x's before calling FUN when FILL-PARAGRAPH is nil. auto-fill-spaces (here (point)) (c-lit-limits c-lit-limits) @@ -3620,9 +3784,12 @@ command to conveniently insert and align the necessary backslashes." ;; Restore point on undo. It's necessary since we do a lot of ;; hidden inserts and deletes below that should be as transparent ;; as possible. - (if (and buffer-undo-list (not (eq buffer-undo-list t))) + (if (and buffer-undo-list (not (eq buffer-undo-list t))) (setq buffer-undo-list (cons (point) buffer-undo-list))) + ;; Determine the limits and type of the containing literal (if any): + ;; C-LIT-LIMITS, C-LIT-TYPE; and the limits of the current paragraph: + ;; BEG and END. (c-save-buffer-state () (save-restriction ;; Widen to catch comment limits correctly. @@ -3650,6 +3817,13 @@ command to conveniently insert and align the necessary backslashes." (unwind-protect (progn + ;; For each of the possible types of text (string, C comment ...) + ;; determine BEG and END, the region we will narrow to. If we're in + ;; a literal, constrain BEG and END to the limits of this literal. + ;; + ;; For some of these text types, particularly a block comment, we + ;; may need to massage whitespace near literal delimiters, so that + ;; these don't get filled inappropriately. (cond ((eq c-lit-type 'c++) ; Line comment. @@ -3673,22 +3847,34 @@ command to conveniently insert and align the necessary backslashes." (setq apply-outside-literal t)) ((eq c-lit-type 'c) ; Block comment. - (when (>= end (cdr c-lit-limits)) - ;; The region includes the comment ender which we might - ;; want to keep together with the last word. - (unless (save-excursion - (goto-char (cdr c-lit-limits)) - (beginning-of-line) - (and (looking-at (concat "[ \t]*\\(" - c-current-comment-prefix - "\\)\\*/")) - (eq (cdr c-lit-limits) (match-end 0)) - ;; The comment ender is on a line of its - ;; own. Keep it that way. - (set-marker end (point)))) - - ;; The comment ender should hang. Replace all space between - ;; it and the last word either by one or two 'x's (when + (when + (or (> end (cdr c-lit-limits)) + (and (= end (cdr c-lit-limits)) + (eq (char-before end) ?/) + (eq (char-before (1- end)) ?*) + ;; disallow "/*/" + (> (- (cdr c-lit-limits) (car c-lit-limits)) 3))) + ;; There is a comment ender, and the region includes it. If + ;; it's on its own line, it stays on its own line. If it's got + ;; company on the line, it keeps (at least one word of) it. + ;; "=====*/" counts as a comment ender here, but "===== */" + ;; doesn't and "foo*/" doesn't. + (unless + (save-excursion + (goto-char (cdr c-lit-limits)) + (beginning-of-line) + (and (search-forward-regexp + (concat "\\=[ \t]*\\(" c-current-comment-prefix "\\)") + (- (cdr c-lit-limits) 2) t) + (not (search-forward-regexp + "\\(\\s \\|\\sw\\)" + (- (cdr c-lit-limits) 2) 'limit)) + ;; The comment ender IS on its own line. Exclude + ;; this line from the filling. + (set-marker end (c-point 'bol)))) + + ;; The comment ender is hanging. Replace all space between it + ;; and the last word either by one or two 'x's (when ;; FILL-PARAGRAPH is non-nil), or a row of x's the same width ;; as the whitespace (when auto filling), and include it in ;; the region. We'll change them back to whitespace @@ -3705,23 +3891,26 @@ command to conveniently insert and align the necessary backslashes." spaces) (save-excursion + ;; Insert a CR after the "*/", adjust END (goto-char (cdr c-lit-limits)) (setq tmp-post (point-marker)) (insert ?\n) (set-marker end (point)) + (forward-line -1) ; last line of the comment (if (and (looking-at (concat "[ \t]*\\(\\(" c-current-comment-prefix "\\)[ \t]*\\)")) (eq ender-start (match-end 0))) - ;; The comment ender is prefixed by nothing - ;; but a comment line prefix. Remove it - ;; along with surrounding ws. + ;; The comment ender is prefixed by nothing but a + ;; comment line prefix. IS THIS POSSIBLE? (ACM, + ;; 2006/4/28). Remove it along with surrounding ws. (setq spaces (- (match-end 1) (match-end 2))) (goto-char ender-start)) (skip-chars-backward " \t\r\n") ; Surely this can be ; " \t"? "*/" is NOT alone on the line (ACM, 2005/8/18) + ;; What's being tested here? 2006/4/20. FIXME!!! (if (/= (point) ender-start) (progn (if (<= here (point)) @@ -4057,6 +4246,7 @@ If a fill prefix is specified, it overrides all the above." (c-collect-line-comments c-lit-limits)) c-lit-type))) (pos (point)) + (start-col (current-column)) (comment-text-end (or (and (eq c-lit-type 'c) (save-excursion @@ -4073,6 +4263,11 @@ If a fill prefix is specified, it overrides all the above." ;; ;; If point is on the 'B' then the line will be ;; broken after "Bla b". + ;; + ;; If we have an empty comment, /* */, the next + ;; lot of code pushes point to the */. We fix + ;; this by never allowing point to end up to the + ;; right of where it started. (while (and (< (current-column) (cdr fill)) (not (eolp))) (forward-char 1)) @@ -4095,7 +4290,10 @@ If a fill prefix is specified, it overrides all the above." ((< (point) (+ (car c-lit-limits) 2)) (goto-char (+ (car c-lit-limits) 2)))) (funcall do-line-break) - (insert-and-inherit (car fill)))) + (insert-and-inherit (car fill)) + (if (> (current-column) start-col) + (move-to-column start-col)))) ; can this hit the + ; middle of a TAB? ;; Inside a comment that should be broken. (let ((comment-start comment-start) (comment-end comment-end) @@ -4171,49 +4369,63 @@ it. When point is inside a comment, continue it with the appropriate comment prefix (see the `c-comment-prefix-regexp' and `c-block-comment-prefix' variables for details). The end of a -C++-style line comment doesn't count as inside it." +C++-style line comment doesn't count as inside it. + +When point is inside a string, only insert a backslash when it is also +inside a preprocessor directive." (interactive "*") (let* (c-lit-limits c-lit-type (c-macro-start c-macro-start)) - (if (c-save-buffer-state () - (setq c-lit-limits (c-literal-limits nil nil t) - c-lit-type (c-literal-type c-lit-limits)) - (or (eq c-lit-type 'c) - (and (eq c-lit-type 'c++) - (< (save-excursion - (skip-chars-forward " \t") - (point)) - (1- (cdr (setq c-lit-limits (c-collect-line-comments - c-lit-limits)))))) - (and (or (not (looking-at "\\s *$")) - (eq (char-before) ?\\)) - (c-query-and-set-macro-start) - (<= (save-excursion - (goto-char c-macro-start) - (if (looking-at c-opt-cpp-start) - (goto-char (match-end 0))) - (point)) - (point))))) - - (let ((comment-multi-line t) - (fill-prefix nil)) - (c-indent-new-comment-line nil t)) - - (delete-horizontal-space) - (newline) + (c-save-buffer-state () + (setq c-lit-limits (c-literal-limits nil nil t) + c-lit-type (c-literal-type c-lit-limits)) + (when (eq c-lit-type 'c++) + (setq c-lit-limits (c-collect-line-comments c-lit-limits))) + (c-query-and-set-macro-start)) + (cond + ((or (eq c-lit-type 'c) + (and (eq c-lit-type 'c++) ; C++ comment, but not at the very end of it. + (< (save-excursion + (skip-chars-forward " \t") + (point)) + (1- (cdr c-lit-limits)))) + (and (numberp c-macro-start) ; Macro, but not at the very end of + ; it, not in a string, and not in the + ; cpp keyword. + (not (eq c-lit-type 'string)) + (or (not (looking-at "\\s *$")) + (eq (char-before) ?\\)) + (<= (save-excursion + (goto-char c-macro-start) + (if (looking-at c-opt-cpp-start) + (goto-char (match-end 0))) + (point)) + (point)))) + (let ((comment-multi-line t) + (fill-prefix nil)) + (c-indent-new-comment-line nil t))) + + ((eq c-lit-type 'string) + (if (and (numberp c-macro-start) + (not (eq (char-before) ?\\))) + (insert ?\\)) + (newline)) + + (t (delete-horizontal-space) + (newline) ;; c-indent-line may look at the current indentation, so let's ;; start out with the same indentation as the previous line. - (let ((col (save-excursion - (forward-line -1) - (while (and (looking-at "[ \t]*\\\\?$") - (= (forward-line -1) 0))) - (current-indentation)))) - (indent-to col)) - - (indent-according-to-mode)))) + (let ((col (save-excursion + (backward-char) + (forward-line 0) + (while (and (looking-at "[ \t]*\\\\?$") + (= (forward-line -1) 0))) + (current-indentation)))) + (indent-to col)) + (indent-according-to-mode))))) (defun c-context-open-line () "Insert a line break suitable to the context and leave point before it.