diff options
| author | Eric S. Raymond | 1991-12-11 16:08:43 +0000 |
|---|---|---|
| committer | Eric S. Raymond | 1991-12-11 16:08:43 +0000 |
| commit | a17915dc4c38e41ce29ec74dd56074ea01e6a206 (patch) | |
| tree | dabe0f55bdaa1baf698481bb3b4caf24a0bcc2ef | |
| parent | a7a50f69a016a687449acbf138eb5bfc3ce527c2 (diff) | |
| download | emacs-a17915dc4c38e41ce29ec74dd56074ea01e6a206.tar.gz emacs-a17915dc4c38e41ce29ec74dd56074ea01e6a206.zip | |
Initial revision
| -rw-r--r-- | lisp/progmodes/c-mode.el | 1057 |
1 files changed, 1057 insertions, 0 deletions
diff --git a/lisp/progmodes/c-mode.el b/lisp/progmodes/c-mode.el new file mode 100644 index 00000000000..a9267b3b7c9 --- /dev/null +++ b/lisp/progmodes/c-mode.el | |||
| @@ -0,0 +1,1057 @@ | |||
| 1 | ;; C code editing commands for Emacs | ||
| 2 | ;; Copyright (C) 1985, 1986, 1987 Free Software Foundation, Inc. | ||
| 3 | |||
| 4 | ;; This file is part of GNU Emacs. | ||
| 5 | |||
| 6 | ;; GNU Emacs is free software; you can redistribute it and/or modify | ||
| 7 | ;; it under the terms of the GNU General Public License as published by | ||
| 8 | ;; the Free Software Foundation; either version 1, or (at your option) | ||
| 9 | ;; any later version. | ||
| 10 | |||
| 11 | ;; GNU Emacs is distributed in the hope that it will be useful, | ||
| 12 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | ;; GNU General Public License for more details. | ||
| 15 | |||
| 16 | ;; You should have received a copy of the GNU General Public License | ||
| 17 | ;; along with GNU Emacs; see the file COPYING. If not, write to | ||
| 18 | ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 19 | |||
| 20 | |||
| 21 | (defvar c-mode-abbrev-table nil | ||
| 22 | "Abbrev table in use in C mode.") | ||
| 23 | (define-abbrev-table 'c-mode-abbrev-table ()) | ||
| 24 | |||
| 25 | (defvar c-mode-map () | ||
| 26 | "Keymap used in C mode.") | ||
| 27 | (if c-mode-map | ||
| 28 | () | ||
| 29 | (setq c-mode-map (make-sparse-keymap)) | ||
| 30 | (define-key c-mode-map "{" 'electric-c-brace) | ||
| 31 | (define-key c-mode-map "}" 'electric-c-brace) | ||
| 32 | (define-key c-mode-map ";" 'electric-c-semi) | ||
| 33 | (define-key c-mode-map "#" 'electric-c-sharp-sign) | ||
| 34 | (define-key c-mode-map ":" 'electric-c-terminator) | ||
| 35 | (define-key c-mode-map "\e\C-h" 'mark-c-function) | ||
| 36 | (define-key c-mode-map "\e\C-q" 'indent-c-exp) | ||
| 37 | (define-key c-mode-map "\ea" 'c-beginning-of-statement) | ||
| 38 | (define-key c-mode-map "\ee" 'c-end-of-statement) | ||
| 39 | (define-key c-mode-map "\eq" 'c-fill-paragraph) | ||
| 40 | (define-key c-mode-map "\177" 'backward-delete-char-untabify) | ||
| 41 | (define-key c-mode-map "\t" 'c-indent-command)) | ||
| 42 | |||
| 43 | ;; cmacexp is lame because it uses no preprocessor symbols. | ||
| 44 | ;; It isn't very extensible either -- hardcodes /lib/cpp. | ||
| 45 | (autoload 'c-macro-expand "cmacexp" | ||
| 46 | "Display the result of expanding all C macros occurring in the region. | ||
| 47 | The expansion is entirely correct because it uses the C preprocessor." | ||
| 48 | t) | ||
| 49 | |||
| 50 | (defvar c-mode-syntax-table nil | ||
| 51 | "Syntax table in use in C-mode buffers.") | ||
| 52 | |||
| 53 | (if c-mode-syntax-table | ||
| 54 | () | ||
| 55 | (setq c-mode-syntax-table (make-syntax-table)) | ||
| 56 | (modify-syntax-entry ?\\ "\\" c-mode-syntax-table) | ||
| 57 | (modify-syntax-entry ?/ ". 14" c-mode-syntax-table) | ||
| 58 | (modify-syntax-entry ?* ". 23" c-mode-syntax-table) | ||
| 59 | (modify-syntax-entry ?+ "." c-mode-syntax-table) | ||
| 60 | (modify-syntax-entry ?- "." c-mode-syntax-table) | ||
| 61 | (modify-syntax-entry ?= "." c-mode-syntax-table) | ||
| 62 | (modify-syntax-entry ?% "." c-mode-syntax-table) | ||
| 63 | (modify-syntax-entry ?< "." c-mode-syntax-table) | ||
| 64 | (modify-syntax-entry ?> "." c-mode-syntax-table) | ||
| 65 | (modify-syntax-entry ?& "." c-mode-syntax-table) | ||
| 66 | (modify-syntax-entry ?| "." c-mode-syntax-table) | ||
| 67 | (modify-syntax-entry ?\' "\"" c-mode-syntax-table)) | ||
| 68 | |||
| 69 | (defconst c-indent-level 2 | ||
| 70 | "*Indentation of C statements with respect to containing block.") | ||
| 71 | (defconst c-brace-imaginary-offset 0 | ||
| 72 | "*Imagined indentation of a C open brace that actually follows a statement.") | ||
| 73 | (defconst c-brace-offset 0 | ||
| 74 | "*Extra indentation for braces, compared with other text in same context.") | ||
| 75 | (defconst c-argdecl-indent 5 | ||
| 76 | "*Indentation level of declarations of C function arguments.") | ||
| 77 | (defconst c-label-offset -2 | ||
| 78 | "*Offset of C label lines and case statements relative to usual indentation.") | ||
| 79 | (defconst c-continued-statement-offset 2 | ||
| 80 | "*Extra indent for lines not starting new statements.") | ||
| 81 | (defconst c-continued-brace-offset 0 | ||
| 82 | "*Extra indent for substatements that start with open-braces. | ||
| 83 | This is in addition to c-continued-statement-offset.") | ||
| 84 | (defconst c-style-alist | ||
| 85 | '(("GNU" | ||
| 86 | (c-indent-level . 2) | ||
| 87 | (c-argdecl-indent . 5) | ||
| 88 | (c-brace-offset . 0) | ||
| 89 | (c-label-offset . -2) | ||
| 90 | (c-continued-statement-offset . 2)) | ||
| 91 | ("K&R" | ||
| 92 | (c-indent-level . 5) | ||
| 93 | (c-argdecl-indent . 0) | ||
| 94 | (c-brace-offset . -5) | ||
| 95 | (c-label-offset . -5) | ||
| 96 | (c-continued-statement-offset . 5)) | ||
| 97 | ("BSD" | ||
| 98 | (c-indent-level . 4) | ||
| 99 | (c-argdecl-indent . 4) | ||
| 100 | (c-brace-offset . -4) | ||
| 101 | (c-label-offset . -4) | ||
| 102 | (c-continued-statement-offset . 4)) | ||
| 103 | ("Whitesmith" | ||
| 104 | (c-indent-level . 4) | ||
| 105 | (c-argdecl-indent . 4) | ||
| 106 | (c-brace-offset . 0) | ||
| 107 | (c-label-offset . -4) | ||
| 108 | (c-continued-statement-offset . 4)))) | ||
| 109 | |||
| 110 | (defconst c-auto-newline nil | ||
| 111 | "*Non-nil means automatically newline before and after braces, | ||
| 112 | and after colons and semicolons, inserted in C code. | ||
| 113 | If you do not want a leading newline before braces then use: | ||
| 114 | (define-key c-mode-map "{" 'electric-c-semi)") | ||
| 115 | |||
| 116 | (defconst c-tab-always-indent t | ||
| 117 | "*Non-nil means TAB in C mode should always reindent the current line, | ||
| 118 | regardless of where in the line point is when the TAB command is used.") | ||
| 119 | |||
| 120 | (defun set-c-style (&optional style) | ||
| 121 | "Set up the c-mode style variables from the c-style variable or if | ||
| 122 | STYLE argument is given, use that. It makes the c indentation style | ||
| 123 | variables buffer local." | ||
| 124 | (interactive) | ||
| 125 | (let ((c-styles (mapcar 'car c-style-alist))) | ||
| 126 | (if (interactive-p) | ||
| 127 | (setq style | ||
| 128 | (let ((style-string ; get style name with completion | ||
| 129 | (completing-read | ||
| 130 | (format "Set c mode indentation style to (default %s): " | ||
| 131 | default-c-style) | ||
| 132 | (vconcat c-styles) | ||
| 133 | (function (lambda (arg) (memq arg c-styles))) | ||
| 134 | ))) | ||
| 135 | (if (string-equal "" style-string) | ||
| 136 | default-c-style | ||
| 137 | (intern style-string)) | ||
| 138 | ))) | ||
| 139 | (setq style (or style c-style)) ; use c-style if style is nil | ||
| 140 | (make-local-variable 'c-style) | ||
| 141 | (if (memq style c-styles) | ||
| 142 | (setq c-style style) | ||
| 143 | (error "Bad c style: %s" style) | ||
| 144 | ) | ||
| 145 | (message "c-style: %s" c-style) | ||
| 146 | ; finally, set the indentation style variables making each one local | ||
| 147 | (mapcar (function (lambda (c-style-pair) | ||
| 148 | (make-local-variable (car c-style-pair)) | ||
| 149 | (set (car c-style-pair) | ||
| 150 | (cdr c-style-pair)))) | ||
| 151 | (cdr (assq c-style c-style-alist))) | ||
| 152 | c-style | ||
| 153 | ) | ||
| 154 | ) | ||
| 155 | |||
| 156 | (defun c-mode () | ||
| 157 | "Major mode for editing C code. | ||
| 158 | Expression and list commands understand all C brackets. | ||
| 159 | Tab indents for C code. | ||
| 160 | Comments are delimited with /* ... */. | ||
| 161 | Paragraphs are separated by blank lines only. | ||
| 162 | Delete converts tabs to spaces as it moves back. | ||
| 163 | \\{c-mode-map} | ||
| 164 | Variables controlling indentation style: | ||
| 165 | c-tab-always-indent | ||
| 166 | Non-nil means TAB in C mode should always reindent the current line, | ||
| 167 | regardless of where in the line point is when the TAB command is used. | ||
| 168 | c-auto-newline | ||
| 169 | Non-nil means automatically newline before and after braces, | ||
| 170 | and after colons and semicolons, inserted in C code. | ||
| 171 | c-indent-level | ||
| 172 | Indentation of C statements within surrounding block. | ||
| 173 | The surrounding block's indentation is the indentation | ||
| 174 | of the line on which the open-brace appears. | ||
| 175 | c-continued-statement-offset | ||
| 176 | Extra indentation given to a substatement, such as the | ||
| 177 | then-clause of an if or body of a while. | ||
| 178 | c-continued-brace-offset | ||
| 179 | Extra indentation given to a brace that starts a substatement. | ||
| 180 | This is in addition to c-continued-statement-offset. | ||
| 181 | c-brace-offset | ||
| 182 | Extra indentation for line if it starts with an open brace. | ||
| 183 | c-brace-imaginary-offset | ||
| 184 | An open brace following other text is treated as if it were | ||
| 185 | this far to the right of the start of its line. | ||
| 186 | c-argdecl-indent | ||
| 187 | Indentation level of declarations of C function arguments. | ||
| 188 | c-label-offset | ||
| 189 | Extra indentation for line that is a label, or case or default. | ||
| 190 | |||
| 191 | Settings for K&R and BSD indentation styles are | ||
| 192 | c-indent-level 5 8 | ||
| 193 | c-continued-statement-offset 5 8 | ||
| 194 | c-brace-offset -5 -8 | ||
| 195 | c-argdecl-indent 0 8 | ||
| 196 | c-label-offset -5 -8 | ||
| 197 | |||
| 198 | Turning on C mode calls the value of the variable c-mode-hook with no args, | ||
| 199 | if that value is non-nil." | ||
| 200 | (interactive) | ||
| 201 | (kill-all-local-variables) | ||
| 202 | (use-local-map c-mode-map) | ||
| 203 | (setq major-mode 'c-mode) | ||
| 204 | (setq mode-name "C") | ||
| 205 | (setq local-abbrev-table c-mode-abbrev-table) | ||
| 206 | (set-syntax-table c-mode-syntax-table) | ||
| 207 | (make-local-variable 'paragraph-start) | ||
| 208 | (setq paragraph-start (concat "^$\\|" page-delimiter)) | ||
| 209 | (make-local-variable 'paragraph-separate) | ||
| 210 | (setq paragraph-separate paragraph-start) | ||
| 211 | (make-local-variable 'paragraph-ignore-fill-prefix) | ||
| 212 | (setq paragraph-ignore-fill-prefix t) | ||
| 213 | (make-local-variable 'indent-line-function) | ||
| 214 | (setq indent-line-function 'c-indent-line) | ||
| 215 | (make-local-variable 'indent-region-function) | ||
| 216 | (setq indent-region-function 'c-indent-region) | ||
| 217 | (make-local-variable 'require-final-newline) | ||
| 218 | (setq require-final-newline t) | ||
| 219 | (make-local-variable 'comment-start) | ||
| 220 | (setq comment-start "/* ") | ||
| 221 | (make-local-variable 'comment-end) | ||
| 222 | (setq comment-end " */") | ||
| 223 | (make-local-variable 'comment-column) | ||
| 224 | (setq comment-column 32) | ||
| 225 | (make-local-variable 'comment-start-skip) | ||
| 226 | (setq comment-start-skip "/\\*+ *") | ||
| 227 | (make-local-variable 'comment-indent-hook) | ||
| 228 | (setq comment-indent-hook 'c-comment-indent) | ||
| 229 | (make-local-variable 'parse-sexp-ignore-comments) | ||
| 230 | (setq parse-sexp-ignore-comments t) | ||
| 231 | (run-hooks 'c-mode-hook)) | ||
| 232 | |||
| 233 | ;; This is used by indent-for-comment | ||
| 234 | ;; to decide how much to indent a comment in C code | ||
| 235 | ;; based on its context. | ||
| 236 | (defun c-comment-indent () | ||
| 237 | (if (looking-at "^/\\*") | ||
| 238 | 0 ;Existing comment at bol stays there. | ||
| 239 | (let ((opoint (point))) | ||
| 240 | (save-excursion | ||
| 241 | (beginning-of-line) | ||
| 242 | (cond ((looking-at "[ \t]*}[ \t]*\\($\\|/\\*\\)") | ||
| 243 | ;; A comment following a solitary close-brace | ||
| 244 | ;; should have only one space. | ||
| 245 | (search-forward "}") | ||
| 246 | (1+ (current-column))) | ||
| 247 | ((or (looking-at "^#[ \t]*endif[ \t]*") | ||
| 248 | (looking-at "^#[ \t]*else[ \t]*")) | ||
| 249 | 7) ;2 spaces after #endif | ||
| 250 | ((progn | ||
| 251 | (goto-char opoint) | ||
| 252 | (skip-chars-backward " \t") | ||
| 253 | (and (= comment-column 0) (bolp))) | ||
| 254 | ;; If comment-column is 0, and nothing but space | ||
| 255 | ;; before the comment, align it at 0 rather than 1. | ||
| 256 | 0) | ||
| 257 | (t | ||
| 258 | (max (1+ (current-column)) ;Else indent at comment column | ||
| 259 | comment-column))))))) ; except leave at least one space. | ||
| 260 | |||
| 261 | (defun c-fill-paragraph (&optional arg) | ||
| 262 | "Like \\[fill-paragraph] but handle C comments. | ||
| 263 | If point is inside a comment, the current paragraph of the comment | ||
| 264 | is filled, preserving the comment indentation or line-starting decorations." | ||
| 265 | (interactive "P") | ||
| 266 | (let ((first-line | ||
| 267 | (save-excursion | ||
| 268 | (beginning-of-line) | ||
| 269 | (skip-chars-forward " \t") | ||
| 270 | (looking-at comment-start-skip)))) | ||
| 271 | (if (or first-line | ||
| 272 | (eq (calculate-c-indent) t)) | ||
| 273 | ;; Inside a comment: fill one comment paragraph. | ||
| 274 | (let ((fill-prefix | ||
| 275 | ;; The prefix for each line of this paragraph | ||
| 276 | ;; is the appropriate part of the start of this line, | ||
| 277 | ;; up to the column at which text should be indented. | ||
| 278 | (save-excursion | ||
| 279 | (beginning-of-line) | ||
| 280 | (if (looking-at "[ \t]*/\\*.*\\*/") | ||
| 281 | (progn (re-search-forward comment-start-skip) | ||
| 282 | (make-string (current-column) ?\ )) | ||
| 283 | (if first-line (forward-line 1)) | ||
| 284 | (buffer-substring (point) | ||
| 285 | (progn | ||
| 286 | (move-to-column | ||
| 287 | (calculate-c-indent-within-comment t) | ||
| 288 | t) | ||
| 289 | (point)))))) | ||
| 290 | (paragraph-start | ||
| 291 | ;; Lines containing just a comment start or just an end | ||
| 292 | ;; should not be filled into paragraphs they are next to. | ||
| 293 | (concat paragraph-start | ||
| 294 | "\\|^[ \t]*/\\*[ \t]*$\\|^[ \t]*\\*/[ \t]*$\\|^[^ \t/*]")) | ||
| 295 | (paragraph-separate | ||
| 296 | (concat paragraph-separate | ||
| 297 | "\\|^[ \t]*/\\*[ \t]*$\\|^[ \t]*\\*/[ \t]*$\\|^[^ \t/*]"))) | ||
| 298 | (save-restriction | ||
| 299 | ;; Don't fill the comment together with the code following it. | ||
| 300 | (narrow-to-region (point-min) | ||
| 301 | (save-excursion | ||
| 302 | (search-forward "*/" nil 'move) | ||
| 303 | (forward-line 1) | ||
| 304 | (point))) | ||
| 305 | (fill-paragraph arg) | ||
| 306 | (save-excursion | ||
| 307 | (search-forward "*/") | ||
| 308 | (beginning-of-line) | ||
| 309 | (if (looking-at "[ \t]*\\*/") | ||
| 310 | (delete-indentation))))) | ||
| 311 | ;; Outside of comments: do ordinary filling. | ||
| 312 | (fill-paragraph arg)))) | ||
| 313 | |||
| 314 | (defun electric-c-brace (arg) | ||
| 315 | "Insert character and correct line's indentation." | ||
| 316 | (interactive "P") | ||
| 317 | (let (insertpos) | ||
| 318 | (if (and (not arg) | ||
| 319 | (eolp) | ||
| 320 | (or (save-excursion | ||
| 321 | (skip-chars-backward " \t") | ||
| 322 | (bolp)) | ||
| 323 | (if c-auto-newline (progn (c-indent-line) (newline) t) nil))) | ||
| 324 | (progn | ||
| 325 | (insert last-command-char) | ||
| 326 | (c-indent-line) | ||
| 327 | (if c-auto-newline | ||
| 328 | (progn | ||
| 329 | (newline) | ||
| 330 | ;; (newline) may have done auto-fill | ||
| 331 | (setq insertpos (- (point) 2)) | ||
| 332 | (c-indent-line))) | ||
| 333 | (save-excursion | ||
| 334 | (if insertpos (goto-char (1+ insertpos))) | ||
| 335 | (delete-char -1)))) | ||
| 336 | (if insertpos | ||
| 337 | (save-excursion | ||
| 338 | (goto-char insertpos) | ||
| 339 | (self-insert-command (prefix-numeric-value arg))) | ||
| 340 | (self-insert-command (prefix-numeric-value arg))))) | ||
| 341 | |||
| 342 | (defun electric-c-sharp-sign (arg) | ||
| 343 | "Insert character and correct line's indentation." | ||
| 344 | (interactive "P") | ||
| 345 | (if (save-excursion | ||
| 346 | (skip-chars-backward " \t") | ||
| 347 | (bolp)) | ||
| 348 | (let ((c-auto-newline nil)) | ||
| 349 | (electric-c-terminator arg)) | ||
| 350 | (self-insert-command (prefix-numeric-value arg)))) | ||
| 351 | |||
| 352 | (defun electric-c-semi (arg) | ||
| 353 | "Insert character and correct line's indentation." | ||
| 354 | (interactive "P") | ||
| 355 | (if c-auto-newline | ||
| 356 | (electric-c-terminator arg) | ||
| 357 | (self-insert-command (prefix-numeric-value arg)))) | ||
| 358 | |||
| 359 | (defun electric-c-terminator (arg) | ||
| 360 | "Insert character and correct line's indentation." | ||
| 361 | (interactive "P") | ||
| 362 | (let (insertpos (end (point))) | ||
| 363 | (if (and (not arg) (eolp) | ||
| 364 | (not (save-excursion | ||
| 365 | (beginning-of-line) | ||
| 366 | (skip-chars-forward " \t") | ||
| 367 | (or (= (following-char) ?#) | ||
| 368 | ;; Colon is special only after a label, or case .... | ||
| 369 | ;; So quickly rule out most other uses of colon | ||
| 370 | ;; and do no indentation for them. | ||
| 371 | (and (eq last-command-char ?:) | ||
| 372 | (not (looking-at "case[ \t'/(]\\|default\\>")) | ||
| 373 | (save-excursion | ||
| 374 | (skip-chars-forward "a-zA-Z0-9_$") | ||
| 375 | (skip-chars-forward " \t") | ||
| 376 | (< (point) end))) | ||
| 377 | (progn | ||
| 378 | (beginning-of-defun) | ||
| 379 | (let ((pps (parse-partial-sexp (point) end))) | ||
| 380 | (or (nth 3 pps) (nth 4 pps) (nth 5 pps)))))))) | ||
| 381 | (progn | ||
| 382 | (insert last-command-char) | ||
| 383 | (c-indent-line) | ||
| 384 | (and c-auto-newline | ||
| 385 | (not (c-inside-parens-p)) | ||
| 386 | (progn | ||
| 387 | (newline) | ||
| 388 | ;; (newline) may have done auto-fill | ||
| 389 | (setq insertpos (- (point) 2)) | ||
| 390 | (c-indent-line))) | ||
| 391 | (save-excursion | ||
| 392 | (if insertpos (goto-char (1+ insertpos))) | ||
| 393 | (delete-char -1)))) | ||
| 394 | (if insertpos | ||
| 395 | (save-excursion | ||
| 396 | (goto-char insertpos) | ||
| 397 | (self-insert-command (prefix-numeric-value arg))) | ||
| 398 | (self-insert-command (prefix-numeric-value arg))))) | ||
| 399 | |||
| 400 | (defun c-inside-parens-p () | ||
| 401 | (condition-case () | ||
| 402 | (save-excursion | ||
| 403 | (save-restriction | ||
| 404 | (narrow-to-region (point) | ||
| 405 | (progn (beginning-of-defun) (point))) | ||
| 406 | (goto-char (point-max)) | ||
| 407 | (= (char-after (or (scan-lists (point) -1 1) (point-min))) ?\())) | ||
| 408 | (error nil))) | ||
| 409 | |||
| 410 | (defun c-indent-command (&optional whole-exp) | ||
| 411 | "Indent current line as C code, or in some cases insert a tab character. | ||
| 412 | If `c-tab-always-indent' is non-nil (the default), always indent current line. | ||
| 413 | Otherwise, indent the current line only if point is at the left margin or | ||
| 414 | in the line's indentation; otherwise insert a tab. | ||
| 415 | |||
| 416 | A numeric argument, regardless of its value, means indent rigidly all the | ||
| 417 | lines of the expression starting after point so that this line becomes | ||
| 418 | properly indented. The relative indentation among the lines of the | ||
| 419 | expression are preserved." | ||
| 420 | (interactive "P") | ||
| 421 | (if whole-exp | ||
| 422 | ;; If arg, always indent this line as C | ||
| 423 | ;; and shift remaining lines of expression the same amount. | ||
| 424 | (let ((shift-amt (c-indent-line)) | ||
| 425 | beg end) | ||
| 426 | (save-excursion | ||
| 427 | (if c-tab-always-indent | ||
| 428 | (beginning-of-line)) | ||
| 429 | ;; Find beginning of following line. | ||
| 430 | (save-excursion | ||
| 431 | (forward-line 1) (setq beg (point))) | ||
| 432 | ;; Find first beginning-of-sexp for sexp extending past this line. | ||
| 433 | (while (< (point) beg) | ||
| 434 | (forward-sexp 1) | ||
| 435 | (setq end (point)) | ||
| 436 | (skip-chars-forward " \t\n"))) | ||
| 437 | (if (> end beg) | ||
| 438 | (indent-code-rigidly beg end shift-amt "#"))) | ||
| 439 | (if (and (not c-tab-always-indent) | ||
| 440 | (save-excursion | ||
| 441 | (skip-chars-backward " \t") | ||
| 442 | (not (bolp)))) | ||
| 443 | (insert-tab) | ||
| 444 | (c-indent-line)))) | ||
| 445 | |||
| 446 | (defun c-indent-line () | ||
| 447 | "Indent current line as C code. | ||
| 448 | Return the amount the indentation changed by." | ||
| 449 | (let ((indent (calculate-c-indent nil)) | ||
| 450 | beg shift-amt | ||
| 451 | (case-fold-search nil) | ||
| 452 | (pos (- (point-max) (point)))) | ||
| 453 | (beginning-of-line) | ||
| 454 | (setq beg (point)) | ||
| 455 | (cond ((eq indent nil) | ||
| 456 | (setq indent (current-indentation))) | ||
| 457 | ((eq indent t) | ||
| 458 | (setq indent (calculate-c-indent-within-comment))) | ||
| 459 | ((looking-at "[ \t]*#") | ||
| 460 | (setq indent 0)) | ||
| 461 | (t | ||
| 462 | (skip-chars-forward " \t") | ||
| 463 | (if (listp indent) (setq indent (car indent))) | ||
| 464 | (cond ((or (looking-at "case[ \t'/(]\\|default\\>") | ||
| 465 | (and (looking-at "[A-Za-z]") | ||
| 466 | (save-excursion | ||
| 467 | (forward-sexp 1) | ||
| 468 | (looking-at ":")))) | ||
| 469 | (setq indent (max 1 (+ indent c-label-offset)))) | ||
| 470 | ((and (looking-at "else\\b") | ||
| 471 | (not (looking-at "else\\s_"))) | ||
| 472 | (setq indent (save-excursion | ||
| 473 | (c-backward-to-start-of-if) | ||
| 474 | (current-indentation)))) | ||
| 475 | ((looking-at "}[ \t]*else") | ||
| 476 | (setq indent (save-excursion | ||
| 477 | (forward-char) | ||
| 478 | (backward-sexp) | ||
| 479 | (current-indentation)))) | ||
| 480 | ((and (looking-at "while\\b") | ||
| 481 | (save-excursion | ||
| 482 | (c-backward-to-start-of-do))) | ||
| 483 | ;; This is a `while' that ends a do-while. | ||
| 484 | (setq indent (save-excursion | ||
| 485 | (c-backward-to-start-of-do) | ||
| 486 | (current-indentation)))) | ||
| 487 | ((= (following-char) ?}) | ||
| 488 | (setq indent (- indent c-indent-level))) | ||
| 489 | ((= (following-char) ?{) | ||
| 490 | (setq indent (+ indent c-brace-offset)))))) | ||
| 491 | (skip-chars-forward " \t") | ||
| 492 | (setq shift-amt (- indent (current-column))) | ||
| 493 | (if (zerop shift-amt) | ||
| 494 | (if (> (- (point-max) pos) (point)) | ||
| 495 | (goto-char (- (point-max) pos))) | ||
| 496 | (delete-region beg (point)) | ||
| 497 | (indent-to indent) | ||
| 498 | ;; If initial point was within line's indentation, | ||
| 499 | ;; position after the indentation. Else stay at same point in text. | ||
| 500 | (if (> (- (point-max) pos) (point)) | ||
| 501 | (goto-char (- (point-max) pos)))) | ||
| 502 | shift-amt)) | ||
| 503 | |||
| 504 | (defun calculate-c-indent (&optional parse-start) | ||
| 505 | "Return appropriate indentation for current line as C code. | ||
| 506 | In usual case returns an integer: the column to indent to. | ||
| 507 | Returns nil if line starts inside a string, t if in a comment." | ||
| 508 | (save-excursion | ||
| 509 | (beginning-of-line) | ||
| 510 | (let ((indent-point (point)) | ||
| 511 | (case-fold-search nil) | ||
| 512 | state | ||
| 513 | containing-sexp) | ||
| 514 | (if parse-start | ||
| 515 | (goto-char parse-start) | ||
| 516 | (beginning-of-defun)) | ||
| 517 | (while (< (point) indent-point) | ||
| 518 | (setq parse-start (point)) | ||
| 519 | (setq state (parse-partial-sexp (point) indent-point 0)) | ||
| 520 | (setq containing-sexp (car (cdr state)))) | ||
| 521 | (cond ((or (nth 3 state) (nth 4 state)) | ||
| 522 | ;; return nil or t if should not change this line | ||
| 523 | (nth 4 state)) | ||
| 524 | ((null containing-sexp) | ||
| 525 | ;; Line is at top level. May be data or function definition, | ||
| 526 | ;; or may be function argument declaration. | ||
| 527 | ;; Indent like the previous top level line | ||
| 528 | ;; unless that ends in a closeparen without semicolon, | ||
| 529 | ;; in which case this line is the first argument decl. | ||
| 530 | (goto-char indent-point) | ||
| 531 | (skip-chars-forward " \t") | ||
| 532 | (if (= (following-char) ?{) | ||
| 533 | 0 ; Unless it starts a function body | ||
| 534 | (c-backward-to-noncomment (or parse-start (point-min))) | ||
| 535 | ;; Look at previous line that's at column 0 | ||
| 536 | ;; to determine whether we are in top-level decls | ||
| 537 | ;; or function's arg decls. Set basic-indent accordingly. | ||
| 538 | (let ((basic-indent | ||
| 539 | (save-excursion | ||
| 540 | (re-search-backward "^[^ \^L\t\n#]" nil 'move) | ||
| 541 | (if (and (looking-at "\\sw\\|\\s_") | ||
| 542 | (looking-at "[^\"\n=]*(") | ||
| 543 | (progn | ||
| 544 | (goto-char (1- (match-end 0))) | ||
| 545 | (forward-sexp 1) | ||
| 546 | (skip-chars-forward " \t\f") | ||
| 547 | (and (< (point) indent-point) | ||
| 548 | (not (memq (following-char) | ||
| 549 | '(?\, ?\;)))))) | ||
| 550 | c-argdecl-indent 0)))) | ||
| 551 | basic-indent))) | ||
| 552 | |||
| 553 | ;; ;; Now add a little if this is a continuation line. | ||
| 554 | ;; (+ basic-indent (if (or (bobp) | ||
| 555 | ;; (memq (preceding-char) '(?\) ?\; ?\})) | ||
| 556 | ;; ;; Line with zero indentation | ||
| 557 | ;; ;; is probably the return-type | ||
| 558 | ;; ;; of a function definition, | ||
| 559 | ;; ;; so following line is function name. | ||
| 560 | ;; (= (current-indentation) 0)) | ||
| 561 | ;; 0 c-continued-statement-offset)) | ||
| 562 | |||
| 563 | ((/= (char-after containing-sexp) ?{) | ||
| 564 | ;; line is expression, not statement: | ||
| 565 | ;; indent to just after the surrounding open. | ||
| 566 | (goto-char (1+ containing-sexp)) | ||
| 567 | (current-column)) | ||
| 568 | (t | ||
| 569 | ;; Statement level. Is it a continuation or a new statement? | ||
| 570 | ;; Find previous non-comment character. | ||
| 571 | (goto-char indent-point) | ||
| 572 | (c-backward-to-noncomment containing-sexp) | ||
| 573 | ;; Back up over label lines, since they don't | ||
| 574 | ;; affect whether our line is a continuation. | ||
| 575 | (while (or (eq (preceding-char) ?\,) | ||
| 576 | (and (eq (preceding-char) ?:) | ||
| 577 | (or (eq (char-after (- (point) 2)) ?\') | ||
| 578 | (memq (char-syntax (char-after (- (point) 2))) | ||
| 579 | '(?w ?_))))) | ||
| 580 | (if (eq (preceding-char) ?\,) | ||
| 581 | (progn (forward-char -1) | ||
| 582 | (c-backward-to-start-of-continued-exp containing-sexp))) | ||
| 583 | (beginning-of-line) | ||
| 584 | (c-backward-to-noncomment containing-sexp)) | ||
| 585 | ;; Check for a preprocessor statement or its continuation lines. | ||
| 586 | ;; Move back to end of previous non-preprocessor line. | ||
| 587 | (let ((found (point)) stop) | ||
| 588 | (while (not stop) | ||
| 589 | (cond ((save-excursion (end-of-line 0) | ||
| 590 | (= (preceding-char) ?\\)) | ||
| 591 | (end-of-line 0)) | ||
| 592 | ;; This line is not preceded by a backslash. | ||
| 593 | ;; So either it starts a preprocessor command | ||
| 594 | ;; or any following continuation lines | ||
| 595 | ;; should not be skipped. | ||
| 596 | ((progn (beginning-of-line) (= (following-char) ?#)) | ||
| 597 | (end-of-line 0) | ||
| 598 | (setq found (point))) | ||
| 599 | (t (setq stop t)))) | ||
| 600 | (goto-char found)) | ||
| 601 | ;; Now we get the answer. | ||
| 602 | (if (and (not (memq (preceding-char) '(nil ?\, ?\; ?\} ?\{))) | ||
| 603 | ;; But don't treat a line with a close-brace | ||
| 604 | ;; as a continuation. It is probably the | ||
| 605 | ;; end of an enum type declaration. | ||
| 606 | (save-excursion | ||
| 607 | (goto-char indent-point) | ||
| 608 | (skip-chars-forward " \t") | ||
| 609 | (not (= (following-char) ?})))) | ||
| 610 | ;; This line is continuation of preceding line's statement; | ||
| 611 | ;; indent c-continued-statement-offset more than the | ||
| 612 | ;; previous line of the statement. | ||
| 613 | (progn | ||
| 614 | (c-backward-to-start-of-continued-exp containing-sexp) | ||
| 615 | (+ c-continued-statement-offset (current-column) | ||
| 616 | (if (save-excursion (goto-char indent-point) | ||
| 617 | (skip-chars-forward " \t") | ||
| 618 | (eq (following-char) ?{)) | ||
| 619 | c-continued-brace-offset 0))) | ||
| 620 | ;; This line starts a new statement. | ||
| 621 | ;; Position following last unclosed open. | ||
| 622 | (goto-char containing-sexp) | ||
| 623 | ;; Is line first statement after an open-brace? | ||
| 624 | (or | ||
| 625 | ;; If no, find that first statement and indent like it. | ||
| 626 | (save-excursion | ||
| 627 | (forward-char 1) | ||
| 628 | (let ((colon-line-end 0)) | ||
| 629 | (while (progn (skip-chars-forward " \t\n") | ||
| 630 | (looking-at "#\\|/\\*\\|case[ \t\n'/(].*:\\|[a-zA-Z0-9_$]*:")) | ||
| 631 | ;; Skip over comments and labels following openbrace. | ||
| 632 | (cond ((= (following-char) ?\#) | ||
| 633 | (forward-line 1)) | ||
| 634 | ((= (following-char) ?\/) | ||
| 635 | (forward-char 2) | ||
| 636 | (search-forward "*/" nil 'move)) | ||
| 637 | ;; case or label: | ||
| 638 | (t | ||
| 639 | (save-excursion (end-of-line) | ||
| 640 | (setq colon-line-end (point))) | ||
| 641 | (search-forward ":")))) | ||
| 642 | ;; The first following code counts | ||
| 643 | ;; if it is before the line we want to indent. | ||
| 644 | (and (< (point) indent-point) | ||
| 645 | (if (> colon-line-end (point)) | ||
| 646 | (- (current-indentation) c-label-offset) | ||
| 647 | (current-column))))) | ||
| 648 | ;; If no previous statement, | ||
| 649 | ;; indent it relative to line brace is on. | ||
| 650 | ;; For open brace in column zero, don't let statement | ||
| 651 | ;; start there too. If c-indent-level is zero, | ||
| 652 | ;; use c-brace-offset + c-continued-statement-offset instead. | ||
| 653 | ;; For open-braces not the first thing in a line, | ||
| 654 | ;; add in c-brace-imaginary-offset. | ||
| 655 | (+ (if (and (bolp) (zerop c-indent-level)) | ||
| 656 | (+ c-brace-offset c-continued-statement-offset) | ||
| 657 | c-indent-level) | ||
| 658 | ;; Move back over whitespace before the openbrace. | ||
| 659 | ;; If openbrace is not first nonwhite thing on the line, | ||
| 660 | ;; add the c-brace-imaginary-offset. | ||
| 661 | (progn (skip-chars-backward " \t") | ||
| 662 | (if (bolp) 0 c-brace-imaginary-offset)) | ||
| 663 | ;; If the openbrace is preceded by a parenthesized exp, | ||
| 664 | ;; move to the beginning of that; | ||
| 665 | ;; possibly a different line | ||
| 666 | (progn | ||
| 667 | (if (eq (preceding-char) ?\)) | ||
| 668 | (forward-sexp -1)) | ||
| 669 | ;; Get initial indentation of the line we are on. | ||
| 670 | (current-indentation)))))))))) | ||
| 671 | |||
| 672 | (defun calculate-c-indent-within-comment (&optional after-star) | ||
| 673 | "Return the indentation amount for line inside a block comment. | ||
| 674 | Optional arg AFTER-STAR means, if lines in the comment have a leading star, | ||
| 675 | return the indentation of the text that would follow this star." | ||
| 676 | (let (end star-start) | ||
| 677 | (save-excursion | ||
| 678 | (beginning-of-line) | ||
| 679 | (skip-chars-forward " \t") | ||
| 680 | (setq star-start (= (following-char) ?\*)) | ||
| 681 | (skip-chars-backward " \t\n") | ||
| 682 | (setq end (point)) | ||
| 683 | (beginning-of-line) | ||
| 684 | (skip-chars-forward " \t") | ||
| 685 | (if after-star | ||
| 686 | (and (looking-at "\\*") | ||
| 687 | (re-search-forward "\\*[ \t]*"))) | ||
| 688 | (and (re-search-forward "/\\*[ \t]*" end t) | ||
| 689 | star-start | ||
| 690 | (not after-star) | ||
| 691 | (goto-char (1+ (match-beginning 0)))) | ||
| 692 | (if (and (looking-at "[ \t]*$") (= (preceding-char) ?\*)) | ||
| 693 | (1+ (current-column)) | ||
| 694 | (current-column))))) | ||
| 695 | |||
| 696 | |||
| 697 | (defun c-backward-to-noncomment (lim) | ||
| 698 | (let (opoint stop) | ||
| 699 | (while (not stop) | ||
| 700 | (skip-chars-backward " \t\n\f" lim) | ||
| 701 | (setq opoint (point)) | ||
| 702 | (if (and (>= (point) (+ 2 lim)) | ||
| 703 | (save-excursion | ||
| 704 | (forward-char -2) | ||
| 705 | (looking-at "\\*/"))) | ||
| 706 | (search-backward "/*" lim 'move) | ||
| 707 | (setq stop (or (<= (point) lim) | ||
| 708 | (save-excursion | ||
| 709 | (beginning-of-line) | ||
| 710 | (skip-chars-forward " \t") | ||
| 711 | (not (looking-at "#"))))) | ||
| 712 | (or stop (beginning-of-line)))))) | ||
| 713 | |||
| 714 | (defun c-backward-to-start-of-continued-exp (lim) | ||
| 715 | (if (memq (preceding-char) '(?\) ?\")) | ||
| 716 | (forward-sexp -1)) | ||
| 717 | (beginning-of-line) | ||
| 718 | (if (<= (point) lim) | ||
| 719 | (goto-char (1+ lim))) | ||
| 720 | (skip-chars-forward " \t")) | ||
| 721 | |||
| 722 | (defun c-backward-to-start-of-if (&optional limit) | ||
| 723 | "Move to the start of the last \"unbalanced\" `if'." | ||
| 724 | (or limit (setq limit (save-excursion (beginning-of-defun) (point)))) | ||
| 725 | (let ((if-level 1) | ||
| 726 | (case-fold-search nil)) | ||
| 727 | (while (and (not (bobp)) (not (zerop if-level))) | ||
| 728 | (backward-sexp 1) | ||
| 729 | (cond ((looking-at "else\\b") | ||
| 730 | (setq if-level (1+ if-level))) | ||
| 731 | ((looking-at "if\\b") | ||
| 732 | (setq if-level (1- if-level))) | ||
| 733 | ((< (point) limit) | ||
| 734 | (setq if-level 0) | ||
| 735 | (goto-char limit)))))) | ||
| 736 | |||
| 737 | (defun c-backward-to-start-of-do (&optional limit) | ||
| 738 | "If point follows a `do' statement, move to beginning of it and return t. | ||
| 739 | Otherwise return nil and don't move point." | ||
| 740 | (or limit (setq limit (save-excursion (beginning-of-defun) (point)))) | ||
| 741 | (let ((first t) | ||
| 742 | (startpos (point)) | ||
| 743 | (done nil)) | ||
| 744 | (while (not done) | ||
| 745 | (let ((next-start (point))) | ||
| 746 | (condition-case nil | ||
| 747 | ;; Move back one token or one brace or paren group. | ||
| 748 | (backward-sexp 1) | ||
| 749 | ;; If we find an open-brace, we lose. | ||
| 750 | (error (setq done 'fail))) | ||
| 751 | (if done | ||
| 752 | nil | ||
| 753 | ;; If we reached a `do', we win. | ||
| 754 | (if (looking-at "do\\b") | ||
| 755 | (setq done 'succeed) | ||
| 756 | ;; Otherwise, if we skipped a semicolon, we lose. | ||
| 757 | ;; (Exception: we can skip one semicolon before getting | ||
| 758 | ;; to a the last token of the statement, unless that token | ||
| 759 | ;; is a close brace.) | ||
| 760 | (if (save-excursion | ||
| 761 | (forward-sexp 1) | ||
| 762 | (or (and (not first) (= (preceding-char) ?})) | ||
| 763 | (search-forward ";" next-start t | ||
| 764 | (if (and first | ||
| 765 | (/= (preceding-char) ?})) | ||
| 766 | 2 1)))) | ||
| 767 | (setq done 'fail) | ||
| 768 | (setq first nil) | ||
| 769 | ;; If we go too far back in the buffer, we lose. | ||
| 770 | (if (< (point) limit) | ||
| 771 | (setq done 'fail))))))) | ||
| 772 | (if (eq done 'succeed) | ||
| 773 | t | ||
| 774 | (goto-char startpos) | ||
| 775 | nil))) | ||
| 776 | |||
| 777 | (defun c-beginning-of-statement (count) | ||
| 778 | "Go to the beginning of the innermost C statement. | ||
| 779 | With prefix arg, go back N - 1 statements. If already at the beginning of a | ||
| 780 | statement then go to the beginning of the preceeding one." | ||
| 781 | (interactive "p") | ||
| 782 | (while (> count 0) | ||
| 783 | (c-beginning-of-statement-1) | ||
| 784 | (setq count (1- count))) | ||
| 785 | (while (< count 0) | ||
| 786 | (c-end-of-statement-1) | ||
| 787 | (setq count (1+ count)))) | ||
| 788 | |||
| 789 | (defun c-end-of-statement (count) | ||
| 790 | "Go to the end of the innermost C statement. | ||
| 791 | With prefix arg, go forward N - 1 statements. Moves forward to end of the | ||
| 792 | next statement if already at end." | ||
| 793 | (interactive "p") | ||
| 794 | (c-beginning-of-statement (- count))) | ||
| 795 | |||
| 796 | (defun c-beginning-of-statement-1 () | ||
| 797 | (let ((last-begin (point)) | ||
| 798 | (first t)) | ||
| 799 | (condition-case () | ||
| 800 | (progn | ||
| 801 | (while (and (not (bobp)) | ||
| 802 | (progn | ||
| 803 | (backward-sexp 1) | ||
| 804 | (or first | ||
| 805 | (not (re-search-forward "[;{}]" last-begin t))))) | ||
| 806 | (setq last-begin (point) first nil)) | ||
| 807 | (goto-char last-begin)) | ||
| 808 | (error (if first (backward-up-list 1) (goto-char last-begin)))))) | ||
| 809 | |||
| 810 | (defun c-end-of-statement-1 () | ||
| 811 | (condition-case () | ||
| 812 | (progn | ||
| 813 | (while (and (not (eobp)) | ||
| 814 | (let ((beg (point))) | ||
| 815 | (forward-sexp 1) | ||
| 816 | (let ((end (point))) | ||
| 817 | (save-excursion | ||
| 818 | (goto-char beg) | ||
| 819 | (not (re-search-forward "[;{}]" end t))))))) | ||
| 820 | (re-search-backward "[;}]") | ||
| 821 | (forward-char 1)) | ||
| 822 | (error | ||
| 823 | (let ((beg (point))) | ||
| 824 | (backward-up-list -1) | ||
| 825 | (let ((end (point))) | ||
| 826 | (goto-char beg) | ||
| 827 | (search-forward ";" end 'move)))))) | ||
| 828 | |||
| 829 | (defun mark-c-function () | ||
| 830 | "Put mark at end of C function, point at beginning." | ||
| 831 | (interactive) | ||
| 832 | (push-mark (point)) | ||
| 833 | (end-of-defun) | ||
| 834 | (push-mark (point)) | ||
| 835 | (beginning-of-defun) | ||
| 836 | (backward-paragraph)) | ||
| 837 | |||
| 838 | (defun indent-c-exp (&optional endpos) | ||
| 839 | "Indent each line of the C grouping following point. | ||
| 840 | If optional arg ENDPOS is given, indent each line, stopping when | ||
| 841 | ENDPOS is encountered." | ||
| 842 | (interactive) | ||
| 843 | (let* ((indent-stack (list nil)) | ||
| 844 | (opoint (point)) ;; May be altered below. | ||
| 845 | (contain-stack | ||
| 846 | (list (if endpos | ||
| 847 | (let (funbeg) | ||
| 848 | ;; Find previous fcn-start. | ||
| 849 | (save-excursion (forward-char 1) | ||
| 850 | (beginning-of-defun) | ||
| 851 | (setq funbeg (point))) | ||
| 852 | ;; Try to find containing open, | ||
| 853 | ;; but don't scan past that fcn-start. | ||
| 854 | (save-restriction | ||
| 855 | (narrow-to-region funbeg (point)) | ||
| 856 | (condition-case nil | ||
| 857 | (save-excursion | ||
| 858 | (backward-up-list 1) (point)) | ||
| 859 | ;; We gave up: must be between fcns. | ||
| 860 | ;; Set opoint to beg of prev fcn | ||
| 861 | ;; since otherwise calculate-c-indent | ||
| 862 | ;; will get wrong answers. | ||
| 863 | (error (setq opoint funbeg) | ||
| 864 | (point))))) | ||
| 865 | (point)))) | ||
| 866 | (case-fold-search nil) | ||
| 867 | restart outer-loop-done inner-loop-done state ostate | ||
| 868 | this-indent last-sexp | ||
| 869 | at-else at-brace at-while | ||
| 870 | last-depth | ||
| 871 | (next-depth 0)) | ||
| 872 | ;; If the braces don't match, get an error right away. | ||
| 873 | (save-excursion | ||
| 874 | (forward-sexp 1)) | ||
| 875 | ;; Realign the comment on the first line, even though we don't reindent it. | ||
| 876 | (save-excursion | ||
| 877 | (let ((beg (point))) | ||
| 878 | (and (re-search-forward | ||
| 879 | comment-start-skip | ||
| 880 | (save-excursion (end-of-line) (point)) t) | ||
| 881 | ;; Make sure the comment starter we found | ||
| 882 | ;; is not actually in a string or quoted. | ||
| 883 | (let ((new-state | ||
| 884 | (parse-partial-sexp beg (point) | ||
| 885 | nil nil state))) | ||
| 886 | (and (not (nth 3 new-state)) (not (nth 5 new-state)))) | ||
| 887 | (progn (indent-for-comment) (beginning-of-line))))) | ||
| 888 | (save-excursion | ||
| 889 | (setq outer-loop-done nil) | ||
| 890 | (while (and (not (eobp)) | ||
| 891 | (if endpos (< (point) endpos) | ||
| 892 | (not outer-loop-done))) | ||
| 893 | (setq last-depth next-depth) | ||
| 894 | ;; Compute how depth changes over this line | ||
| 895 | ;; plus enough other lines to get to one that | ||
| 896 | ;; does not end inside a comment or string. | ||
| 897 | ;; Meanwhile, do appropriate indentation on comment lines. | ||
| 898 | (setq inner-loop-done nil) | ||
| 899 | (while (and (not inner-loop-done) | ||
| 900 | (not (and (eobp) (setq outer-loop-done t)))) | ||
| 901 | (setq ostate state) | ||
| 902 | (setq state (parse-partial-sexp (point) (progn (end-of-line) (point)) | ||
| 903 | nil nil state)) | ||
| 904 | (setq next-depth (car state)) | ||
| 905 | (if (and (car (cdr (cdr state))) | ||
| 906 | (>= (car (cdr (cdr state))) 0)) | ||
| 907 | (setq last-sexp (car (cdr (cdr state))))) | ||
| 908 | (if (or (nth 4 ostate)) | ||
| 909 | (c-indent-line)) | ||
| 910 | (if (or (nth 3 state)) | ||
| 911 | (forward-line 1) | ||
| 912 | (setq inner-loop-done t))) | ||
| 913 | (and endpos | ||
| 914 | (while (< next-depth 0) | ||
| 915 | (setq indent-stack (append indent-stack (list nil))) | ||
| 916 | (setq contain-stack (append contain-stack (list nil))) | ||
| 917 | (setq next-depth (1+ next-depth)) | ||
| 918 | (setq last-depth (1+ last-depth)) | ||
| 919 | (setcar (nthcdr 6 state) (1+ (nth 6 state))))) | ||
| 920 | (setq outer-loop-done (and (not endpos) (<= next-depth 0))) | ||
| 921 | (if outer-loop-done | ||
| 922 | nil | ||
| 923 | ;; If this line had ..))) (((.. in it, pop out of the levels | ||
| 924 | ;; that ended anywhere in this line, even if the final depth | ||
| 925 | ;; doesn't indicate that they ended. | ||
| 926 | (while (> last-depth (nth 6 state)) | ||
| 927 | (setq indent-stack (cdr indent-stack) | ||
| 928 | contain-stack (cdr contain-stack) | ||
| 929 | last-depth (1- last-depth))) | ||
| 930 | (if (/= last-depth next-depth) | ||
| 931 | (setq last-sexp nil)) | ||
| 932 | ;; Add levels for any parens that were started in this line. | ||
| 933 | (while (< last-depth next-depth) | ||
| 934 | (setq indent-stack (cons nil indent-stack) | ||
| 935 | contain-stack (cons nil contain-stack) | ||
| 936 | last-depth (1+ last-depth))) | ||
| 937 | (if (null (car contain-stack)) | ||
| 938 | (setcar contain-stack (or (car (cdr state)) | ||
| 939 | (save-excursion (forward-sexp -1) | ||
| 940 | (point))))) | ||
| 941 | (forward-line 1) | ||
| 942 | (skip-chars-forward " \t") | ||
| 943 | (if (eolp) | ||
| 944 | nil | ||
| 945 | (if (and (car indent-stack) | ||
| 946 | (>= (car indent-stack) 0)) | ||
| 947 | ;; Line is on an existing nesting level. | ||
| 948 | ;; Lines inside parens are handled specially. | ||
| 949 | (if (/= (char-after (car contain-stack)) ?{) | ||
| 950 | (setq this-indent (car indent-stack)) | ||
| 951 | ;; Line is at statement level. | ||
| 952 | ;; Is it a new statement? Is it an else? | ||
| 953 | ;; Find last non-comment character before this line | ||
| 954 | (save-excursion | ||
| 955 | (setq at-else (looking-at "else\\W")) | ||
| 956 | (setq at-brace (= (following-char) ?{)) | ||
| 957 | (setq at-while (looking-at "while\\b")) | ||
| 958 | (c-backward-to-noncomment opoint) | ||
| 959 | (if (not (memq (preceding-char) '(nil ?\, ?\; ?} ?: ?{))) | ||
| 960 | ;; Preceding line did not end in comma or semi; | ||
| 961 | ;; indent this line c-continued-statement-offset | ||
| 962 | ;; more than previous. | ||
| 963 | (progn | ||
| 964 | (c-backward-to-start-of-continued-exp (car contain-stack)) | ||
| 965 | (setq this-indent | ||
| 966 | (+ c-continued-statement-offset (current-column) | ||
| 967 | (if at-brace c-continued-brace-offset 0)))) | ||
| 968 | ;; Preceding line ended in comma or semi; | ||
| 969 | ;; use the standard indent for this level. | ||
| 970 | (cond (at-else (progn (c-backward-to-start-of-if opoint) | ||
| 971 | (setq this-indent | ||
| 972 | (current-indentation)))) | ||
| 973 | ((and at-while (c-backward-to-start-of-do opoint)) | ||
| 974 | (setq this-indent (current-indentation))) | ||
| 975 | (t (setq this-indent (car indent-stack))))))) | ||
| 976 | ;; Just started a new nesting level. | ||
| 977 | ;; Compute the standard indent for this level. | ||
| 978 | (let ((val (calculate-c-indent | ||
| 979 | (if (car indent-stack) | ||
| 980 | (- (car indent-stack)) | ||
| 981 | opoint)))) | ||
| 982 | (setcar indent-stack | ||
| 983 | (setq this-indent val)))) | ||
| 984 | ;; Adjust line indentation according to its contents | ||
| 985 | (if (or (looking-at "case[ \t'/(]\\|default\\>") | ||
| 986 | (and (looking-at "[A-Za-z]") | ||
| 987 | (save-excursion | ||
| 988 | (forward-sexp 1) | ||
| 989 | (looking-at ":")))) | ||
| 990 | (setq this-indent (max 1 (+ this-indent c-label-offset)))) | ||
| 991 | (if (= (following-char) ?}) | ||
| 992 | (setq this-indent (- this-indent c-indent-level))) | ||
| 993 | (if (= (following-char) ?{) | ||
| 994 | (setq this-indent (+ this-indent c-brace-offset))) | ||
| 995 | ;; Don't leave indentation in empty lines. | ||
| 996 | (if (eolp) (setq this-indent 0)) | ||
| 997 | ;; Put chosen indentation into effect. | ||
| 998 | (or (= (current-column) this-indent) | ||
| 999 | (= (following-char) ?\#) | ||
| 1000 | (progn | ||
| 1001 | (delete-region (point) (progn (beginning-of-line) (point))) | ||
| 1002 | (indent-to this-indent))) | ||
| 1003 | ;; Indent any comment following the text. | ||
| 1004 | (or (looking-at comment-start-skip) | ||
| 1005 | (let ((beg (point))) | ||
| 1006 | (and (re-search-forward | ||
| 1007 | comment-start-skip | ||
| 1008 | (save-excursion (end-of-line) (point)) t) | ||
| 1009 | ;; Make sure the comment starter we found | ||
| 1010 | ;; is not actually in a string or quoted. | ||
| 1011 | (let ((new-state | ||
| 1012 | (parse-partial-sexp beg (point) | ||
| 1013 | nil nil state))) | ||
| 1014 | (and (not (nth 3 new-state)) (not (nth 5 new-state)))) | ||
| 1015 | (progn (indent-for-comment) (beginning-of-line))))))))))) | ||
| 1016 | |||
| 1017 | ;; Look at all comment-start strings in the current line after point. | ||
| 1018 | ;; Return t if one of them starts a real comment. | ||
| 1019 | ;; This is not used yet, because indent-for-comment | ||
| 1020 | ;; isn't smart enough to handle the cases this can find. | ||
| 1021 | (defun indent-c-find-real-comment () | ||
| 1022 | (let (win) | ||
| 1023 | (while (and (not win) | ||
| 1024 | (re-search-forward comment-start-skip | ||
| 1025 | (save-excursion (end-of-line) (point)) | ||
| 1026 | t)) | ||
| 1027 | ;; Make sure the comment start is not quoted. | ||
| 1028 | (let ((state-1 | ||
| 1029 | (parse-partial-sexp | ||
| 1030 | (save-excursion (beginning-of-line) (point)) | ||
| 1031 | (point) nil nil state))) | ||
| 1032 | (setq win (and (null (nth 3 state-1)) (null (nth 5 state-1)))))) | ||
| 1033 | win)) | ||
| 1034 | |||
| 1035 | ;; Indent every line whose first char is between START and END inclusive. | ||
| 1036 | (defun c-indent-region (start end) | ||
| 1037 | (save-excursion | ||
| 1038 | (goto-char start) | ||
| 1039 | (let ((endmark (copy-marker end))) | ||
| 1040 | (and (bolp) (not (eolp)) | ||
| 1041 | (c-indent-line)) | ||
| 1042 | (indent-c-exp endmark) | ||
| 1043 | (set-marker endmark nil)))) | ||
| 1044 | |||
| 1045 | (defun set-c-style (style) | ||
| 1046 | "Set C-mode variables to use one of several different indentation styles. | ||
| 1047 | Takes one argument, a string representing the desired style. | ||
| 1048 | Available styles are GNU, K&R, BSD and Whitesmith." | ||
| 1049 | (interactive (list (completing-read "Use which C indentation style? " | ||
| 1050 | c-style-alist nil t))) | ||
| 1051 | (let ((vars (cdr (assoc style c-style-alist)))) | ||
| 1052 | (if vars | ||
| 1053 | (if (interactive-p) (message "Using %s C indentation style" style)) | ||
| 1054 | (error "Bogus style type, \"%s\"" style)) | ||
| 1055 | (while vars | ||
| 1056 | (set (car (car vars)) (cdr (car vars))) | ||
| 1057 | (setq vars (cdr vars))))) | ||