comparison lisp/modes/old-c++-mode.el @ 0:376386a54a3c r19-14

Import from CVS: tag r19-14
author cvs
date Mon, 13 Aug 2007 08:45:50 +0200
parents
children 0293115a14e9
comparison
equal deleted inserted replaced
-1:000000000000 0:376386a54a3c
1 ;;; c++-mode.el --- major mode for editing C++ (and C) code
2
3 ;; Author: 1992 Barry A. Warsaw, Century Computing Inc. <bwarsaw@cen.com>
4 ;; 1987 Dave Detlefs and Stewart Clamen
5 ;; 1985 Richard M. Stallman
6 ;; Maintainer: c++-mode-help@anthem.nlm.nih.gov
7 ;; Created: a long, long, time ago. adapted from the original c-mode.el
8 ;; Version: 2.353
9 ;; Last Modified: 1993/06/23 13:58:52
10 ;; Keywords: c
11
12 ;; Copyright (C) 1992, 1993 Free Software Foundation, Inc.
13
14 ;; This file is part of XEmacs.
15
16 ;; XEmacs is free software; you can redistribute it and/or modify it
17 ;; under the terms of the GNU General Public License as published by
18 ;; the Free Software Foundation; either version 2, or (at your option)
19 ;; any later version.
20
21 ;; XEmacs is distributed in the hope that it will be useful, but
22 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
23 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 ;; General Public License for more details.
25
26 ;; You should have received a copy of the GNU General Public License
27 ;; along with XEmacs; see the file COPYING. If not, write to the Free
28 ;; Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
29
30 ;; Introduction
31 ;; ============
32 ;; Do a "C-h m" in a c++-mode buffer for more information on
33 ;; customizing c++-mode. To submit bug reports hit "C-c C-b" in a
34 ;; c++-mode buffer. This runs the command c++-submit-bug-report and
35 ;; automatically sets up the mail buffer with all the necessary
36 ;; information. If you have other questions contact me at the
37 ;; following address: c++-mode-help@anthem.nlm.nih.gov. Please don't
38 ;; send bug reports to my personal account, I may not get it for a
39 ;; long time.
40
41 ;; Notes for Novice Users
42 ;; ======================
43 ;; c++-mode facilitates editing of C++ code by automatically handling
44 ;; the indentation of lines of code in a manner very similar to c-mode
45 ;; as distributed with GNU Emacs. Refer to the GNU Emacs manual,
46 ;; chapter 21 for more information on "Editing Programs". In fact,
47 ;; c++-mode (through its companion mode entry point c++-c-mode) can
48 ;; also be used to edit both K&R and ANSI C code!
49 ;;
50 ;; To use c++-mode, add the following to your .emacs file. This
51 ;; assumes you will use .cc or .C extensions for your C++ source:
52 ;;
53 ;; (autoload 'c++-mode "c++-mode" "C++ Editing Mode" t)
54 ;; (autoload 'c++-c-mode "c++-mode" "C Editing Mode" t)
55 ;; (setq auto-mode-alist
56 ;; (append '(("\\.C$" . c++-mode)
57 ;; ("\\.cc$" . c++-mode)
58 ;; ("\\.c$" . c++-c-mode) ; to edit C code
59 ;; ("\\.h$" . c++-c-mode) ; to edit C code
60 ;; ) auto-mode-alist))
61 ;;
62 ;; If you want to use the default c-mode for editing C code, then just
63 ;; omit the lines marked "to edit C code".
64 ;;
65 ;; Finally, you may want to customize certain c++-mode variables. The
66 ;; best place to do this is in the mode hook variable called
67 ;; c++-mode-hook. Again, see the Emacs manual, chapter 21 for more
68 ;; information.
69
70 ;; Important Note about Escapes in Comments, and Performance
71 ;; =========================================================
72 ;; You may notice that certain characters, when typed in comment
73 ;; regions, get escaped with a backslash. This is a workaround for
74 ;; bugs in Emacs' syntax parsing algorithms. In brief, syntax parsing
75 ;; in Emacs 18 and derivatives is broken because syntax tables are not
76 ;; rich enough to support more than 1 comment style per mode (as C++
77 ;; requires). The result is that Emacs will sometimes choke on
78 ;; unbalanced parentheses and single quotes in comments. Please do a
79 ;; "C-h v c++-untame-characters" for more information.
80 ;;
81 ;; This problem affect both the accuracy and performance of c++-mode
82 ;; because some parsing must be performed in Emacs lisp instead of
83 ;; relying on the C primitives. In general, I've chosen accuracy over
84 ;; performance, but have worked hard to give moderately acceptable
85 ;; speed in all but the most uncommon situations. You will most likely
86 ;; notice c++-mode slowing when you're editing a file of preprocessor
87 ;; commands, or inside long functions or class definitions.
88 ;; Optimization is an ongoing concern, but the real solution is to fix
89 ;; Emacs.
90 ;;
91 ;; As of release 19.4, Lucid Emacs is distributed with the fixes in
92 ;; place, and c++-mode will automatically take advantage of them so
93 ;; none of the above applies to you. Similar patches will be part of
94 ;; FSF GNU Emacs 19. Some patches for GNU Emacs 18 have been released
95 ;; on the beta site, but they are unsupported. Email for more
96 ;; information.
97
98 ;; Beta Testers Mailing List
99 ;; =========================
100 ;; Want to be a c++-mode victim, er, beta-tester? Send add/drop
101 ;; requests to c++-mode-victims-request@anthem.nlm.nih.gov.
102 ;; Discussions go to c++-mode-victims@anthem.nlm.nih.gov, but bug
103 ;; reports and such should still be sent to c++-mode-help only.
104 ;;
105 ;; Many, many thanks go out to all the folks on the beta test list.
106 ;; Without their patience, testing, insight, and code contribution,
107 ;; c++-mode.el would be a far inferior package.
108
109 ;; Getting c++-mode.el
110 ;; ===================
111 ;; The latest public release version of this file should always be
112 ;; available for anonymous ftp on the Emacs lisp archive machine. The
113 ;; path to the file is:
114 ;;
115 ;; archive.cis.ohio-state.edu:pub/gnu/emacs/elisp-archive/modes/c++-mode.el.Z
116 ;;
117 ;; For those of you without anon-ftp access, you can use the DEC's
118 ;; ftpmail'er at the address ftpmail@decwrl.dec.com. Send the
119 ;; following message in the body of your mail to that address to get
120 ;; c++-mode:
121 ;;
122 ;; reply <a valid net address back to you>
123 ;; connect archive.cis.ohio-state.edu
124 ;; binary
125 ;; uuencode
126 ;; chdir pub/gnu/emacs/elisp-archive/modes
127 ;; get c++-mode.el.Z
128 ;;
129 ;; or just send the message "help" for more information on ftpmail.
130 ;; Response times will vary with the number of requests in the queue.
131
132 ;; LCD Archive Entry:
133 ;; c++-mode|Barry A. Warsaw|c++-mode-help@anthem.nlm.nih.gov
134 ;; |Mode for editing C++, and ANSI/K&R C code (was Detlefs' c++-mode.el)
135 ;; |1993/06/23 13:58:52|2.353|
136
137 ;;; Code:
138
139 ;; some people may not have c-mode loaded in by default. c++-mode.el
140 ;; unfortunately still depends on distrib c-mode. c-mode doesn't
141 ;; provide itself so this hack is best known way to ensure its loaded
142 (or (fboundp 'c-mode)
143 (load "c-mode" nil t))
144
145
146 ;; ======================================================================
147 ;; user definable variables
148 ;; vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
149
150 (defconst c++-emacs-features
151 (let ((mse-spec 'no-dual-comments)
152 (scanner 'v18))
153 ;; vanilla GNU18/Epoch 4 uses default values
154 (if (= 8 (length (parse-partial-sexp (point) (point))))
155 ;; we know we're using v19 style dual-comment specifications.
156 ;; All Lemacsen use 8-bit modify-syntax-entry flags, as do all
157 ;; patched FSF19, GNU18, Epoch4's. Only vanilla FSF19 uses
158 ;; 1-bit flag. Lets be as smart as we can about figuring this
159 ;; out.
160 (let ((table (copy-syntax-table)))
161 (modify-syntax-entry ?a ". 12345678" table)
162 (if (= (logand (lsh (aref table ?a) -16) 255) 255)
163 (setq mse-spec '8-bit)
164 (setq mse-spec '1-bit))
165 ;; we also know we're using a quicker, built-in comment
166 ;; scanner, but we don't know if its old-style or new.
167 ;; Fortunately we can ask emacs directly
168 (if (fboundp 'forward-comment)
169 (setq scanner 'v19)
170 (setq scanner 'old-v19))))
171 ;; now cobble up the necessary list
172 (list mse-spec scanner))
173 "A list of needed features extant in the Emacs you are using.
174 There are many flavors of Emacs out on the net, each with different
175 features supporting those needed by c++-mode. Here's the current
176 known list, along with the values for this variable:
177
178 Vanilla GNU 18/Epoch 4: (no-dual-comments v18)
179 GNU 18/Epoch 4 (patch1): (8-bit old-v19)
180 GNU 18/Epoch 4 (patch2): (8-bit v19)
181 Lemacs 19.4 - 19.7: (8-bit old-v19)
182 Lemacs 19.8 and over: (8-bit v19)
183 FSF 19: (1-bit v19)
184 FSF 19 (patched): (8-bit v19)")
185
186 (defvar c++-mode-abbrev-table nil
187 "Abbrev table in use in c++-mode buffers.")
188 (define-abbrev-table 'c++-mode-abbrev-table ())
189
190 (defvar c++-mode-map ()
191 "Keymap used in c++-mode.")
192 (if c++-mode-map
193 ()
194 (setq c++-mode-map (make-sparse-keymap))
195 (define-key c++-mode-map "\C-j" 'reindent-then-newline-and-indent)
196 (define-key c++-mode-map "\C-m" 'newline-and-indent)
197 (define-key c++-mode-map "{" 'c++-electric-brace)
198 (define-key c++-mode-map "}" 'c++-electric-brace)
199 (define-key c++-mode-map ";" 'c++-electric-semi)
200 (define-key c++-mode-map "#" 'c++-electric-pound)
201 (define-key c++-mode-map "\e\C-h" 'mark-c-function)
202 (define-key c++-mode-map "\e\C-q" 'c++-indent-exp)
203 (define-key c++-mode-map "\t" 'c++-indent-command)
204 (define-key c++-mode-map "\C-c\C-i" 'c++-insert-header)
205 (define-key c++-mode-map "\C-c\C-\\" 'c++-macroize-region)
206 (define-key c++-mode-map "\C-c\C-c" 'c++-comment-region)
207 (define-key c++-mode-map "\C-c\C-u" 'c++-uncomment-region)
208 (define-key c++-mode-map "\C-c\C-x" 'c++-match-paren)
209 (define-key c++-mode-map "\e\C-a" 'c++-beginning-of-defun)
210 (define-key c++-mode-map "\e\C-e" 'c++-end-of-defun)
211 (define-key c++-mode-map "\e\C-x" 'c++-indent-defun)
212 (define-key c++-mode-map "/" 'c++-electric-slash)
213 (define-key c++-mode-map "*" 'c++-electric-star)
214 (define-key c++-mode-map ":" 'c++-electric-colon)
215 (define-key c++-mode-map "\177" 'c++-electric-delete)
216 (define-key c++-mode-map "\C-c\C-t" 'c++-toggle-auto-hungry-state)
217 (define-key c++-mode-map "\C-c\C-h" 'c++-toggle-hungry-state)
218 (define-key c++-mode-map "\C-c\C-a" 'c++-toggle-auto-state)
219 (if (memq 'v18 c++-emacs-features)
220 (progn
221 (define-key c++-mode-map "\C-c'" 'c++-tame-comments)
222 (define-key c++-mode-map "'" 'c++-tame-insert)
223 (define-key c++-mode-map "[" 'c++-tame-insert)
224 (define-key c++-mode-map "]" 'c++-tame-insert)
225 (define-key c++-mode-map "(" 'c++-tame-insert)
226 (define-key c++-mode-map ")" 'c++-tame-insert)))
227 (define-key c++-mode-map "\C-c\C-b" 'c++-submit-bug-report)
228 (define-key c++-mode-map "\C-c\C-v" 'c++-version)
229 ;; these are necessary because default forward-sexp and
230 ;; backward-sexp don't automatically let-bind
231 ;; parse-sexp-ignore-comments, which is needed for them to work
232 ;; properly in a C++ buffer.
233 (define-key c++-mode-map "\e\C-f" 'c++-forward-sexp)
234 (define-key c++-mode-map "\e\C-b" 'c++-backward-sexp)
235 )
236
237 (defvar c++-mode-syntax-table nil
238 "Syntax table used in c++-mode buffers.")
239 (defvar c++-c-mode-syntax-table nil
240 "Syntax table used in c++-c-mode buffers.")
241
242 (if c++-mode-syntax-table
243 ()
244 (setq c++-mode-syntax-table (make-syntax-table))
245 (modify-syntax-entry ?\\ "\\" c++-mode-syntax-table)
246 (modify-syntax-entry ?+ "." c++-mode-syntax-table)
247 (modify-syntax-entry ?- "." c++-mode-syntax-table)
248 (modify-syntax-entry ?= "." c++-mode-syntax-table)
249 (modify-syntax-entry ?% "." c++-mode-syntax-table)
250 (modify-syntax-entry ?< "." c++-mode-syntax-table)
251 (modify-syntax-entry ?> "." c++-mode-syntax-table)
252 (modify-syntax-entry ?& "." c++-mode-syntax-table)
253 (modify-syntax-entry ?| "." c++-mode-syntax-table)
254 (modify-syntax-entry ?\' "\"" c++-mode-syntax-table)
255 ;; comment syntax
256 (cond
257 ((memq '8-bit c++-emacs-features)
258 ;; Lucid emacs has the best implementation
259 (modify-syntax-entry ?/ ". 1456" c++-mode-syntax-table)
260 (modify-syntax-entry ?* ". 23" c++-mode-syntax-table)
261 (modify-syntax-entry ?\n "> b" c++-mode-syntax-table))
262 ((memq '1-bit c++-emacs-features)
263 ;; FSF19 has sub-optimal, but workable implementation
264 ;; Some strange behavior may be encountered. LOBBY FSF!
265 (modify-syntax-entry ?/ ". 124" c++-mode-syntax-table)
266 (modify-syntax-entry ?* ". 23b" c++-mode-syntax-table)
267 (modify-syntax-entry ?\n ">" c++-mode-syntax-table))
268 (t
269 ;; Vanilla GNU18 is just plain busted. We'll do the best we can,
270 ;; but some strange behavior may be encountered. PATCH or UPGRADE!
271 (modify-syntax-entry ?/ ". 124" c++-mode-syntax-table)
272 (modify-syntax-entry ?* ". 23" c++-mode-syntax-table)
273 (modify-syntax-entry ?\n ">" c++-mode-syntax-table))
274 ))
275
276 (if c++-c-mode-syntax-table
277 ()
278 (setq c++-c-mode-syntax-table (make-syntax-table))
279 (modify-syntax-entry ?\\ "\\" c++-c-mode-syntax-table)
280 (modify-syntax-entry ?+ "." c++-c-mode-syntax-table)
281 (modify-syntax-entry ?- "." c++-c-mode-syntax-table)
282 (modify-syntax-entry ?= "." c++-c-mode-syntax-table)
283 (modify-syntax-entry ?% "." c++-c-mode-syntax-table)
284 (modify-syntax-entry ?< "." c++-c-mode-syntax-table)
285 (modify-syntax-entry ?> "." c++-c-mode-syntax-table)
286 (modify-syntax-entry ?& "." c++-c-mode-syntax-table)
287 (modify-syntax-entry ?| "." c++-c-mode-syntax-table)
288 (modify-syntax-entry ?\' "\"" c++-c-mode-syntax-table)
289 (modify-syntax-entry ?/ ". 14" c++-c-mode-syntax-table)
290 (modify-syntax-entry ?* ". 23" c++-c-mode-syntax-table)
291 )
292
293 (defvar c++-tab-always-indent
294 (if (boundp 'c-tab-always-indent) c-tab-always-indent t)
295 "*Controls the operation of the TAB key.
296 If t (the default), always just indent the current line. If nil,
297 indent the current line only if point is at the left margin or in the
298 line's indentation; otherwise insert a tab. If not-nil-or-t, then tab
299 is inserted only within literals (comments and strings) and inside
300 preprocessor directives, but line is always reindented.")
301 (defvar c++-always-arglist-indent-p nil
302 "*Control indentation of continued arglists.
303 When non-nil, arglists continued on subsequent lines will always
304 indent `c++-empty-arglist-indent' spaces, otherwise, they will indent to
305 just under previous line's argument indentation.")
306 (defvar c++-block-close-brace-offset 0
307 "*Extra indentation given to close braces which close a block.
308 This variable can be either an integer or a list. If an integer, it
309 describes the extra offset given a block closing brace (and a closing
310 paren if `c++-paren-as-block-close-p' is non-nil), treating all
311 closing parens the same. If a list of the form (OTHERS . TOPLEVEL),
312 OTHERS is an integer describing the offset given to all but top-level
313 (e.g. function) closing braces, while TOPLEVEL is an integer
314 describing offset given only to braces which close top-level
315 constructs.")
316 (defvar c++-paren-as-block-close-p nil
317 "*Treat a parenthesis which is the first non-whitespace on a line as
318 a paren which closes a block. When non-nil, `c-indent-level' is
319 subtracted, and `c++-block-close-brace-offset' is added to the line's
320 offset.")
321 (defvar c++-continued-member-init-offset nil
322 "*Extra indent for continuation lines of member inits; nil means to align
323 with previous initializations rather than with the colon on the first line.")
324 (defvar c++-member-init-indent 0
325 "*Indentation level of member initializations in function declarations.")
326 (defvar c++-friend-offset -4
327 "*Offset of C++ friend class declarations relative to member declarations.")
328 (defvar c++-access-specifier-offset c-label-offset
329 "*Extra indentation given to public, protected, and private labels.")
330 (defvar c++-empty-arglist-indent nil
331 "*Indicates how far to indent a line following an empty argument list.
332 Nil means indent to just after the paren.")
333 (defvar c++-comment-only-line-offset 0
334 "*Indentation offset for line which contains only C or C++ style comments.
335 This variable can take either a single integer or a list of integers.
336 If a single integer this is the extra indentation offset to apply to
337 all comment-only lines, except those which start in column zero. If a
338 list is used, the first integer is for all non-column-zero
339 comment-only lines and the second integer is for all column-zero
340 lines. You can also use a list containing only 1 integer, in which
341 case, this value is used for all comment-only lines. For example:
342
343 value meaning
344 ===== =======
345 0 comment-only lines do not indent
346 4 non-col0 lines indent 4 spaces, col0 lines don't indent
347 '(4) all comment-only lines indent 4 spaces
348 '(4 1) non-col0 lines indent 4 spaces, col0 lines indent 1 space")
349
350 (defvar c++-C-block-comments-indent-p nil
351 "*4 styles of C block comments are supported. If this variable is nil,
352 then styles 1-3 are supported. If this variable is non-nil, style 4 is
353 supported.
354 style 1: style 2: style 3: style 4:
355 /* /* /* /*
356 blah * blah ** blah blah
357 blah * blah ** blah blah
358 */ */ */ */
359 ")
360 (defvar c++-cleanup-list nil
361 "*List of various C++ constructs to ``clean up''.
362 These cleanups only take place when the auto-newline feature is turned
363 on, as evidenced by the `/a' or `/ah' appearing next to the mode name.
364
365 Current legal values are:
366 `brace-else-brace' -- clean up ``} else {'' constructs by placing entire
367 construct on a single line. This cleanup only
368 takes place when there is nothing but white
369 space between the braces and the else.
370 `empty-defun-braces' -- cleans up empty C++ function braces by
371 placing them on the same line.
372 `defun-close-semi' -- cleans up the terminating semi-colon on class
373 definitions and functions by placing the semi
374 on the same line as the closing brace.")
375 (defvar c++-hanging-braces t
376 "*Controls the insertion of newlines before open (left) braces.
377 This variable only has effect when auto-newline is on, as evidenced by
378 the `/a' or `/ah' appearing next to the mode name. If nil, open
379 braces do not hang (i.e. a newline is inserted before all open
380 braces). If t, all open braces hang -- no newline is inserted before
381 open braces. If not nil or t, newlines are only inserted before
382 top-level open braces; all other braces hang.")
383 (defvar c++-hanging-member-init-colon 'before
384 "*Defines how colons which introduce member initializations are formatted.
385 Legal values are:
386 t -- no newlines inserted before or after colon
387 nil -- newlines inserted before and after colon
388 `after' -- newlines inserted only after colon
389 `before` -- newlines inserted only before colon")
390 (defvar c++-auto-hungry-initial-state 'none
391 "*Initial state of auto/hungry features when buffer is first visited.
392 Legal values are:
393 `none' -- no auto-newline and no hungry-delete-key.
394 `auto-only' -- auto-newline, but no hungry-delete-key.
395 `hungry-only' -- no auto-newline, but hungry-delete-key.
396 `auto-hungry' -- both auto-newline and hungry-delete-key enabled.
397 Nil is synonymous for `none' and t is synonymous for `auto-hungry'.")
398
399 (defvar c++-auto-hungry-toggle t
400 "*Enable/disable toggling of auto/hungry features.
401 Legal values are:
402 `none' -- auto-newline and hungry-delete-key cannot be enabled.
403 `auto-only' -- only auto-newline feature can be toggled.
404 `hungry-only' -- only hungry-delete-key feature can be toggled.
405 `auto-hungry' -- both auto-newline and hungry-delete-key can be toggled.
406 Nil is synonymous for `none' and t is synonymous for `auto-hungry'.")
407
408 (defvar c++-relative-offset-p t
409 "*Control the calculation for indentation.
410 When non-nil (the default), indentation is calculated relative to the
411 first statement in the block. When nil, the indentation is calculated
412 without regard to how the first statement is indented.")
413
414 (defvar c++-untame-characters (and (memq 'v18 c++-emacs-features) '(?\'))
415 "*Utilize a backslashing workaround of an Emacs syntax parsing bug.
416 If non-nil, this variable should contain a list of characters which
417 will be prepended by a backslash in comment regions. By default, the
418 list contains only the most troublesome character, the single quote.
419 To be completely safe, set this variable to:
420
421 '(?\( ?\) ?\' ?\{ ?\} ?\[ ?\])
422
423 This is the full list of characters which can potentially cause
424 problems if they exist unbalanced within comments. Setting this
425 variable to nil will defeat this feature, but be forewarned! Such
426 un-escaped characters in comment regions can potentially break many
427 things such as some indenting and blinking of parenthesis.
428
429 Note further that only the default set of characters will be escaped
430 automatically as they are typed. But, executing `c++-tame-comments'
431 (\\[c++-tame-comments]) will escape all characters which are members
432 of this set, and which are found in comments throughout the file.
433
434 Finally, c++-mode can tell if you're running a patched Emacs. If so,
435 taming characters isn't necessary and this variable is automatically
436 set to nil.")
437
438 (defvar c++-default-macroize-column 78
439 "*Column to insert backslashes.")
440 (defvar c++-special-indent-hook nil
441 "*Hook for user defined special indentation adjustments.
442 This hook gets called after a line is indented by the mode. By
443 supplying a hook, you can make adjustments to the line's standard
444 indentation. If you do use this hook, you will likely need to also
445 set `c++-relative-offset-p' to nil. The call to this hook is wrapped in
446 a `save-excursion' so you don't need to worry about restoring point and
447 mark inside the hook function.")
448 (defvar c++-delete-function 'backward-delete-char-untabify
449 "*Function called by `c++-electric-delete' when deleting a single char.")
450 (defvar c++-electric-pound-behavior nil
451 "*List of behaviors for electric pound insertion.
452 Only currently supported behavior is `alignleft'.")
453 (defvar c++-backscan-limit 2000
454 "*Limit in characters for looking back while skipping syntactic ws.
455 If you typically write really big methods, and start noticing
456 incorrect indentations, try cranking this value up. The larger this
457 value is, though, the slower parts of c++-mode can become. Setting
458 this variable to nil defeats backscan limits.")
459
460 ;; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
461 ;; NO USER DEFINABLE VARIABLES BEYOND THIS POINT
462 ;;
463 (defvar c++-hungry-delete-key nil
464 "Internal state of hungry delete key feature.")
465 (defvar c++-auto-newline nil
466 "Internal state of auto newline feature.")
467
468 (make-variable-buffer-local 'c++-auto-newline)
469 (make-variable-buffer-local 'c++-hungry-delete-key)
470
471 (defconst c++-access-key "\\<\\(public\\|protected\\|private\\)\\>:"
472 "Regexp which describes access specification keywords.")
473 (defconst c++-class-key
474 (concat
475 "\\(\\(extern\\|typedef\\)\\s +\\)?"
476 "\\(template\\s *<[^>]*>\\s *\\)?"
477 "\\<\\(class\\|struct\\|union\\)\\>")
478 "Regexp which describes a class declaration, including templates.")
479 (defconst c++-inher-key
480 (concat "\\(\\<static\\>\\s +\\)?"
481 c++-class-key
482 "[ \t]+\\(\\(\\w\\|_\\)+[ \t]*:[ \t]*\\)?")
483 "Regexp which describes a class inheritance declaration.")
484
485
486 ;; ======================================================================
487 ;; c++-mode main entry point
488 ;; ======================================================================
489 ;;##autoload ;; don't autoload an obsolete package
490 (defun c++-mode ()
491 "Major mode for editing C++ code. 2.353
492 To submit a problem report, enter `\\[c++-submit-bug-report]' from a
493 c++-mode buffer. This automatically sets up a mail buffer with
494 version information already added. You just need to add a description
495 of the problem and send the message.
496
497 1. Very much like editing C code,
498 2. Expression and list commands understand all C++ brackets,
499 3. Tab at left margin indents for C++ code,
500 4. Both C++ and C style block comments are recognized,
501 5. Paragraphs are separated by blank lines only,
502 6. Hungry delete key and auto newline features are optional.
503
504 IMPORTANT NOTE: You may notice that some characters (by default, only
505 single quote) will get escaped with a backslash when typed in a
506 comment region. This is a necessary workaround of a bug present in
507 GNU Emacs 18 and derivatives. Enter `\\[describe-variable] c++-untame-characters RET'
508 for more information. If you are running a patched Emacs, no
509 characters will be escaped in comment regions, and many functions will
510 run much faster.
511
512 Key bindings:
513 \\{c++-mode-map}
514
515 These variables control indentation style. Those with names like
516 c-<thing> are inherited from c-mode. Those with names like
517 c++-<thing> are unique for this mode, or have extended functionality
518 from their c-mode cousins.
519
520 c-argdecl-indent
521 Indentation level of declarations of C function arguments.
522 c-brace-imaginary-offset
523 An open brace following other text is treated as if it were
524 this far to the right of the start of its line.
525 c-brace-offset
526 Extra indentation for line if it starts with an open brace.
527 c-continued-brace-offset
528 Extra indentation given to a brace that starts a substatement.
529 This is in addition to `c-continued-statement-offset'.
530 c-continued-statement-offset
531 Extra indentation given to a substatement, such as the
532 then-clause of an if or body of a while.
533 c-indent-level
534 Indentation of C statements within surrounding block.
535 The surrounding block's indentation is the indentation
536 of the line on which the open-brace appears.
537 c-label-offset
538 Extra indentation for line that is a label, or case or ``default:''
539
540 c++-C-block-comments-indent-p
541 Style of C block comments to support.
542 c++-access-specifier-offset
543 Extra indentation given to public, protected, and private keyword lines.
544 c++-always-arglist-indent-p
545 Control indentation of continued arglists. When non-nil, arglists
546 continued on subsequent lines will always indent
547 `c++-empty-arglist-indent' spaces, otherwise, they will indent to
548 just under previous line's argument indentation.
549 c++-auto-hungry-initial-state
550 Initial state of auto/hungry feature when a C++ buffer is first visited.
551 c++-auto-hungry-toggle
552 Enable/disable toggling of auto/hungry features.
553 c++-backscan-limit
554 Limit in characters for looking back while skipping syntactic
555 whitespace. This variable is only used in an un-patched Emacs to
556 help improve performance at the expense of some accuracy. Patched
557 Emacses are both fast and accurate.
558 c++-block-close-brace-offset
559 Extra indentation give to braces which close a block.
560 c++-cleanup-list
561 A list of construct ``clean ups'' which c++-mode will perform when
562 auto-newline feature is on. Current legal values are:
563 `brace-else-brace', `empty-defun-braces', `defun-close-semi'.
564 c++-comment-only-line-offset
565 Extra indentation for a line containing only a C or C++ style
566 comment. Can be an integer or list, specifying the various styles
567 of comment-only line special indentations.
568 c++-continued-member-init-offset
569 Extra indentation for continuation lines of member initializations; nil
570 means to align with previous initializations rather than with the colon.
571 c++-default-macroize-column
572 Column to insert backslashes when macroizing a region.
573 c++-delete-function
574 Function called by `c++-electric-delete' when deleting a single char.
575 c++-electric-pound-behavior
576 List of behaviors for electric pound insertion.
577 c++-empty-arglist-indent
578 Extra indentation to apply to a line following an empty argument
579 list. nil means to line it up with the left paren.
580 c++-friend-offset
581 Offset of C++ friend class declarations relative to member declarations.
582 c++-hanging-braces
583 Controls open brace hanging behavior when using auto-newline feature.
584 nil says no braces hang, t says all open braces hang. non-nil-or-t
585 means top-level open braces don't hang, all others do.
586 c++-hanging-member-init-colon
587 Defines how colons which introduce member initialization lists are
588 formatted. t means no newlines are inserted either before or after
589 the colon. nil means newlines are inserted both before and after
590 the colon. `before' inserts newlines only before the colon, and
591 `after' inserts newlines only after colon.
592 c++-member-init-indent
593 Indentation level of member initializations in function declarations,
594 if they are on a separate line beginning with a colon.
595 c++-paren-as-block-close-p
596 If non-nil, treat a parenthesis which is the first non-whitespace
597 on a line as a paren which closes a block (i.e. treat it similar
598 to right curly brace).
599 c++-relative-offset-p
600 Control the calculation for indentation. When non-nil (the
601 default), indentation is calculated relative to the first
602 statement in the block. When nil, the indentation is calculated
603 without regard to how the first statement is indented. Useful when
604 using a `c++-special-indent-hook'.
605 c++-special-indent-hook
606 Hook for user defined special indentation adjustments. You can use
607 this hook, which gets called after a line is indented by the mode,
608 to customize indentations of the line.
609 c++-tab-always-indent
610 Controls the operation of the TAB key. t means always just indent
611 the current line. nil means indent the current line only if point
612 is at the left margin or in the line's indentation; otherwise
613 insert a tab. If not-nil-or-t, then tab is inserted only within
614 literals (comments and strings) and inside preprocessor
615 directives, but the line is always reindented. Default is value
616 for `c-tab-always-indent'.
617 c++-untame-characters
618 When non-nil, inserts backslash escapes before certain untamed
619 characters in comment regions. It is recommended that you keep the
620 default setting to workaround a nasty Emacs bug, unless you are
621 running a patched Emacs.
622
623 Auto-newlining is no longer an all or nothing proposition. In my
624 opinion, I don't believe it is possible to implement a perfect
625 auto-newline algorithm. Sometimes you want it and sometimes you don't.
626 So now auto-newline (and its companion feature, hungry-delete-key) can
627 be toggled on and off on the fly. Hungry-delete-key is the optional
628 behavior of the delete key so that, when enabled, hitting the delete
629 key once consumes all preceding whitespace, unless point is within a
630 literal (defined as a C or C++ comment, or string). Inside literals,
631 and with hungry-delete-key disabled, the delete key just calls the
632 function in variable `c++-delete-function'.
633
634 Selection and toggling of these features is controlled by the
635 variables `c++-auto-hungry-initial-state' and `c++-auto-hungry-toggle'.
636 Legal values for both variables are:
637
638 `none' (or nil) -- no auto-newline or hungry-delete-key.
639 `auto-only' -- function affects only auto-newline feature.
640 `hungry-only' -- function affects only hungry-delete-key feature.
641 `auto-hungry' (or t) -- function affects both features.
642
643 Thus if `c++-auto-hungry-initial-state' is `hungry-only', then only
644 hungry-delete-key feature is turned on when the buffer is first
645 visited. If `c++-auto-hungry-toggle' is `auto-hungry', and both
646 auto-newline and hungry-delete-key features are on, then hitting
647 `\\[c++-toggle-auto-hungry-state]' will toggle both features. Hitting
648 `\\[c++-toggle-hungry-state]' will always toggle hungry-delete-key
649 feature and hitting `\\[c++-toggle-auto-state]' will always toggle
650 auto-newline feature, regardless of the value of
651 `c++-auto-hungry-toggle'.
652
653 Settings for K&R, BSD, and Stroustrup indentation styles are
654 c-indent-level 5 8 4
655 c-continued-statement-offset 5 8 4
656 c-continued-brace-offset 0
657 c-brace-offset -5 -8 0
658 c-brace-imaginary-offset 0
659 c-argdecl-indent 0 8 4
660 c-label-offset -5 -8 -4
661 c++-access-specifier-offset -5 -8 -4
662 c++-empty-arglist-indent 4
663 c++-friend-offset 0
664
665 Turning on C++ mode calls the value of the variable `c++-mode-hook' with
666 no args, if that value is non-nil."
667 (interactive)
668 (kill-all-local-variables)
669 (use-local-map c++-mode-map)
670 (set-syntax-table c++-mode-syntax-table)
671 (setq major-mode 'c++-mode
672 mode-name "C++"
673 local-abbrev-table c++-mode-abbrev-table)
674 (set (make-local-variable 'paragraph-start) (concat "^$\\|" page-delimiter))
675 (set (make-local-variable 'paragraph-separate) paragraph-start)
676 (set (make-local-variable 'paragraph-ignore-fill-prefix) t)
677 (set (make-local-variable 'require-final-newline) t)
678 (set (make-local-variable 'parse-sexp-ignore-comments) nil)
679 ;;
680 (set (make-local-variable 'indent-line-function) 'c++-indent-line)
681 (set (make-local-variable 'comment-start) "// ")
682 (set (make-local-variable 'comment-end) "")
683 (set (make-local-variable 'comment-column) 32)
684 (set (make-local-variable 'comment-start-skip) "/\\*+ *\\|// *")
685 (set (make-local-variable 'comment-indent-hook) 'c++-comment-indent)
686 ;; hack auto-hungry designators into modeline-format
687 (if (listp modeline-format)
688 (setq modeline-format
689 (let ((modeline nil))
690 (mapcar
691 (function
692 (lambda (element)
693 (setq modeline
694 (append modeline
695 (if (eq element 'mode-name)
696 '(mode-name (c++-hungry-delete-key
697 (c++-auto-newline "/ah" "/h")
698 (c++-auto-newline "/a")))
699 (list element))))))
700 modeline-format)
701 modeline)))
702 (run-hooks 'c++-mode-hook)
703 (c++-set-auto-hungry-state
704 (memq c++-auto-hungry-initial-state '(auto-only auto-hungry t))
705 (memq c++-auto-hungry-initial-state '(hungry-only auto-hungry t))))
706
707 ;;##autoload ;; don't autoload an obsolete package
708 (defun c++-c-mode ()
709 "Major mode for editing K&R and ANSI C code. 2.353
710 This mode is based on c++-mode. Documentation for this mode is
711 available by doing a `\\[describe-function] c++-mode'."
712 (interactive)
713 (c++-mode)
714 (setq major-mode 'c++-c-mode
715 mode-name "C"
716 local-abbrev-table c-mode-abbrev-table)
717 (setq comment-start "/* "
718 comment-end " */")
719 ;; some syntax differences are necessary for C vs. C++
720 (set-syntax-table c++-c-mode-syntax-table)
721 (run-hooks 'c++-c-mode-hook))
722
723 (defun c++-comment-indent ()
724 "Used by `indent-for-comment' to decide how much to indent a comment
725 in C++ code based on its context."
726 (if (looking-at "^\\(/\\*\\|//\\)")
727 0 ; Existing comment at bol stays there.
728 (save-excursion
729 (skip-chars-backward " \t")
730 (max
731 ;; leave at least one space on non-empty lines.
732 (if (zerop (current-column))
733 0
734 (1+ (current-column)))
735 ;; use comment-column if previous line is comment only line
736 ;; indented to the left of comment-column
737 (save-excursion
738 (beginning-of-line)
739 (if (not (bobp)) (forward-line -1))
740 (skip-chars-forward " \t")
741 (if (looking-at "/\\*\\|//")
742 (if (< (current-column) comment-column)
743 comment-column
744 (current-column))
745 0))
746 (let ((cur-pt (point)))
747 (beginning-of-line 0)
748 ;; If previous line had a comment, use it's indent
749 (if (re-search-forward comment-start-skip cur-pt t)
750 (progn
751 (goto-char (match-beginning 0))
752 (current-column))
753 comment-column)))))) ; otherwise indent at comment column.
754
755
756 ;; ======================================================================
757 ;; most command level (interactive) and related
758 ;; ======================================================================
759 (defun c++-set-auto-hungry-state (auto-p hungry-p)
760 "Set auto/hungry to state indicated by AUTO-P and HUNGRY-P.
761 Update modeline to indicate state to user."
762 (setq c++-auto-newline auto-p
763 c++-hungry-delete-key hungry-p)
764 (set-buffer-modified-p (buffer-modified-p)))
765
766 (defun c++-toggle-auto-state (arg)
767 "Toggle auto-newline feature.
768 This function ignores `c++-auto-hungry-toggle' variable. Optional
769 numeric ARG, if supplied turns on auto-newline when positive, turns
770 off auto-newline when negative and toggles when zero."
771 (interactive "P")
772 (let ((auto (cond
773 ((not arg)
774 (not c++-auto-newline))
775 ((zerop (setq arg (prefix-numeric-value arg)))
776 (not c++-auto-newline))
777 ((< arg 0) nil)
778 (t t))))
779 (c++-set-auto-hungry-state auto c++-hungry-delete-key)))
780
781 (defun c++-toggle-hungry-state (arg)
782 "Toggle hungry-delete-key feature.
783 This function ignores `c++-auto-hungry-toggle' variable. Optional
784 numeric ARG, if supplied turns on hungry-delete-key when positive,
785 turns off hungry-delete-key when negative and toggles when zero."
786 (interactive "P")
787 (let ((hungry (cond
788 ((not arg)
789 (not c++-hungry-delete-key))
790 ((zerop (setq arg (prefix-numeric-value arg)))
791 (not c++-hungry-delete-key))
792 ((< arg 0) nil)
793 (t t))))
794 (c++-set-auto-hungry-state c++-auto-newline hungry)))
795
796 (defun c++-toggle-auto-hungry-state (arg)
797 "Toggle auto-newline and hungry-delete-key features.
798 Actual toggling of these features is controlled by
799 `c++-auto-hungry-toggle' variable.
800
801 Optional argument has the following meanings when supplied:
802 Universal argument \\[universal-argument]
803 resets features to c++-auto-hungry-initial-state.
804 negative number
805 turn off both auto-newline and hungry-delete-key features.
806 positive number
807 turn on both auto-newline and hungry-delete-key features.
808 zero
809 toggle both features regardless of `c++-auto-hungry-toggle-p'."
810 (interactive "P")
811 (let* ((numarg (prefix-numeric-value arg))
812 (apl (list 'auto-only 'auto-hungry t))
813 (hpl (list 'hungry-only 'auto-hungry t))
814 (auto (cond
815 ((not arg)
816 (if (memq c++-auto-hungry-toggle apl)
817 (not c++-auto-newline)
818 c++-auto-newline))
819 ((listp arg)
820 (memq c++-auto-hungry-initial-state apl))
821 ((zerop numarg)
822 (not c++-auto-newline))
823 ((< arg 0) nil)
824 (t t)))
825 (hungry (cond
826 ((not arg)
827 (if (memq c++-auto-hungry-toggle hpl)
828 (not c++-hungry-delete-key)
829 c++-hungry-delete-key))
830 ((listp arg)
831 (memq c++-auto-hungry-initial-state hpl))
832 ((zerop numarg)
833 (not c++-hungry-delete-key))
834 ((< arg 0) nil)
835 (t t))))
836 (c++-set-auto-hungry-state auto hungry)))
837
838 (defun c++-tame-insert (arg)
839 "Safely inserts certain troublesome characters in comment regions.
840 Because of syntax bugs in Emacs, characters with string or parenthesis
841 syntax must be escaped with a backslash or lots of things get messed
842 up. Unfortunately, setting `parse-sexp-ignore-comments' to non-nil does
843 not fix the problem, but this function is unnecessary if you are
844 running a patched Emacs.
845
846 See also the variable `c++-untame-characters'."
847 (interactive "p")
848 (if (and (memq last-command-char c++-untame-characters)
849 (memq (c++-in-literal) '(c c++)))
850 (insert "\\"))
851 (self-insert-command arg))
852
853 (defun c++-electric-delete (arg)
854 "If `c++-hungry-delete-key' is non-nil, consumes all preceding
855 whitespace unless ARG is supplied, or point is inside a C or C++ style
856 comment or string. If ARG is supplied, this just calls
857 `backward-delete-char-untabify' passing along ARG.
858
859 If `c++-hungry-delete-key' is nil, just call `backward-delete-char-untabify'."
860 (interactive "P")
861 (cond
862 ((or (not c++-hungry-delete-key) arg)
863 (funcall c++-delete-function (prefix-numeric-value arg)))
864 ((let ((bod (c++-point 'bod)))
865 (not (or (memq (c++-in-literal bod) '(c c++ string))
866 (save-excursion
867 (skip-chars-backward " \t")
868 (= (preceding-char) ?#)))))
869 (let ((here (point)))
870 (skip-chars-backward " \t\n")
871 (if (/= (point) here)
872 (delete-region (point) here)
873 (funcall c++-delete-function 1))))
874 (t (funcall c++-delete-function 1))))
875
876 (defun c++-electric-pound (arg)
877 "Electric pound command."
878 (interactive "p")
879 (if (memq (c++-in-literal) '(c c++ string))
880 (self-insert-command arg)
881 (let ((here (point-marker))
882 (bobp (bobp))
883 (bolp (bolp)))
884 (if (memq 'alignleft c++-electric-pound-behavior)
885 (progn (beginning-of-line)
886 (delete-horizontal-space)))
887 (if bobp
888 (insert (make-string arg last-command-char))
889 (insert-before-markers (make-string arg last-command-char)))
890 (if (not bolp)
891 (goto-char here))
892 (set-marker here nil))))
893
894 (defun c++-electric-brace (arg)
895 "Insert character and correct line's indentation."
896 (interactive "P")
897 (let (insertpos
898 (last-command-char last-command-char)
899 (bod (c++-point 'bod)))
900 (if (and (not arg)
901 (save-excursion
902 (skip-chars-forward " \t")
903 (eolp))
904 (or (save-excursion
905 (skip-chars-backward " \t")
906 (bolp))
907 (let ((c++-auto-newline c++-auto-newline)
908 (open-brace-p (= last-command-char ?{)))
909 (if (and open-brace-p
910 (or (eq c++-hanging-braces t)
911 (and c++-hanging-braces
912 (not (c++-at-top-level-p t bod)))))
913 (setq c++-auto-newline nil))
914 (if (c++-auto-newline)
915 ;; this may have auto-filled so we need to
916 ;; indent the previous line. we also need to
917 ;; indent the currently line, or
918 ;; c++-beginning-of-defun will not be able to
919 ;; correctly find the bod when
920 ;; c++-match-headers-strongly is nil.
921 (progn (c++-indent-line)
922 (save-excursion
923 (forward-line -1)
924 (c++-indent-line))))
925 t)))
926 (progn
927 (if (and (memq last-command-char c++-untame-characters)
928 (memq (c++-in-literal bod) '(c c++)))
929 (insert "\\"))
930 ;; we need to work around a bogus feature of Emacs where an
931 ;; open brace at bolp means a beginning-of-defun. but it
932 ;; really might not.
933 (and (= last-command-char ?{)
934 (bolp)
935 (c++-indent-line))
936 (insert last-command-char)
937 ;; try to clean up empty defun braces if conditions apply
938 (let ((here (point-marker)))
939 (and (memq 'empty-defun-braces c++-cleanup-list)
940 (c++-at-top-level-p t bod)
941 c++-auto-newline
942 (= last-command-char ?\})
943 (progn (forward-char -1)
944 (skip-chars-backward " \t\n")
945 (= (preceding-char) ?\{))
946 (not (memq (c++-in-literal) '(c c++ string)))
947 (delete-region (point) (1- here)))
948 (goto-char here)
949 (set-marker here nil))
950 (let ((here (point-marker))
951 mbeg mend)
952 (if (and (memq 'brace-else-brace c++-cleanup-list)
953 (= last-command-char ?\{)
954 (let ((status
955 (re-search-backward "}[ \t\n]*else[ \t\n]*{"
956 nil t)))
957 (setq mbeg (match-beginning 0)
958 mend (match-end 0))
959 status)
960 (= mend here)
961 (not (memq (c++-in-literal bod) '(c c++ string))))
962 (progn
963 ;; we should clean up brace-else-brace syntax
964 (delete-region mbeg mend)
965 (insert-before-markers "} else {")
966 (goto-char here)
967 (set-marker here nil))
968 (goto-char here)
969 (set-marker here nil)))
970 (c++-indent-line)
971 (if (c++-auto-newline)
972 (progn
973 ;; c++-auto-newline may have done an auto-fill
974 (save-excursion
975 (let ((here (point-marker)))
976 (goto-char (- (point) 2))
977 (c++-indent-line)
978 (setq insertpos (- (goto-char here) 2))
979 (set-marker here nil)))
980 (c++-indent-line)))
981 (save-excursion
982 (if insertpos (goto-char (1+ insertpos)))
983 (delete-char -1))))
984 (if insertpos
985 (save-excursion
986 (goto-char insertpos)
987 (self-insert-command (prefix-numeric-value arg)))
988 (self-insert-command (prefix-numeric-value arg)))))
989
990 (defun c++-electric-slash (arg)
991 "Insert slash, and if slash is second of a double-slash comment
992 introducing construct, indent line as comment. This only indents if
993 we're on a comment-only line, otherwise use `indent-for-comment' (\\[indent-for-comment])."
994 (interactive "P")
995 (let ((here (point)) char)
996 (self-insert-command (prefix-numeric-value arg))
997 (and (setq char (char-after (1- here)))
998 (= char ?/)
999 (save-excursion
1000 (goto-char here)
1001 (c++-indent-line)))))
1002
1003 (defun c++-electric-star (arg)
1004 "Works with `c++-electric-slash' to auto indent C style comment lines."
1005 (interactive "P")
1006 (let ((here (point)) char)
1007 (self-insert-command (prefix-numeric-value arg))
1008 (if (and (setq char (char-after (1- here)))
1009 (memq (c++-in-literal) '(c))
1010 (memq char '(?/ ?* ?\t 32 ?\n))
1011 (save-excursion
1012 (skip-chars-backward "* \t")
1013 (if (= (preceding-char) ?/)
1014 (progn
1015 (forward-char -1)
1016 (skip-chars-backward " \t")))
1017 (bolp)))
1018 (save-excursion
1019 (goto-char here)
1020 (c++-indent-line)))))
1021
1022 (defun c++-electric-semi (arg)
1023 "Insert character and correct line's indentation."
1024 (interactive "P")
1025 (if (c++-in-literal)
1026 (self-insert-command (prefix-numeric-value arg))
1027 (let ((here (point-marker)))
1028 (if (and (memq 'defun-close-semi c++-cleanup-list)
1029 c++-auto-newline
1030 (progn
1031 (skip-chars-backward " \t\n")
1032 (= (preceding-char) ?})))
1033 (delete-region here (point)))
1034 (goto-char here)
1035 (set-marker here nil))
1036 (c++-electric-terminator arg)))
1037
1038 (defun c++-electric-colon (arg)
1039 "Electrify colon.
1040 De-auto-newline double colons. No auto-new-lines for member
1041 initialization list."
1042 (interactive "P")
1043 (if (c++-in-literal)
1044 (self-insert-command (prefix-numeric-value arg))
1045 (let ((c++-auto-newline c++-auto-newline)
1046 (insertion-point (point))
1047 (bod (c++-point 'bod)))
1048 (save-excursion
1049 (cond
1050 ;; check for double-colon where the first colon is not in a
1051 ;; comment or literal region
1052 ((progn (skip-chars-backward " \t\n")
1053 (and (= (preceding-char) ?:)
1054 (not (memq (c++-in-literal bod) '(c c++ string)))))
1055 (progn (delete-region insertion-point (point))
1056 (setq c++-auto-newline nil
1057 insertion-point (point))))
1058 ;; check for ?: construct which may be at any level
1059 ((progn (goto-char insertion-point)
1060 (condition-case premature-end
1061 (backward-sexp 1)
1062 (error nil))
1063 ;; is possible that the sexp we just skipped was a
1064 ;; negative number. in that case the minus won't be
1065 ;; gobbled
1066 (skip-chars-backward "-")
1067 (c++-backward-syntactic-ws bod)
1068 (= (preceding-char) ?\?))
1069 (setq c++-auto-newline nil))
1070 ;; check for being at top level or top with respect to the
1071 ;; class. if not, process as normal
1072 ((progn (goto-char insertion-point)
1073 (not (c++-at-top-level-p t bod))))
1074 ;; if at top level, check to see if we are introducing a member
1075 ;; init list. if not, continue
1076 ((progn (c++-backward-syntactic-ws bod)
1077 (= (preceding-char) ?\)))
1078 (goto-char insertion-point)
1079 ;; at a member init list, figure out about auto newlining. if
1080 ;; nil or before then put a newline before the colon and
1081 ;; adjust the insertion point, but *only* if there is no
1082 ;; newline already before the insertion point
1083 (if (and (memq c++-hanging-member-init-colon '(nil before))
1084 c++-auto-newline)
1085 (if (not (save-excursion (skip-chars-backward " \t")
1086 (bolp)))
1087 (let ((c++-auto-newline t))
1088 (c++-auto-newline)
1089 (setq insertion-point (point)))))
1090 ;; if hanging colon is after or nil, then newline is inserted
1091 ;; after colon. set up variable so c++-electric-terminator
1092 ;; places the newline correctly
1093 (setq c++-auto-newline
1094 (and c++-auto-newline
1095 (memq c++-hanging-member-init-colon '(nil after)))))
1096 ;; last condition is always put newline after colon
1097 (t (setq c++-auto-newline nil))
1098 )) ; end-cond, end-save-excursion
1099 (goto-char insertion-point)
1100 (c++-electric-terminator arg))))
1101
1102 (defun c++-electric-terminator (arg)
1103 "Insert character and correct line's indentation."
1104 (interactive "P")
1105 (let (insertpos (end (point)))
1106 (if (and (not arg)
1107 (save-excursion
1108 (skip-chars-forward " \t")
1109 (eolp))
1110 (not (save-excursion
1111 (beginning-of-line)
1112 (skip-chars-forward " \t")
1113 (or (= (following-char) ?#)
1114 ;; Colon is special only after a label, or
1115 ;; case, or another colon.
1116 ;; So quickly rule out most other uses of colon
1117 ;; and do no indentation for them.
1118 (and (eq last-command-char ?:)
1119 (not (looking-at "case[ \t]"))
1120 (save-excursion
1121 (forward-word 1)
1122 (skip-chars-forward " \t")
1123 (< (point) end))
1124 ;; Do re-indent double colons
1125 (save-excursion
1126 (end-of-line 1)
1127 (looking-at ":")))
1128 (progn
1129 (c++-beginning-of-defun)
1130 (let* ((parse-sexp-ignore-comments t)
1131 (pps (parse-partial-sexp (point) end)))
1132 (or (nth 3 pps) (nth 4 pps) (nth 5 pps))))))))
1133 (progn
1134 (insert last-command-char)
1135 (c++-indent-line)
1136 (and c++-auto-newline
1137 (not (c++-in-parens-p))
1138 (progn
1139 ;; the new marker object, used to be just an integer
1140 (setq insertpos (make-marker))
1141 ;; changed setq to set-marker
1142 (set-marker insertpos (1- (point)))
1143 ;; do this before the newline, since in auto fill can break
1144 (newline)
1145 (c++-indent-line)))
1146 (save-excursion
1147 (if insertpos (goto-char (1+ insertpos)))
1148 (delete-char -1))))
1149 (if insertpos
1150 (save-excursion
1151 (goto-char insertpos)
1152 (self-insert-command (prefix-numeric-value arg)))
1153 (self-insert-command (prefix-numeric-value arg)))))
1154
1155 (defun c++-indent-command (&optional whole-exp)
1156 "Indent current line as C++ code, or in some cases insert a tab character.
1157
1158 If `c++-tab-always-indent' is t, always just indent the current line.
1159 If nil, indent the current line only if point is at the left margin or
1160 in the line's indentation; otherwise insert a tab. If not-nil-or-t,
1161 then tab is inserted only within literals (comments and strings) and
1162 inside preprocessor directives, but line is always reindented.
1163
1164 A numeric argument, regardless of its value, means indent rigidly all
1165 the lines of the expression starting after point so that this line
1166 becomes properly indented. The relative indentation among the lines
1167 of the expression are preserved."
1168 (interactive "P")
1169 (let ((bod (c++-point 'bod)))
1170 (if whole-exp
1171 ;; If arg, always indent this line as C
1172 ;; and shift remaining lines of expression the same amount.
1173 (let ((shift-amt (c++-indent-line bod))
1174 beg end)
1175 (save-excursion
1176 (if (eq c++-tab-always-indent t)
1177 (beginning-of-line))
1178 (setq beg (point))
1179 (forward-sexp 1)
1180 (setq end (point))
1181 (goto-char beg)
1182 (forward-line 1)
1183 (setq beg (point)))
1184 (if (> end beg)
1185 (indent-code-rigidly beg end shift-amt "#")))
1186 (cond
1187 ;; CASE 1: indent when at column zero or in lines indentation,
1188 ;; otherwise insert a tab
1189 ((not c++-tab-always-indent)
1190 (if (and (save-excursion
1191 (skip-chars-backward " \t")
1192 (bolp))
1193 (or (looking-at "[ \t]*$")
1194 (/= (point) (c++-point 'boi))
1195 (bolp)))
1196 (c++-indent-line bod)
1197 (insert-tab)))
1198 ;; CASE 2: just indent the line
1199 ((eq c++-tab-always-indent t)
1200 (c++-indent-line bod))
1201 ;; CASE 3: if in a literal, insert a tab, but always indent the line
1202 ((or (memq (c++-in-literal bod) '(c c++ string))
1203 (save-excursion
1204 (skip-chars-backward " \t")
1205 (= (preceding-char) ?#)))
1206 (let ((here (point))
1207 (boi (save-excursion (back-to-indentation) (point)))
1208 (indent-p nil))
1209 (c++-indent-line bod)
1210 (save-excursion
1211 (back-to-indentation)
1212 (setq indent-p (and (> here boi) (= (point) boi))))
1213 (if indent-p (insert-tab))))
1214 ;; CASE 4: bogus, just indent the line
1215 (t (c++-indent-line bod))))))
1216
1217 (defun c++-indent-exp ()
1218 "Indent each line of the C++ grouping following point."
1219 (interactive)
1220 (let ((indent-stack (list nil))
1221 (contain-stack (list (point)))
1222 (case-fold-search nil)
1223 restart outer-loop-done inner-loop-done state ostate
1224 this-indent last-sexp last-depth
1225 at-else at-brace
1226 (parse-sexp-ignore-comments t)
1227 (opoint (point))
1228 (next-depth 0))
1229 (save-excursion
1230 (forward-sexp 1))
1231 (save-excursion
1232 (setq outer-loop-done nil)
1233 (while (and (not (eobp)) (not outer-loop-done))
1234 (setq last-depth next-depth)
1235 ;; Compute how depth changes over this line
1236 ;; plus enough other lines to get to one that
1237 ;; does not end inside a comment or string.
1238 ;; Meanwhile, do appropriate indentation on comment lines.
1239 (setq inner-loop-done nil)
1240 (while (and (not inner-loop-done)
1241 (not (and (eobp) (setq outer-loop-done t))))
1242 (setq ostate state)
1243 ;; fix by reed@adapt.net.com
1244 ;; must pass in the return past the end of line, so that
1245 ;; parse-partial-sexp finds it, and recognizes that a "//"
1246 ;; comment is over. otherwise, state is set that we're in a
1247 ;; comment, and never gets unset, causing outer-loop to only
1248 ;; terminate in (eobp). old:
1249 ;;(setq state (parse-partial-sexp (point)
1250 ;;(progn (end-of-line) (point))
1251 ;;nil nil state))
1252 (let ((start (point))
1253 (line-end
1254 (progn (end-of-line)
1255 (while (eq (c++-in-literal) 'c)
1256 (forward-line 1)
1257 (c++-indent-line)
1258 (end-of-line))
1259 (skip-chars-backward " \t")
1260 (end-of-line)
1261 (point)))
1262 (end (progn (if (not (eobp)) (forward-char)) (point))))
1263 (setq state (parse-partial-sexp start end nil nil state))
1264 (goto-char line-end))
1265 (setq next-depth (car state))
1266 (if (and (car (cdr (cdr state)))
1267 (>= (car (cdr (cdr state))) 0))
1268 (setq last-sexp (car (cdr (cdr state)))))
1269 (if (or (nth 4 ostate))
1270 (c++-indent-line))
1271 (if (or (nth 3 state))
1272 (forward-line 1)
1273 (setq inner-loop-done t)))
1274 (if (<= next-depth 0)
1275 (setq outer-loop-done t))
1276 (if outer-loop-done
1277 nil
1278 ;; If this line had ..))) (((.. in it, pop out of the levels
1279 ;; that ended anywhere in this line, even if the final depth
1280 ;; doesn't indicate that they ended.
1281 (while (> last-depth (nth 6 state))
1282 (setq indent-stack (cdr indent-stack)
1283 contain-stack (cdr contain-stack)
1284 last-depth (1- last-depth)))
1285 (if (/= last-depth next-depth)
1286 (setq last-sexp nil))
1287 ;; Add levels for any parens that were started in this line.
1288 (while (< last-depth next-depth)
1289 (setq indent-stack (cons nil indent-stack)
1290 contain-stack (cons nil contain-stack)
1291 last-depth (1+ last-depth)))
1292 (if (null (car contain-stack))
1293 (setcar contain-stack (or (car (cdr state))
1294 (save-excursion (forward-sexp -1)
1295 (point)))))
1296 (forward-line 1)
1297 (skip-chars-forward " \t")
1298 ;; check for C comment block
1299 (if (memq (c++-in-literal) '(c))
1300 (let ((eoc (save-excursion
1301 (re-search-forward "\\*/" (point-max) 'move)
1302 (point))))
1303 (while (< (point) eoc)
1304 (c++-indent-line)
1305 (forward-line 1))))
1306 (if (eolp)
1307 nil
1308 (if (and (car indent-stack)
1309 (>= (car indent-stack) 0))
1310 ;; Line is on an existing nesting level.
1311 ;; Lines inside parens are handled specially.
1312 (if (or (/= (char-after (car contain-stack)) ?{)
1313 ;;(c++-at-top-level-p t))
1314 ;; baw hack for continued statement offsets
1315 ;; repercussions???
1316 t)
1317 (setq this-indent (car indent-stack))
1318 ;; Line is at statement level.
1319 ;; Is it a new statement? Is it an else?
1320 ;; Find last non-comment character before this line
1321 (save-excursion
1322 (setq at-else (looking-at "else\\W"))
1323 (setq at-brace (= (following-char) ?{))
1324 (c++-backward-syntactic-ws opoint)
1325 (if (not (memq (preceding-char) '(nil ?\, ?\; ?} ?: ?{)))
1326 ;; Preceding line did not end in comma or semi;
1327 ;; indent this line c-continued-statement-offset
1328 ;; more than previous.
1329 (progn
1330 (c-backward-to-start-of-continued-exp
1331 (car contain-stack))
1332 (setq this-indent
1333 (+ c-continued-statement-offset
1334 (current-column)
1335 (if at-brace c-continued-brace-offset 0))))
1336 ;; Preceding line ended in comma or semi;
1337 ;; use the standard indent for this level.
1338 (if at-else
1339 (progn (c++-backward-to-start-of-if opoint)
1340 (back-to-indentation)
1341 (skip-chars-forward "{ \t")
1342 (setq this-indent (current-column)))
1343 (setq this-indent (car indent-stack))))))
1344 ;; Just started a new nesting level.
1345 ;; Compute the standard indent for this level.
1346 (let ((val (c++-calculate-indent
1347 (if (car indent-stack)
1348 (- (car indent-stack))))))
1349 (setcar indent-stack
1350 (setq this-indent val))))
1351 ;; Adjust line indentation according to its contents
1352 (cond
1353 ;; looking at public, protected, private line
1354 ((looking-at c++-access-key)
1355 (setq this-indent (+ this-indent c++-access-specifier-offset)))
1356 ;; looking at a case, default, or other label
1357 ((or (looking-at "\\(case[ \t]+.*\\|default[ \t]*\\):")
1358 (and (looking-at "[A-Za-z]")
1359 (save-excursion
1360 (forward-sexp 1)
1361 (looking-at ":[^:]"))))
1362 (setq this-indent (max 0 (+ this-indent c-label-offset))))
1363 ;; looking at a comment only line?
1364 ((looking-at comment-start-skip)
1365 ;; different indentation base on whether this is a col0
1366 ;; comment only line or not. also, if comment is in, or
1367 ;; to the right of comment-column, the comment doesn't
1368 ;; move
1369 (progn
1370 (skip-chars-forward " \t")
1371 (setq this-indent
1372 (if (>= (current-column) comment-column)
1373 (current-column)
1374 (c++-comment-offset
1375 (bolp)
1376 (+ this-indent
1377 (if (save-excursion
1378 (c++-backward-syntactic-ws
1379 (car contain-stack))
1380 (memq (preceding-char)
1381 '(nil ?\, ?\; ?} ?: ?{)))
1382 0 c-continued-statement-offset))
1383 )))))
1384 ;; looking at a friend declaration
1385 ((looking-at "friend[ \t]")
1386 (setq this-indent (+ this-indent c++-friend-offset)))
1387 ;; looking at a close brace
1388 ((= (following-char) ?})
1389 (setq this-indent (- this-indent c-indent-level)))
1390 ;; looking at an open brace
1391 ((= (following-char) ?{)
1392 (setq this-indent
1393 (+ this-indent c-brace-offset
1394 (if (c++-at-top-level-p t (car contain-stack))
1395 0 c-indent-level))))
1396 ;; check for continued statements
1397 ((save-excursion
1398 (c++-backward-syntactic-ws (car contain-stack))
1399 (and (not (c++-in-parens-p))
1400 (not (memq (preceding-char) '(nil ?\000 ?\; ?\} ?\: ?\{)))
1401 (progn
1402 (beginning-of-line)
1403 (skip-chars-forward " \t")
1404 (not (looking-at c++-class-key)))))
1405 (setq this-indent
1406 (+ this-indent
1407 c-continued-statement-offset
1408 ;; are we in a member init list?
1409 (if (not (looking-at "[ \t]*:"))
1410 (save-excursion
1411 (let ((lim (car contain-stack)))
1412 (c++-backward-syntactic-ws lim)
1413 (while (and (< lim (point))
1414 (= (preceding-char) ?,))
1415 (beginning-of-line)
1416 (c++-backward-syntactic-ws))
1417 (forward-line 1)
1418 (beginning-of-line)
1419 (if (looking-at "[ \t]*:")
1420 (- (save-excursion
1421 (skip-chars-forward " \t")
1422 (point))
1423 (point))
1424 0)))
1425 0)
1426 )))
1427 ;; check for stream operator
1428 ((looking-at "\\(<<\\|>>\\)")
1429 (setq this-indent (c++-calculate-indent)))
1430 ) ;; end-cond
1431 ;; Put chosen indentation into effect.
1432 (or (= (current-column) this-indent)
1433 (= (following-char) ?\#)
1434 (progn
1435 (delete-region (point) (progn (beginning-of-line) (point)))
1436 (indent-to this-indent)))
1437 ;; Indent any comment following the text.
1438 (or (looking-at comment-start-skip)
1439 (if (re-search-forward
1440 comment-start-skip
1441 (c++-point 'eol) t)
1442 (progn (indent-for-comment)
1443 (beginning-of-line))))
1444 ))))))
1445
1446 (defun c++-insert-header ()
1447 "Insert header denoting C++ code at top of buffer."
1448 (interactive)
1449 (save-excursion
1450 (goto-char (point-min))
1451 (insert "// "
1452 "This may look like C code, but it is really "
1453 "-*- C++ -*-"
1454 "\n\n")))
1455
1456 (defun c++-tame-comments ()
1457 "Backslashifies all untamed in comment regions found in the buffer.
1458 This is a workaround for Emacs syntax bugs. This function is
1459 unnecessary (and un-used automatically) if you are running a patched
1460 Emacs. Untamed characters to escape are defined in the variable
1461 `c++-untame-characters'."
1462 (interactive)
1463 ;; make the list into a valid charset, escaping where necessary
1464 (let ((charset (concat "^" (mapconcat
1465 (function
1466 (lambda (char)
1467 (if (memq char '(?\\ ?^ ?-))
1468 (concat "\\" (char-to-string char))
1469 (char-to-string char))))
1470 c++-untame-characters ""))))
1471 (save-excursion
1472 (beginning-of-buffer)
1473 (while (not (eobp))
1474 (skip-chars-forward charset)
1475 (if (and (not (zerop (following-char)))
1476 (memq (c++-in-literal) '(c c++))
1477 (/= (preceding-char) ?\\ ))
1478 (insert "\\"))
1479 (if (not (eobp))
1480 (forward-char 1))))))
1481
1482 ;; taken from match-paren.el. Author: unknown
1483 (defun c++-match-paren ()
1484 "Jumps to the paren matching the one under point, if there is one."
1485 (interactive)
1486 (let ((parse-sexp-ignore-comments (memq 'v19 c++-emacs-features)))
1487 (cond
1488 ((looking-at "[\(\[{]")
1489 (forward-sexp 1)
1490 (backward-char))
1491 ((looking-at "[])}]")
1492 (forward-char)
1493 (backward-sexp 1))
1494 (t (message "Could not find matching paren.")))))
1495
1496 (defun c++-forward-sexp (&optional arg)
1497 "Safe forward-sexp call."
1498 (interactive "_p")
1499 (let ((parse-sexp-ignore-comments (memq 'v19 c++-emacs-features)))
1500 (forward-sexp arg)))
1501
1502 (defun c++-backward-sexp (&optional arg)
1503 "Safe backward-sexp call."
1504 (interactive "_p")
1505 (let ((parse-sexp-ignore-comments (memq 'v19 c++-emacs-features)))
1506 (backward-sexp arg)))
1507
1508
1509 ;; ======================================================================
1510 ;; compatibility between emacsen
1511 ;; ======================================================================
1512
1513 ;; This is the best we can do in vanilla GNU 18 emacsen. Note that the
1514 ;; following problems exist:
1515 ;; 1. We only look back to LIM, and that could place us inside a
1516 ;; literal if we are scanning backwards over lots of comments
1517 ;; 2. This can potentially get slower the larger LIM is
1518 ;; If anybody has a better solution, I'll all ears
1519 (defun c++-backward-syntactic-ws-v18 (&optional lim)
1520 "Skip backwards over syntactic whitespace.
1521 Syntactic whitespace is defined as lexical whitespace, C and C++ style
1522 comments, and preprocessor directives. Search no farther back than
1523 optional LIM. If LIM is omitted, `beginning-of-defun' is used."
1524 (let ((lim (or lim (c++-point 'bod)))
1525 literal stop)
1526 (if (and c++-backscan-limit
1527 (> (- (point) lim) c++-backscan-limit))
1528 (setq lim (- (point) c++-backscan-limit)))
1529 (while (not stop)
1530 (skip-chars-backward " \t\n\r\f" lim)
1531 ;; c++ comment
1532 (if (eq (setq literal (c++-in-literal lim)) 'c++)
1533 (progn
1534 (skip-chars-backward "^/" lim)
1535 (skip-chars-backward "/" lim)
1536 (while (not (or (and (= (following-char) ?/)
1537 (= (char-after (1+ (point))) ?/))
1538 (<= (point) lim)))
1539 (skip-chars-backward "^/" lim)
1540 (skip-chars-backward "/" lim)))
1541 ;; c comment
1542 (if (eq literal 'c)
1543 (progn
1544 (skip-chars-backward "^*" lim)
1545 (skip-chars-backward "*" lim)
1546 (while (not (or (and (= (following-char) ?*)
1547 (= (preceding-char) ?/))
1548 (<= (point) lim)))
1549 (skip-chars-backward "^*" lim)
1550 (skip-chars-backward "*" lim))
1551 (or (bobp) (forward-char -1)))
1552 ;; preprocessor directive
1553 (if (eq literal 'pound)
1554 (progn
1555 (beginning-of-line)
1556 (setq stop (<= (point) lim)))
1557 ;; just outside of c block
1558 (if (and (= (preceding-char) ?/)
1559 (= (char-after (- (point) 2)) ?*))
1560 (progn
1561 (skip-chars-backward "^*" lim)
1562 (skip-chars-backward "*" lim)
1563 (while (not (or (and (= (following-char) ?*)
1564 (= (preceding-char) ?/))
1565 (<= (point) lim)))
1566 (skip-chars-backward "^*" lim)
1567 (skip-chars-backward "*" lim))
1568 (or (bobp) (forward-char -1)))
1569 ;; none of the above
1570 (setq stop t))))))))
1571
1572 ;; This defun works well for Lemacs 19.4-7, which implemented a first
1573 ;; shot at doing this via a C built-in backward-syntactic-ws. This
1574 ;; has been obsoleted in future Lemacsen and in FSF19
1575 (defun c++-fast-backward-syntactic-ws-1 (&optional lim)
1576 "Skip backwards over syntactic whitespace.
1577 Syntactic whitespace is defined as lexical whitespace, C and C++ style
1578 comments, and preprocessor directives. Search no farther back than
1579 optional LIM. If LIM is omitted, `beginning-of-defun' is used."
1580 (save-restriction
1581 (let ((parse-sexp-ignore-comments t)
1582 donep boi char
1583 (lim (or lim (c++-point 'bod))))
1584 (if (< lim (point))
1585 (unwind-protect
1586 (progn
1587 (narrow-to-region lim (point))
1588 ;; cpp statements are comments for our purposes here
1589 (if (eq major-mode 'c++-mode)
1590 (modify-syntax-entry ?# "< b" c++-mode-syntax-table)
1591 (modify-syntax-entry ?\n "> b" c++-c-mode-syntax-table)
1592 (modify-syntax-entry ?# "< b" c++-c-mode-syntax-table))
1593 (while (not donep)
1594 ;; if you're not running a patched XEmacs, the new byte
1595 ;; compiler will complain about this function. ignore that
1596 (backward-syntactic-ws)
1597 (if (not (looking-at "#\\|/\\*\\|//\\|\n"))
1598 (forward-char 1))
1599 (setq boi (c++-point 'boi)
1600 char (char-after boi))
1601 (if (and char (= char ?#))
1602 (progn (goto-char boi)
1603 (setq donep (<= (point) lim)))
1604 (setq donep t))
1605 ))
1606 ;; cpp statements are not comments anywhere else
1607 (if (eq major-mode 'c++-mode)
1608 (modify-syntax-entry ?# "." c++-mode-syntax-table)
1609 (modify-syntax-entry ?\n " " c++-c-mode-syntax-table)
1610 (modify-syntax-entry ?# "." c++-c-mode-syntax-table))))
1611 )))
1612
1613 ;; This is the way it should be done for all post 19.7 Lemacsen and
1614 ;; for all FSF19 implementations
1615 (defun c++-fast-backward-syntactic-ws-2 (&optional lim)
1616 "Skip backwards over syntactic whitespace.
1617 Syntactic whitespace is defined as lexical whitespace, C and C++ style
1618 comments, and preprocessor directives. Search no farther back than
1619 optional LIM. If LIM is omitted, `beginning-of-defun' is used."
1620 (save-restriction
1621 (let* ((lim (or lim (c++-point 'bod)))
1622 (here lim))
1623 (if (< lim (point))
1624 (unwind-protect
1625 (progn
1626 (narrow-to-region lim (point))
1627 ;; cpp statements are comments for our purposes here
1628 (if (eq major-mode 'c++-mode)
1629 (modify-syntax-entry ?# "< b" c++-mode-syntax-table)
1630 (modify-syntax-entry ?\n "> b" c++-c-mode-syntax-table)
1631 (modify-syntax-entry ?# "< b" c++-c-mode-syntax-table))
1632 (while (/= here (point))
1633 (setq here (point))
1634 (forward-comment -1)))
1635 ;; cpp statements are not comments everywhere else
1636 (if (eq major-mode 'c++-mode)
1637 (modify-syntax-entry ?# "." c++-mode-syntax-table)
1638 (modify-syntax-entry ?\n " " c++-c-mode-syntax-table)
1639 (modify-syntax-entry ?# "." c++-c-mode-syntax-table))))
1640 )))
1641
1642 ;; This is the slow and ugly way, but its the best we can do in
1643 ;; vanilla GNU18 emacsen
1644 (defun c++-in-literal-v18 (&optional lim)
1645 "Determine if point is in a C++ ``literal''.
1646 Return `c' if in a C-style comment, `c++' if in a C++ style comment,
1647 `string' if in a string literal, `pound' if on a preprocessor line, or
1648 nil if not in a comment at all. Optional LIM is used as the backward
1649 limit of the search. If omitted, or nil, `c++-beginning-of-defun' is
1650 used."
1651 (save-excursion
1652 (let* ((here (point))
1653 (state nil)
1654 (match nil)
1655 (backlim (or lim (c++-point 'bod))))
1656 (goto-char backlim)
1657 (while (< (point) here)
1658 (setq match
1659 (and (re-search-forward "\\(/[/*]\\)\\|[\"']\\|\\(^[ \t]*#\\)"
1660 here 'move)
1661 (buffer-substring (match-beginning 0) (match-end 0))))
1662 (setq state
1663 (cond
1664 ;; no match
1665 ((null match) nil)
1666 ;; looking at the opening of a C++ style comment
1667 ((string= "//" match)
1668 (if (<= here (progn (end-of-line) (point))) 'c++))
1669 ;; looking at the opening of a C block comment
1670 ((string= "/*" match)
1671 (if (not (re-search-forward "*/" here 'move)) 'c))
1672 ;; looking at the opening of a double quote string
1673 ((string= "\"" match)
1674 (if (not (save-restriction
1675 ;; this seems to be necessary since the
1676 ;; re-search-forward will not work without it
1677 (narrow-to-region (point) here)
1678 (re-search-forward
1679 ;; this regexp matches a double quote
1680 ;; which is preceded by an even number
1681 ;; of backslashes, including zero
1682 "\\([^\\]\\|^\\)\\(\\\\\\\\\\)*\"" here 'move)))
1683 'string))
1684 ;; looking at the opening of a single quote string
1685 ((string= "'" match)
1686 (if (not (save-restriction
1687 ;; see comments from above
1688 (narrow-to-region (point) here)
1689 (re-search-forward
1690 ;; this matches a single quote which is
1691 ;; preceded by zero or two backslashes.
1692 "\\([^\\]\\|^\\)\\(\\\\\\\\\\)?'"
1693 here 'move)))
1694 'string))
1695 ((string-match "[ \t]*#" match)
1696 (if (<= here (progn (end-of-line) (point))) 'pound))
1697 (t nil)))
1698 ) ; end-while
1699 state)))
1700
1701 ;; This is for all 8-bit emacsen (Lucid 19, patched GNU18)
1702 (defun c++-in-literal-8-bit (&optional lim)
1703 "Determine if point is in a C++ ``literal''.
1704 Return `c' if in a C-style comment, `c++' if in a C++ style comment,
1705 `string' if in a string literal, `pound' if on a preprocessor line, or
1706 nil if not in a comment at all. Optional LIM is used as the backward
1707 limit of the search. If omitted, or nil, `c++-beginning-of-defun' is
1708 used."
1709 (save-excursion
1710 (let* ((backlim (or lim (c++-point 'bod)))
1711 (here (point))
1712 (parse-sexp-ignore-comments t) ; may not be necessary
1713 (state (parse-partial-sexp backlim (point))))
1714 (cond
1715 ((nth 3 state) 'string)
1716 ((nth 4 state) (if (nth 7 state) 'c++ 'c))
1717 ((progn
1718 (goto-char here)
1719 (beginning-of-line)
1720 (looking-at "[ \t]*#"))
1721 'pound)
1722 (t nil)))))
1723
1724 ;; This is for all 1-bit emacsen (FSF19)
1725 (defun c++-in-literal-1-bit (&optional lim)
1726 "Determine if point is in a C++ ``literal''.
1727 Return `c' if in a C-style comment, `c++' if in a C++ style comment,
1728 `string' if in a string literal, `pound' if on a preprocessor line, or
1729 nil if not in a comment at all. Optional LIM is used as the backward
1730 limit of the search. If omitted, or nil, `c++-beginning-of-defun' is
1731 used."
1732 (save-excursion
1733 (let* ((backlim (or lim (c++-point 'bod)))
1734 (here (point))
1735 (parse-sexp-ignore-comments t) ; may not be necessary
1736 (state (parse-partial-sexp backlim (point))))
1737 (cond
1738 ((nth 3 state) 'string)
1739 ((nth 4 state) (if (nth 7 state) 'c 'c++))
1740 ((progn
1741 (goto-char here)
1742 (beginning-of-line)
1743 (looking-at "[ \t]*#"))
1744 'pound)
1745 (t nil)))))
1746
1747 (cond
1748 ((memq 'old-v19 c++-emacs-features)
1749 (fset 'c++-backward-syntactic-ws 'c++-fast-backward-syntactic-ws-1))
1750 ((memq 'v19 c++-emacs-features)
1751 (fset 'c++-backward-syntactic-ws 'c++-fast-backward-syntactic-ws-2))
1752 (t
1753 (fset 'c++-backward-syntactic-ws 'c++-backward-syntactic-ws-v18))
1754 )
1755 (cond
1756 ((memq '8-bit c++-emacs-features)
1757 (fset 'c++-in-literal 'c++-in-literal-8-bit))
1758 ((memq '1-bit c++-emacs-features)
1759 (fset 'c++-in-literal 'c++-in-literal-1-bit))
1760 (t
1761 (fset 'c++-in-literal 'c++-in-literal-v18))
1762 )
1763
1764
1765 ;; ======================================================================
1766 ;; defuns for parsing syntactic elements
1767 ;; ======================================================================
1768 (defun c++-parse-state (&optional limit)
1769 "Determinate the syntactic state of the code at point.
1770 Iteratively uses `parse-partial-sexp' from point to LIMIT and returns
1771 the result of `parse-partial-sexp' at point. LIMIT is optional and
1772 defaults to `point-max'."
1773 (let ((limit (or limit (point-max)))
1774 (parse-sexp-ignore-comments t)
1775 state)
1776 (while (< (point) limit)
1777 (setq state (parse-partial-sexp (point) limit 0)))
1778 state))
1779
1780 (defun c++-at-top-level-p (wrt &optional bod)
1781 "Return t if point is not inside a containing C++ expression, nil
1782 if it is embedded in an expression. When WRT is non-nil, returns nil
1783 if not at the top level with respect to an enclosing class, or the
1784 depth of class nesting at point. With WRT nil, returns nil if not at
1785 the ``real'' top level. Optional BOD is the beginning of defun."
1786 (save-excursion
1787 (let ((indent-point (point))
1788 (case-fold-search nil)
1789 state containing-sexp paren-depth
1790 (bod (or bod (c++-point 'bod)))
1791 foundp)
1792 (goto-char bod)
1793 (setq state (c++-parse-state indent-point)
1794 containing-sexp (nth 1 state)
1795 paren-depth (nth 0 state))
1796 (cond
1797 ((eq major-mode 'c++-c-mode)
1798 (and (null containing-sexp) 0))
1799 ((not wrt)
1800 (null containing-sexp))
1801 ((null containing-sexp) 0)
1802 ((c++-in-parens-p) nil)
1803 (t
1804 ;; calculate depth wrt containing (possibly nested) classes
1805 (goto-char containing-sexp)
1806 (while (and (setq foundp (re-search-backward
1807 (concat "[;}]\\|" c++-class-key)
1808 (point-min) t))
1809 (let ((bod (c++-point 'bod)))
1810 (or (c++-in-literal bod)
1811 (c++-in-parens-p bod)
1812 ;; see if class key is inside a template spec
1813 (and (looking-at c++-class-key)
1814 (progn (skip-chars-backward " \t\n")
1815 (memq (preceding-char) '(?, ?<))))))))
1816 (if (memq (following-char) '(?} ?\;))
1817 nil
1818 (setq state (c++-parse-state containing-sexp))
1819 (and foundp
1820 (not (nth 1 state))
1821 (nth 2 state)
1822 paren-depth))
1823 )))))
1824
1825 (defun c++-in-parens-p (&optional lim)
1826 "Return t if inside a paren expression.
1827 Optional LIM is used as the backward limit of the search."
1828 (let ((lim (or lim (c++-point 'bod))))
1829 (condition-case var
1830 (save-excursion
1831 (save-restriction
1832 (narrow-to-region (point) lim)
1833 (goto-char (point-max))
1834 (= (char-after (or (scan-lists (point) -1 1)
1835 (point-min)))
1836 ?\()))
1837 (error nil)
1838 )))
1839
1840 (defun c++-in-function-p (&optional containing)
1841 "Return t if inside a C++ function definition.
1842 Optional CONTAINING is position of containing s-exp open brace. If not
1843 supplied, point is used as search start."
1844 (save-excursion
1845 (let ((here (if (not containing)
1846 (point)
1847 (goto-char containing)
1848 (c++-backward-syntactic-ws)
1849 (point))))
1850 (if (and (= (preceding-char) ?t)
1851 (forward-word -1)
1852 (looking-at "\\<const\\>"))
1853 (c++-backward-syntactic-ws)
1854 (goto-char here))
1855 (= (preceding-char) ?\)))))
1856
1857
1858 ;; ======================================================================
1859 ;; defuns for calculating indentation
1860 ;; ======================================================================
1861 (defun c++-indent-line (&optional bod)
1862 "Indent current line as C++ code.
1863 Return the amount the indentation changed by. Optional BOD is the
1864 point of the beginning of the C++ definition."
1865 (let* ((bod (or bod (c++-point 'bod)))
1866 (indent (c++-calculate-indent nil bod))
1867 beg shift-amt
1868 close-paren top-close-paren
1869 (case-fold-search nil)
1870 (pos (- (point-max) (point))))
1871 ;; calculate block close paren offset
1872 (if (listp c++-block-close-brace-offset)
1873 (setq close-paren (car c++-block-close-brace-offset)
1874 top-close-paren (cdr c++-block-close-brace-offset))
1875 (setq close-paren c++-block-close-brace-offset
1876 top-close-paren c++-block-close-brace-offset))
1877 ;; now start cleanup
1878 (beginning-of-line)
1879 (setq beg (point))
1880 (cond
1881 ((eq indent nil)
1882 (setq indent (current-indentation)))
1883 ((eq indent t)
1884 (setq indent (c++-calculate-c-indent-within-comment)))
1885 ((looking-at "[ \t]*#")
1886 (setq indent 0))
1887 ((save-excursion
1888 (back-to-indentation)
1889 (looking-at "//\\|/\\*"))
1890 ;; we've found a comment-only line. we now must try to determine
1891 ;; if the line is a continuation from a comment on the previous
1892 ;; line. we check to see if the comment starts in or to the
1893 ;; right of comment-column and if so, we don't change its
1894 ;; indentation.
1895 (skip-chars-forward " \t")
1896 (if (>= (current-column) comment-column)
1897 (setq indent (current-column))
1898 (setq indent (c++-comment-offset (bolp) indent))))
1899 (t
1900 (skip-chars-forward " \t")
1901 (if (listp indent) (setq indent (car indent)))
1902 (cond
1903 ((looking-at c++-access-key)
1904 (setq indent (+ indent c++-access-specifier-offset)))
1905 ((looking-at "default[ \t]*:")
1906 (setq indent (+ indent c-label-offset)))
1907 ((or (looking-at "case[ \t]+.*:")
1908 (and (looking-at "[A-Za-z]")
1909 (save-excursion
1910 (forward-sexp 1)
1911 (looking-at ":[^:]"))))
1912 (setq indent (max 1 (+ indent c-label-offset))))
1913 ((and (looking-at "else\\b")
1914 (not (looking-at "else\\s_")))
1915 (setq indent (save-excursion
1916 (c++-backward-to-start-of-if)
1917 (back-to-indentation)
1918 (skip-chars-forward "{ \t")
1919 (current-column))))
1920 ((looking-at "\\<friend\\>")
1921 (setq indent (+ indent c++-friend-offset)))
1922 ((and (= (following-char) ?\))
1923 c++-paren-as-block-close-p)
1924 (setq indent (+ (- indent c-indent-level)
1925 (if (save-excursion
1926 (forward-char 1)
1927 (c++-at-top-level-p nil bod))
1928 top-close-paren
1929 close-paren))))
1930 ((= (following-char) ?})
1931 (setq indent (+ (- indent c-indent-level)
1932 (if (save-excursion
1933 (forward-char 1)
1934 (c++-at-top-level-p nil bod))
1935 top-close-paren
1936 close-paren))))
1937 ((= (following-char) ?{)
1938 (setq indent (+ indent c-brace-offset))))))
1939 (skip-chars-forward " \t")
1940 (setq shift-amt (- indent (current-column)))
1941 (if (zerop shift-amt)
1942 (if (> (- (point-max) pos) (point))
1943 (goto-char (- (point-max) pos)))
1944 (delete-region beg (point))
1945 (indent-to indent)
1946 ;; If initial point was within line's indentation,
1947 ;; position after the indentation. Else stay at same point in text.
1948 (if (> (- (point-max) pos) (point))
1949 (goto-char (- (point-max) pos))))
1950 ;; save-excursion is necessary because things break if the hook
1951 ;; changes point or mark
1952 (save-excursion
1953 (run-hooks 'c++-special-indent-hook))
1954 shift-amt))
1955
1956 (defun c++-cont-indent (ipnt char lim)
1957 "Calculate the indentation for a continued statement.
1958 IPNT is the indentation point; CHAR is the character before the
1959 indentation point, excluding any intervening whitespace; LIM is the
1960 minimum point to search backwards to."
1961 (let ((charlist '(nil ?\000 ?\, ?\; ?\} ?\: ?\{))
1962 streamop-pos here)
1963 (goto-char ipnt)
1964 (c++-backward-syntactic-ws lim)
1965 (if (not (memq char charlist))
1966 ;; This line is continuation of preceding line's statement
1967 (progn
1968 (c-backward-to-start-of-continued-exp lim)
1969 ;; take care of << and >> while in streams
1970 (setq here (point))
1971 (if (save-excursion
1972 (and (progn (goto-char ipnt)
1973 (looking-at "[ \t]*\\(<<\\|>>\\)"))
1974 (progn (goto-char here)
1975 (skip-chars-forward "^><\n")
1976 (setq streamop-pos (current-column))
1977 (looking-at "\\(<<\\|>>\\)"))))
1978 streamop-pos
1979 (+ (current-column)
1980 ;; prevent repeated continued indentation
1981 (if (save-excursion
1982 (beginning-of-line 1)
1983 (c++-backward-syntactic-ws lim)
1984 (memq (preceding-char) charlist))
1985 c-continued-statement-offset
1986 ;; the following statements *do* indent even
1987 ;; for single statements (are there others?)
1988 (if (looking-at "\\(do\\|else\\|for\\|if\\|while\\)\\b")
1989 c-continued-statement-offset
1990 ;; else may be a continued statement inside
1991 ;; a simple for/else/while/if/do loop
1992 (beginning-of-line 1)
1993 (forward-char -1)
1994 (c++-backward-syntactic-ws lim)
1995 (c-backward-to-start-of-continued-exp lim)
1996 (if (looking-at "\\(do\\|else\\|for\\|if\\|while\\)\\b")
1997 c-continued-statement-offset
1998 0)))
1999 (save-excursion
2000 (goto-char ipnt)
2001 (skip-chars-forward " \t")
2002 (cond
2003 ((= (following-char) ?\{)
2004 c-continued-brace-offset)
2005 ((and (= (following-char) ?\})
2006 (progn (forward-char 1)
2007 (c++-at-top-level-p nil lim)))
2008 (- c-continued-statement-offset))
2009 (t 0))))))
2010 nil)))
2011
2012 (defun c++-calculate-indent (&optional parse-start bod)
2013 "Return appropriate indentation for current line as C++ code.
2014 In usual case returns an integer: the column to indent to.
2015 Returns nil if line starts inside a string, t if in a comment.
2016 Optional PARSE-START is the location to start parsing, and optional
2017 BOD is the beginning of the C++ definition."
2018 (save-excursion
2019 (beginning-of-line)
2020 (let ((indent-point (point))
2021 (case-fold-search nil)
2022 state do-indentation literal in-meminit-p
2023 containing-sexp streamop-pos char-before-ip
2024 (inclass-shift 0) inclass-depth inclass-unshift
2025 (bod (or bod (c++-point 'bod))))
2026 (if parse-start
2027 (goto-char parse-start)
2028 (goto-char bod))
2029 (setq parse-start (point)
2030 state (c++-parse-state indent-point)
2031 containing-sexp (nth 1 state))
2032 ;; it is possible that c++-defun-header-weak could not find the
2033 ;; beginning of the C++ definition. The following code attempts
2034 ;; to work around this. It is probably better to just use
2035 ;; c++-match-header-strongly, but there are performance questions
2036 (if (null state)
2037 (let* ((c++-match-header-strongly t)
2038 (bod (c++-point 'bod)))
2039 (goto-char bod)
2040 (setq state (c++-parse-state indent-point)
2041 containing-sexp (nth 1 state)
2042 parse-start (point))))
2043 (setq literal (c++-in-literal bod))
2044 ;; cache char before indent point
2045 (save-excursion
2046 (goto-char indent-point)
2047 (c++-backward-syntactic-ws bod)
2048 (setq char-before-ip (preceding-char)))
2049 (cond
2050 ;; CASE 1: in a string.
2051 ((memq literal '(string)) nil)
2052 ;; CASE 2: in a C or C++ style comment.
2053 ((memq literal '(c c++)) t)
2054 ;; CASE 3: Line is at top level. May be comment-only line,
2055 ;; data or function definition, or may be function argument
2056 ;; declaration or member initialization. Indent like the
2057 ;; previous top level line unless:
2058 ;;
2059 ;; 1. the previous line ends in a closeparen without
2060 ;; semicolon, in which case this line is the first
2061 ;; argument declaration or member initialization, or
2062 ;;
2063 ;; 2. the previous line ends with a closeparen
2064 ;; (closebrace), optional spaces, and a semicolon, in
2065 ;; which case this line follows a multiline function
2066 ;; declaration (class definition), or
2067 ;;
2068 ;; 3. the previous line begins with a colon, in which
2069 ;; case this is the second line of member inits. It is
2070 ;; assumed that arg decls and member inits are not mixed.
2071 ;;
2072 ((setq inclass-depth (c++-at-top-level-p t bod))
2073 (+
2074 ;; add an offset if we are inside a class defun body, i.e. we
2075 ;; are at the top level, but only wrt a containing class
2076 (let ((shift/level (+ c-indent-level c-brace-imaginary-offset)))
2077 (setq inclass-shift (* shift/level inclass-depth)
2078 inclass-unshift (* shift/level (max 0 (1- inclass-depth))))
2079 inclass-shift)
2080 (progn
2081 (goto-char indent-point)
2082 (skip-chars-forward " \t")
2083 (cond
2084 ;;
2085 ((or (= (following-char) ?{)
2086 (progn
2087 (c++-backward-syntactic-ws parse-start)
2088 (bobp)))
2089 0)
2090 ;; first arg decl or member init
2091 ((c++-in-function-p)
2092 (goto-char indent-point)
2093 (skip-chars-forward " \t")
2094 (if (= (following-char) ?:)
2095 c++-member-init-indent
2096 c-argdecl-indent))
2097 ;;
2098 ((progn
2099 (if (= (preceding-char) ?\;)
2100 (progn
2101 (backward-char 1)
2102 (skip-chars-backward " \t")))
2103 ;; may be first line after a hanging member init colon.
2104 ;; check to be sure its not a scope operator meaning we
2105 ;; are inside a member def
2106 (or (= (preceding-char) ?:)
2107 (save-excursion
2108 (forward-line 1)
2109 (skip-chars-forward " \t")
2110 (or (eobp) (forward-char 1))
2111 (and (= (preceding-char) ?:)
2112 (/= (following-char) ?:)))
2113 (save-excursion
2114 (and (= (preceding-char) ?,)
2115 (let ((bol (c++-point 'bol)))
2116 (skip-chars-backward "^:" bol)
2117 (= (preceding-char) ?:))
2118 (not (c++-in-parens-p))
2119 (progn
2120 (forward-char -1)
2121 (skip-chars-backward " \t")
2122 (not (bolp)))
2123 ;; make sure its not a multiple inheritance
2124 ;; continuation line
2125 (progn
2126 (beginning-of-line)
2127 (not (looking-at c++-inher-key)))
2128 ))))
2129 ;; check to see if we're looking at a member init, or
2130 ;; access specifier
2131 (if (progn
2132 (beginning-of-line)
2133 (skip-chars-forward " \t")
2134 (looking-at c++-access-key))
2135 ;; access specifier. class defun opening brace may
2136 ;; not be in col zero, and derived classes could be
2137 ;; on a separate line than class intro
2138 (progn
2139 (goto-char (or containing-sexp bod))
2140 (beginning-of-line)
2141 (skip-chars-forward " \t")
2142 (if (looking-at
2143 ":[ \t]*\\<\\(public\\|protected\\|private\\)\\>")
2144 (forward-line -1))
2145 (- (current-indentation)
2146 ;; remove some nested inclass indentation
2147 inclass-unshift))
2148 ;; member init, so add offset. add additional offset if
2149 ;; looking at line with just a member init colon
2150 (+ c++-member-init-indent
2151 (if (looking-at ":[ \t]*$")
2152 (or c++-continued-member-init-offset 0) 0))))
2153 ((or (= (preceding-char) ?})
2154 (= (preceding-char) ?\))
2155 (save-excursion
2156 (beginning-of-line)
2157 (looking-at "[ \t]*\\<friend\\>")))
2158 ;; indentation of class defun opening brace may not be
2159 ;; zero
2160 (goto-char (or containing-sexp bod))
2161 (- (current-indentation)
2162 ;; remove some nested inclass indentation
2163 inclass-unshift))
2164 ;; cont arg decls or member inits. we might be inside a
2165 ;; K&R C arg decl
2166 ((save-excursion
2167 (while (and (< bod (point))
2168 (memq (preceding-char) '(?\, ?\;)))
2169 (beginning-of-line)
2170 (c++-backward-syntactic-ws bod))
2171 (and (eq major-mode 'c++-c-mode)
2172 (= (preceding-char) ?\))))
2173 (+ c-argdecl-indent
2174 (progn
2175 (goto-char indent-point)
2176 (c++-backward-syntactic-ws bod)
2177 (if (= (preceding-char) ?,)
2178 c-continued-statement-offset
2179 0))))
2180 ((progn
2181 (beginning-of-line)
2182 (skip-chars-forward " \t")
2183 (or (memq (c++-in-literal bod) '(c c++))
2184 (looking-at "/[/*]")))
2185 0)
2186 ;; are we looking at the first member init?
2187 ((and (= (following-char) ?:)
2188 (save-excursion
2189 (c++-backward-syntactic-ws bod)
2190 (= (preceding-char) ?\))))
2191 (if c++-continued-member-init-offset
2192 (+ (current-indentation)
2193 c++-continued-member-init-offset)
2194 (progn
2195 (forward-char 1)
2196 (skip-chars-forward " \t")
2197 (- (current-column)
2198 inclass-shift))))
2199 ;; else first check to see if its a multiple inheritance
2200 ;; continuation line, but not a K&R C arg decl
2201 ((and (not (eq major-mode 'c++-c-mode))
2202 (looking-at c++-inher-key))
2203 (if (= char-before-ip ?,)
2204 (progn (goto-char (match-end 0))
2205 (current-column))
2206 ;; nope, its probably a nested class
2207 0))
2208 ;; we might be looking at the opening brace of a class
2209 ;; defun
2210 ((= (following-char) ?\{)
2211 ;; indentation of opening brace may not be zero
2212 (- (current-indentation)
2213 ;; remove some nested inclass indentation
2214 inclass-unshift))
2215 ((eolp)
2216 ;; looking at a blank line, indent next line to zero
2217 0)
2218 ;; at beginning of buffer, if nothing else, indent to zero
2219 ((save-excursion
2220 (goto-char indent-point)
2221 (beginning-of-line)
2222 (bobp))
2223 0)
2224 ;; this could be a compound statement, but make sure its
2225 ;; not a member init list
2226 ((save-excursion
2227 (goto-char indent-point)
2228 (c++-backward-syntactic-ws bod)
2229 (and (= (preceding-char) ?,)
2230 (save-excursion
2231 (while (and (< bod (point))
2232 (= (preceding-char) ?,))
2233 (beginning-of-line)
2234 (c++-backward-syntactic-ws bod))
2235 (forward-line 1)
2236 (not (setq in-meminit-p (looking-at "[ \t]*:"))))))
2237 c-continued-statement-offset)
2238 (t
2239 (if (c++-in-parens-p)
2240 ;; we are perhaps inside a member init call
2241 (while (and (c++-in-parens-p)
2242 (< bod (point)))
2243 (forward-line -1)
2244 (skip-chars-forward " \t")))
2245 ;; check to be sure that we're not on the first line of
2246 ;; the member init list
2247 (if (and (= (following-char) ?:)
2248 (save-excursion
2249 (c++-backward-syntactic-ws bod)
2250 (= (preceding-char) ?\))))
2251 (progn
2252 (forward-char 1)
2253 (skip-chars-forward " \t")))
2254 ;; skip to start of compound statement, but only if we're
2255 ;; not in a member initialization list
2256 (if (not in-meminit-p)
2257 (let ((ipnt (point)))
2258 (c++-backward-syntactic-ws bod)
2259 (while (and (= (preceding-char) ?,)
2260 (< bod (point)))
2261 (beginning-of-line)
2262 (skip-chars-forward " \t")
2263 (setq ipnt (point))
2264 (c++-backward-syntactic-ws bod))
2265 (goto-char ipnt)))
2266 ;; subtract inclass-shift since its already incorporated
2267 ;; by default in current-column
2268 (- (current-column) inclass-shift)
2269 )))))
2270 ;; CASE 4: line is expression, not statement. indent to just
2271 ;; after the surrounding open -- unless empty arg list, in
2272 ;; which case we do what c++-empty-arglist-indent says to do.
2273 ((/= (char-after containing-sexp) ?{)
2274 (if (and c++-empty-arglist-indent
2275 (or c++-always-arglist-indent-p
2276 (null (nth 2 state))
2277 ;; indicates empty arg list. Use a heuristic: if
2278 ;; the first non-whitespace following left paren
2279 ;; on same line is not a comment, is not an empty
2280 ;; arglist.
2281 (save-excursion
2282 (goto-char (1+ containing-sexp))
2283 (looking-at "[ \t]*[/\n]"))))
2284 (progn
2285 (goto-char containing-sexp)
2286 (beginning-of-line)
2287 (skip-chars-forward " \t")
2288 (goto-char (min (+ (point) c++-empty-arglist-indent)
2289 (1+ containing-sexp)))
2290 (current-column))
2291 ;; In C-mode, we would always indent to one after the
2292 ;; left paren. Here, though, we may have an
2293 ;; empty-arglist, so we'll indent to the min of that
2294 ;; and the beginning of the first argument.
2295 (goto-char (1+ containing-sexp))
2296 ;; we want to skip any whitespace b/w open paren and
2297 ;; first argument. this handles while (thing) style
2298 ;; and while( thing ) style
2299 (skip-chars-forward " \t")
2300 (current-column)))
2301 ;; CASE 5: Statement. Find previous non-comment character.
2302 (t
2303 (or (c++-cont-indent indent-point char-before-ip containing-sexp)
2304 ;; This line may start a new statement, or it could
2305 ;; represent the while closure of a do/while construct
2306 (if (save-excursion
2307 (and (progn (goto-char indent-point)
2308 (skip-chars-forward " \t\n")
2309 (looking-at "while\\b"))
2310 (progn
2311 (c++-backward-to-start-of-do containing-sexp)
2312 (looking-at "do\\b"))
2313 (setq do-indentation (current-column))))
2314 do-indentation
2315 ;; this could be a case statement. if so we want to
2316 ;; indent it like the first case statement after a switch
2317 (if (save-excursion
2318 (goto-char indent-point)
2319 (skip-chars-forward " \t\n")
2320 (looking-at "\\(case[ \t]+.*\\|default[ \t]*\\):"))
2321 (progn
2322 (goto-char containing-sexp)
2323 (back-to-indentation)
2324 (+ (current-column) c-indent-level))
2325 ;; else, this is the start of a new statement
2326 ;; Position following last unclosed open.
2327 (goto-char containing-sexp)
2328 ;; Is line first statement after an open-brace?
2329 (or
2330 (and c++-relative-offset-p
2331 ;; If no, find that first statement and
2332 ;; indent like it.
2333 (save-excursion
2334 (forward-char 1)
2335 (while
2336 (progn
2337 (skip-chars-forward " \t\n")
2338 (looking-at
2339 (concat
2340 "#\\|/\\*\\|//"
2341 "\\|\\(case[ \t]+.*\\|default[ \t]*\\):"
2342 "\\|[a-zA-Z0-9_$]*:[^:]"
2343 "\\|friend[ \t]"
2344 c++-class-key
2345 "[ \t]")))
2346 ;; Skip over comments and labels
2347 ;; following openbrace.
2348 (cond
2349 ((= (following-char) ?\#)
2350 (forward-line 1))
2351 ((looking-at "/\\*")
2352 (search-forward "*/" nil 'move))
2353 ((looking-at
2354 (concat "//\\|friend[ \t]" c++-class-key
2355 "[ \t]"))
2356 (forward-line 1))
2357 ((looking-at "\\(case[ \t]+.*\\|default[ \t]*\\):")
2358 (forward-line 1))
2359 (t
2360 (re-search-forward ":[^:]" nil 'move))))
2361 ;; The first following code counts
2362 ;; if it is before the line we want to indent.
2363 (and (< (point) indent-point)
2364 (+ (current-column)
2365 (c++-compound-offset
2366 char-before-ip containing-sexp bod)))))
2367 ;; If no previous statement, indent it relative to
2368 ;; line brace is on. For open brace in column
2369 ;; zero, don't let statement start there too. If
2370 ;; c-indent-offset is zero, use c-brace-offset +
2371 ;; c-continued-statement-offset instead. For
2372 ;; open-braces not the first thing in a line, add
2373 ;; in c-brace-imaginary-offset.
2374 (+ (if (and (bolp) (zerop c-indent-level))
2375 (+ c-brace-offset c-continued-statement-offset)
2376 c-indent-level)
2377 ;; Move back over whitespace before the openbrace.
2378 ;; If openbrace is not first nonwhite thing on the line,
2379 ;; add the c-brace-imaginary-offset.
2380 (progn (skip-chars-backward " \t")
2381 (if (bolp) 0 c-brace-imaginary-offset))
2382 ;; If the openbrace is preceded by a parenthesized exp,
2383 ;; move to the beginning of that;
2384 ;; possibly a different line
2385 (progn
2386 (if (eq (preceding-char) ?\))
2387 (forward-sexp -1))
2388 ;; Get initial indentation of the line we are on.
2389 (current-indentation)))))))) ; end t outer cond
2390 ))))
2391
2392 (defun c++-calculate-c-indent-within-comment ()
2393 "Return the indentation amount for line, assuming that
2394 the current line is to be regarded as part of a block comment."
2395 (let (end stars indent)
2396 (save-excursion
2397 (beginning-of-line)
2398 (skip-chars-forward " \t")
2399 (setq stars (if (looking-at "\\*\\*?")
2400 (- (match-end 0) (match-beginning 0))
2401 0))
2402 (skip-chars-backward " \t\n")
2403 (setq end (point))
2404 (beginning-of-line)
2405 (skip-chars-forward " \t")
2406 (if (re-search-forward "/\\*[ \t]*" end t)
2407 (goto-char (+ (match-beginning 0)
2408 (cond
2409 (c++-C-block-comments-indent-p 0)
2410 ((= stars 1) 1)
2411 ((= stars 2) 0)
2412 (t (- (match-end 0) (match-beginning 0)))))))
2413 (current-column))))
2414
2415 (defun c++-comment-offset (col0-line-p indent)
2416 "Calculates and returns the comment-only line offset.
2417 Offset is based on the value of `c++-comment-only-line-offset', the
2418 argument COL0-LINE-P, and the current indentation INDENT."
2419 (let ((offset 0))
2420 (if col0-line-p
2421 ;; col0 means we need to look at the second member of the var's
2422 ;; list value. if value is not a list, then zero is used
2423 (if (listp c++-comment-only-line-offset)
2424 ;; it is a list, so second element must be nil or a number
2425 (setq offset
2426 (+ indent
2427 (or (car (cdr c++-comment-only-line-offset))
2428 (car c++-comment-only-line-offset)))))
2429 ;; not in column zero so indentation is car or value of variable
2430 (setq offset
2431 (+ indent
2432 (if (listp c++-comment-only-line-offset)
2433 (car c++-comment-only-line-offset)
2434 c++-comment-only-line-offset))))
2435 offset))
2436
2437 (defun c++-compound-offset (char-before-ip containing-sexp bod)
2438 "Calculates any addition offset due a comma separated compound statement.
2439 CHAR-BEFORE-IP is the character before the indentation point and
2440 CONTAINING-SEXP is the buffer position of the open brace or paren.
2441 BOD is the `beginning-of-defun' point."
2442 (cond
2443 ;; not a compound statement
2444 ((/= char-before-ip ?,) 0)
2445 ;; open brace could be at column zero == bod
2446 ((and (= containing-sexp bod)
2447 (or (let ((lim (progn
2448 (goto-char containing-sexp)
2449 (forward-line -1)
2450 (point))))
2451 (end-of-line)
2452 (c++-backward-syntactic-ws lim)
2453 (= (preceding-char) ?=))
2454 (progn
2455 (beginning-of-line)
2456 (looking-at "\\(^\\|[ \t]*\\)enum[ \t]"))
2457 ))
2458 0)
2459 ;; check for inside an enum
2460 ((let ((parse-sexp-ignore-comments t)
2461 in-enum-p)
2462 (goto-char containing-sexp)
2463 (while (< bod (point))
2464 (c++-backward-syntactic-ws)
2465 (if (memq (preceding-char) '(?\) ?\" ?\; ?\}))
2466 (goto-char bod)
2467 (forward-sexp -1)
2468 (if (looking-at "\\(enum[ \t\n]\\|\\[.*\\]\\)")
2469 (progn (goto-char bod)
2470 (setq in-enum-p t)))))
2471 in-enum-p)
2472 0)
2473 ;; assume we're not in a list of enums or static array elems
2474 (t c-continued-statement-offset)
2475 ))
2476
2477
2478
2479 ;; ======================================================================
2480 ;; defuns to look backwards for things
2481 ;; ======================================================================
2482
2483 (defun c++-backward-to-start-of-do (&optional limit)
2484 "Move to the start of the last ``unbalanced'' do."
2485 (let ((do-level 1)
2486 (case-fold-search nil)
2487 (limit (or limit (c++-point 'bod))))
2488 (while (not (zerop do-level))
2489 ;; we protect this call because trying to execute this when the
2490 ;; while is not associated with a do will throw an error
2491 (condition-case err
2492 (progn
2493 (backward-sexp 1)
2494 (cond
2495 ((memq (c++-in-literal limit) '(c c++)))
2496 ((looking-at "while\\b")
2497 (setq do-level (1+ do-level)))
2498 ((looking-at "do\\b")
2499 (setq do-level (1- do-level)))
2500 ((< (point) limit)
2501 (setq do-level 0)
2502 (goto-char limit))))
2503 (error
2504 (goto-char limit)
2505 (setq do-level 0))))))
2506
2507 (defun c++-backward-to-start-of-if (&optional limit)
2508 "Move to the start of the last ``unbalanced'' if."
2509 (let ((if-level 1)
2510 (case-fold-search nil)
2511 (limit (or limit (c++-point 'bod))))
2512 (while (and (not (bobp))
2513 (not (zerop if-level)))
2514 (c++-backward-syntactic-ws)
2515 (c++-backward-sexp 1)
2516 (cond ((looking-at "else\\b")
2517 (setq if-level (1+ if-level)))
2518 ((looking-at "if\\b")
2519 (setq if-level (1- if-level)))
2520 ((< (point) limit)
2521 (setq if-level 0)
2522 (goto-char limit))))))
2523
2524 (defun c++-auto-newline ()
2525 "Insert a newline iff we're not in a literal.
2526 Literals are defined as being inside a C or C++ style comment or open
2527 string according to mode's syntax."
2528 (let ((bod (c++-point 'bod)))
2529 (and c++-auto-newline
2530 (not (c++-in-literal bod))
2531 (not (newline)))))
2532
2533 (defun c++-point (position)
2534 "Returns the value of point at certain commonly referenced POSITIONs.
2535 POSITION can be one of the following symbols:
2536 `bol' -- beginning of line
2537 `eol' -- end of line
2538 `bod' -- beginning of defun
2539 `boi' -- back to indentation
2540 This function does not modify point or mark."
2541 (let ((here (point)) bufpos)
2542 (cond
2543 ((eq position 'bol) (beginning-of-line))
2544 ((eq position 'eol) (end-of-line))
2545 ((eq position 'bod) (c++-beginning-of-defun))
2546 ((eq position 'boi) (back-to-indentation))
2547 )
2548 (setq bufpos (point))
2549 (goto-char here)
2550 bufpos))
2551
2552
2553 ;; ======================================================================
2554 ;; defuns for "macroizations" -- making C++ parameterized types via macros
2555 ;; ======================================================================
2556 (defun c++-macroize-region (from to arg)
2557 "Insert backslashes at end of every line in region.
2558 Useful for defining cpp macros. If called with a prefix argument,
2559 it will remove trailing backslashes."
2560 (interactive "r\nP")
2561 (save-excursion
2562 (goto-char from)
2563 (beginning-of-line 1)
2564 (let ((line (count-lines (point-min) (point)))
2565 (to-line (save-excursion (goto-char to)
2566 (count-lines (point-min) (point)))))
2567 (while (< line to-line)
2568 (c++-backslashify-current-line (null arg))
2569 (forward-line 1) (setq line (1+ line))))))
2570
2571 (defun c++-backslashify-current-line (doit)
2572 "Backslashifies current line."
2573 (end-of-line 1)
2574 (cond
2575 (doit
2576 ;; Note that "\\\\" is needed to get one backslash.
2577 (if (not (save-excursion (forward-char -1) (looking-at "\\\\")))
2578 (progn
2579 (if (>= (current-column) c++-default-macroize-column)
2580 (insert " \\")
2581 (while (<= (current-column) c++-default-macroize-column)
2582 (insert "\t") (end-of-line))
2583 (delete-char -1)
2584 (while (< (current-column) c++-default-macroize-column)
2585 (insert " ") (end-of-line))
2586 (insert "\\")))))
2587 (t
2588 (forward-char -1)
2589 (if (looking-at "\\\\")
2590 (progn (skip-chars-backward " \t")
2591 (kill-line))))))
2592
2593
2594 ;; ======================================================================
2595 ;; defuns for commenting out multiple lines.
2596 ;; ======================================================================
2597 (defun c++-comment-region (beg end)
2598 "Comment out all lines in a region between mark and current point by
2599 inserting `comment-start' in front of each line."
2600 (interactive "*r")
2601 (save-excursion
2602 (save-restriction
2603 (narrow-to-region
2604 (progn (goto-char beg) (beginning-of-line) (point))
2605 (progn (goto-char end) (or (bolp) (forward-line 1)) (point)))
2606 (goto-char (point-min))
2607 (while (not (eobp))
2608 (insert comment-start)
2609 (forward-line 1))
2610 (if (eq major-mode 'c++-c-mode)
2611 (insert comment-end)))))
2612
2613 (defun c++-uncomment-region (beg end)
2614 "Uncomment all lines in region between mark and current point by deleting
2615 the leading ``// '' from each line, if any."
2616 (interactive "*r")
2617 (save-excursion
2618 (save-restriction
2619 (narrow-to-region
2620 (progn (goto-char beg) (beginning-of-line) (point))
2621 (progn (goto-char end) (forward-line 1) (point)))
2622 (goto-char (point-min))
2623 (let ((comment-regexp
2624 (if (eq major-mode 'c++-c-mode)
2625 (concat "\\s *\\(" (regexp-quote comment-start)
2626 "\\|" (regexp-quote comment-end)
2627 "\\)")
2628 (concat "\\s *" (regexp-quote comment-start)))))
2629 (while (not (eobp))
2630 (if (looking-at comment-regexp)
2631 (delete-region (match-beginning 0) (match-end 0)))
2632 (forward-line 1))))))
2633
2634
2635 ;; ======================================================================
2636 ;; grammar parsing
2637 ;; ======================================================================
2638
2639 ;;; Below are two regular expressions that attempt to match defuns
2640 ;;; "strongly" and "weakly." The strong one almost reconstructs the
2641 ;;; grammar of C++; the weak one just figures anything id or curly on
2642 ;;; the left begins a defun. The constant "c++-match-header-strongly"
2643 ;;; determines which to use; the default is the weak one.
2644
2645 (defvar c++-match-header-strongly nil
2646 "*If nil, use `c++-defun-header-weak' to identify beginning of definitions,
2647 if non-nil, use `c++-defun-header-strong'.")
2648
2649 (defvar c++-defun-header-strong-struct-equivs
2650 "\\(class\\|struct\\|union\\|enum\\)"
2651 "Regexp to match names of structure declaration blocks in C++")
2652
2653 (defconst c++-defun-header-strong
2654 (let*
2655 (; valid identifiers
2656 ;; There's a real weirdness here -- if I switch the below
2657 (id "\\(\\w\\|_\\)+")
2658 ;; to be
2659 ;; (id "\\(_\\|\\w\\)+")
2660 ;; things no longer work right. Try it and see!
2661
2662 ; overloadable operators
2663 (op-sym1
2664 "[---+*/%^&|~!=<>]\\|[---+*/%^&|<>=!]=\\|<<=?\\|>>=?")
2665 (op-sym2
2666 "&&\\|||\\|\\+\\+\\|--\\|()\\|\\[\\]")
2667 (op-sym (concat "\\(" op-sym1 "\\|" op-sym2 "\\)"))
2668 ; whitespace
2669 (middle "[^\\*]*\\(\\*+[^/\\*][^\\*]*\\)*")
2670 (c-comment (concat "/\\*" middle "\\*+/"))
2671 (wh (concat "\\(\\s \\|\n\\|//.*$\\|" c-comment "\\)"))
2672 (wh-opt (concat wh "*"))
2673 (wh-nec (concat wh "+"))
2674 (oper (concat "\\(" "operator" "\\("
2675 wh-opt op-sym "\\|" wh-nec id "\\)" "\\)"))
2676 (dcl-list "([^():]*)")
2677 (func-name (concat "\\(" oper "\\|" id "::" id "\\|" id "\\)"))
2678 (inits
2679 (concat "\\(:"
2680 "\\(" wh-opt id "(.*\\()" wh-opt "," "\\)\\)*"
2681 wh-opt id "(.*)" wh-opt "{"
2682 "\\|" wh-opt "{\\)"))
2683 (type-name (concat
2684 "\\(" c++-defun-header-strong-struct-equivs wh-nec "\\)?"
2685 id))
2686 (type (concat "\\(const" wh-nec "\\)?"
2687 "\\(" type-name "\\|" type-name wh-opt "\\*+" "\\|"
2688 type-name wh-opt "&" "\\)"))
2689 (modifier "\\(inline\\|virtual\\|overload\\|auto\\|static\\)")
2690 (modifiers (concat "\\(" modifier wh-nec "\\)*"))
2691 (func-header
2692 ;; type arg-dcl
2693 (concat modifiers type wh-nec func-name wh-opt dcl-list wh-opt inits))
2694 (inherit (concat "\\(:" wh-opt "\\(public\\|protected\\|private\\)?"
2695 wh-nec id "\\)"))
2696 (cs-header (concat
2697 c++-defun-header-strong-struct-equivs
2698 wh-nec id wh-opt inherit "?" wh-opt "{")))
2699 (concat "^\\(" func-header "\\|" cs-header "\\)"))
2700 "Strongly-defined regexp to match beginning of structure or
2701 function definition.")
2702
2703
2704 ;; This part has to do with recognizing defuns.
2705
2706 ;; The weak convention we will use is that a defun begins any time
2707 ;; there is a left curly brace, or some identifier on the left margin,
2708 ;; followed by a left curly somewhere on the line. (This will also
2709 ;; incorrectly match some continued strings, but this is after all
2710 ;; just a weak heuristic.) Suggestions for improvement (short of the
2711 ;; strong scheme shown above) are welcomed.
2712
2713 (defconst c++-defun-header-weak "^{\\|^[_a-zA-Z].*{"
2714 "Weakly-defined regexp to match beginning of structure or function
2715 definition.")
2716
2717
2718 (defun c++-beginning-of-defun (&optional arg)
2719 "Find the beginning of the C++ function or class."
2720 (interactive "_p")
2721 (if (not arg) (setq arg 1))
2722 (let ((c++-defun-header (if c++-match-header-strongly
2723 c++-defun-header-strong
2724 c++-defun-header-weak)))
2725 (cond
2726 ((or (= arg 0) (and (> arg 0) (bobp))) nil)
2727 ((and (not (looking-at c++-defun-header))
2728 (let ((curr-pos (point))
2729 (open-pos (if (search-forward "{" nil 'move)
2730 (point)))
2731 (beg-pos
2732 (if (re-search-backward c++-defun-header nil 'move)
2733 (match-beginning 0))))
2734 (if (and open-pos beg-pos
2735 (< beg-pos curr-pos)
2736 (> open-pos curr-pos))
2737 (progn
2738 (goto-char beg-pos)
2739 (if (= arg 1) t nil));; Are we done?
2740 (goto-char curr-pos)
2741 nil))))
2742 (t
2743 (if (and (looking-at c++-defun-header) (not (bobp)))
2744 (forward-char (if (< arg 0) 1 -1)))
2745 (and (re-search-backward c++-defun-header nil 'move (or arg 1))
2746 (goto-char (match-beginning 0)))))))
2747
2748
2749 (defun c++-end-of-defun (arg)
2750 "Find the end of the C++ function or class."
2751 (interactive "_p")
2752 (let ((c++-defun-header (if c++-match-header-strongly
2753 c++-defun-header-strong
2754 c++-defun-header-weak))
2755 (parse-sexp-ignore-comments t))
2756 (if (and (eobp) (> arg 0))
2757 nil
2758 (if (and (> arg 0) (looking-at c++-defun-header)) (forward-char 1))
2759 (let ((pos (point)))
2760 (c++-beginning-of-defun
2761 (if (< arg 0)
2762 (- (- arg (if (eobp) 0 1)))
2763 arg))
2764 (if (and (< arg 0) (bobp))
2765 t
2766 (if (re-search-forward c++-defun-header nil 'move)
2767 (progn (forward-char -1)
2768 (forward-sexp)
2769 (beginning-of-line 2)))
2770 (if (and (= pos (point))
2771 (re-search-forward c++-defun-header nil 'move))
2772 (c++-end-of-defun 1))))
2773 t)))
2774
2775 (defun c++-indent-defun ()
2776 "Indents the current function def, struct or class declaration."
2777 (interactive)
2778 (let ((restore (point)))
2779 (c++-end-of-defun 1)
2780 (beginning-of-line 1)
2781 (let ((end (point-marker)))
2782 (c++-beginning-of-defun)
2783 (while (and (< (point) end))
2784 (c++-indent-line)
2785 (forward-line 1)
2786 (beginning-of-line 1))
2787 (set-marker end nil))
2788 (goto-char restore)))
2789
2790
2791 ;; ======================================================================
2792 ;; defuns for submitting bug reports
2793 ;; ======================================================================
2794 (defconst c++-version "2.353"
2795 "c++-mode version number.")
2796 (defconst c++-mode-help-address "c++-mode-help@anthem.nlm.nih.gov"
2797 "Address accepting submission of bug reports.")
2798
2799 (defun c++-version ()
2800 "Echo the current version of c++-mode."
2801 (interactive)
2802 (message "Using c++-mode.el %s" c++-version))
2803
2804 (defun c++-submit-bug-report ()
2805 "Submit via mail a bug report on c++-mode."
2806 (interactive)
2807 (require 'reporter)
2808 (and
2809 (y-or-n-p "Do you want to submit a report on c++-mode? ")
2810 (reporter-submit-bug-report
2811 c++-mode-help-address
2812 (concat "c++-mode.el " c++-version " (editing "
2813 (if (eq major-mode 'c++-mode) "C++" "C")
2814 " code)")
2815 (list
2816 'c++-emacs-features
2817 'c++-C-block-comments-indent-p
2818 'c++-access-specifier-offset
2819 'c++-always-arglist-indent-p
2820 'c++-auto-hungry-initial-state
2821 'c++-auto-hungry-toggle
2822 'c++-auto-newline
2823 'c++-backscan-limit
2824 'c++-block-close-brace-offset
2825 'c++-cleanup-list
2826 'c++-comment-only-line-offset
2827 'c++-continued-member-init-offset
2828 'c++-default-macroize-column
2829 'c++-defun-header-strong-struct-equivs
2830 'c++-delete-function
2831 'c++-electric-pound-behavior
2832 'c++-empty-arglist-indent
2833 'c++-friend-offset
2834 'c++-hanging-braces
2835 'c++-hanging-member-init-colon
2836 'c++-hungry-delete-key
2837 'c++-match-header-strongly
2838 'c++-member-init-indent
2839 'c++-paren-as-block-close-p
2840 'c++-relative-offset-p
2841 'c++-tab-always-indent
2842 'c++-untame-characters
2843 'c-argdecl-indent
2844 'c-brace-imaginary-offset
2845 'c-brace-offset
2846 'c-continued-brace-offset
2847 'c-continued-statement-offset
2848 'c-indent-level
2849 'c-label-offset
2850 'tab-width
2851 )
2852 (function
2853 (lambda ()
2854 (insert
2855 (if c++-special-indent-hook
2856 (concat "\n@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"
2857 "c++-special-indent-hook is set to '"
2858 (format "%s" c++-special-indent-hook)
2859 ".\nPerhaps this is your problem?\n"
2860 "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n\n")
2861 "\n")
2862 )))
2863 )))
2864
2865
2866 ;; this is sometimes useful
2867 (provide 'c++-mode)
2868
2869 ;;; c++-mode.el ends here