comparison lisp/modes/cc-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 ac2d302a0011
comparison
equal deleted inserted replaced
-1:000000000000 0:376386a54a3c
1 ;;; cc-mode.el --- major mode for editing C, C++, and Objective-C code
2
3 ;; Copyright (C) 1985, 87, 92, 93, 94, 95, 96 Free Software Foundation, Inc.
4
5 ;; Authors: 1992-1996 Barry A. Warsaw
6 ;; 1987 Dave Detlefs and Stewart Clamen
7 ;; 1985 Richard M. Stallman
8 ;; Created: a long, long, time ago. adapted from the original c-mode.el
9 ;; Version: 4.282
10 ;; Last Modified: 1996/02/09 23:15:14
11 ;; Keywords: c languages oop
12
13 ;; NOTE: Read the commentary below for the right way to submit bug reports!
14 ;; NOTE: See the accompanying texinfo manual for details on using this mode!
15
16 ;; This file is part of GNU Emacs.
17
18 ;; GNU Emacs is free software; you can redistribute it and/or modify
19 ;; it under the terms of the GNU General Public License as published by
20 ;; the Free Software Foundation; either version 2, or (at your option)
21 ;; any later version.
22
23 ;; GNU Emacs is distributed in the hope that it will be useful,
24 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
25 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 ;; GNU General Public License for more details.
27
28 ;; You should have received a copy of the GNU General Public License
29 ;; along with GNU Emacs; see the file COPYING. If not, write to the
30 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
31 ;; Boston, MA 02111-1307, USA.
32
33 ;;; Commentary:
34
35 ;; This package provides modes in GNU Emacs for editing C, C++,
36 ;; Objective-C, and Java code. It is intended to be a replacement for
37 ;; c-mode.el (a.k.a. BOCM -- Boring Old C-Mode), and c++-mode.el
38 ;; (a.k.a cplus-md.el and cplus-md1.el), both of which are ancestors
39 ;; of this file. A number of important improvements have been made,
40 ;; briefly: complete K&R C, ANSI C, `ARM' C++, Objective-C, and Java
41 ;; support with consistent indentation across all modes, more
42 ;; intuitive indentation controlling variables, compatibility across
43 ;; all known Emacsen, nice new features, and tons of bug fixes. This
44 ;; package is called "cc-mode" to distinguish it from its ancestors,
45 ;; but there really is no top-level cc-mode. Usage and programming
46 ;; details are contained in an accompanying texinfo manual.
47
48 ;; To submit bug reports, type "C-c C-b". These will be sent to
49 ;; bug-gnu-emacs@prep.ai.mit.edu and I'll read about them there (this
50 ;; is mirrored as the Usenet newsgroup gnu.emacs.bug). Questions can
51 ;; sent to help-gnu-emacs@prep.ai.mit.edu (mirrored as
52 ;; gnu.emacs.help). Please do not send bugs or questions to my
53 ;; personal account.
54
55 ;; YOU CAN IGNORE ALL BYTE-COMPILER WARNINGS. They are the result of
56 ;; the multi-Emacsen support. Emacs 19 (from the FSF), XEmacs 19
57 ;; (formerly Lucid Emacs), and GNU Emacs 18 all do things differently
58 ;; and there's no way to shut the byte-compiler up at the necessary
59 ;; granularity. Let me say this again: YOU CAN IGNORE ALL
60 ;; BYTE-COMPILER WARNINGS (you'd be surprised at how many people don't
61 ;; follow this advice :-).
62
63 ;; If your Emacs is dumped with c-mode.el and/or c++-mode.el, you will
64 ;; need to add the following to your .emacs file before any other
65 ;; reference to c-mode or c++-mode:
66 ;;
67 ;; (fmakunbound 'c-mode)
68 ;; (makunbound 'c-mode-map)
69 ;; (fmakunbound 'c++-mode)
70 ;; (makunbound 'c++-mode-map)
71 ;; (makunbound 'c-style-alist)
72
73 ;; If your Emacs comes with cc-mode already (and as of 18-Jan-1996,
74 ;; XEmacs 19.13 and Emacs 19.30 both do), you only need to add the
75 ;; following to use the latest version of cc-mode:
76 ;;
77 ;; (load "cc-mode")
78 ;;
79 ;; Make sure the new version is earlier on your load-path.
80
81 ;; There are four major mode entry points provided by this package,
82 ;; one for editing C++ code, one for editing C code (both K&R and
83 ;; ANSI), one for editing Objective-C code, and one for editing Java
84 ;; code. The commands are M-x c-mode, M-x c++-mode, M-x objc-mode,
85 ;; and M-x java-mode.
86
87 ;; If you are using an old version of Emacs which does not come
88 ;; with cc-mode.el, you will need to do these things
89 ;; to use it:
90 ;;
91 ;; (autoload 'c++-mode "cc-mode" "C++ Editing Mode" t)
92 ;; (autoload 'c-mode "cc-mode" "C Editing Mode" t)
93 ;; (autoload 'objc-mode "cc-mode" "Objective-C Editing Mode" t)
94 ;; (autoload 'java-mode "cc-mode" "Java Editing Mode" t)
95 ;; (setq auto-mode-alist
96 ;; (append '(("\\.C$" . c++-mode)
97 ;; ("\\.cc$" . c++-mode)
98 ;; ("\\.c$" . c-mode)
99 ;; ("\\.h$" . c-mode)
100 ;; ("\\.m$" . objc-mode)
101 ;; ("\\.java$" . java-mode)
102 ;; ) auto-mode-alist))
103 ;;
104 ;; You do not need these changes in Emacs versions that come with cc-mode.
105
106 ;; Many, many thanks go out to all the folks on the beta test list.
107 ;; Without their patience, testing, insight, code contributions, and
108 ;; encouragement cc-mode.el would be a far inferior package.
109
110 ;; Anonymous ftp URL:
111 ;;
112 ;; ftp://ftp.python.org/pub/emacs/cc-mode.tar.gz
113
114 ;;; Code:
115
116
117 ;; user definable variables
118 ;; vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
119
120 (defvar c-inhibit-startup-warnings-p nil
121 "*If non-nil, inhibits start up compatibility warnings.")
122 (defvar c-strict-syntax-p nil
123 "*If non-nil, all syntactic symbols must be found in `c-offsets-alist'.
124 If the syntactic symbol for a particular line does not match a symbol
125 in the offsets alist, an error is generated, otherwise no error is
126 reported and the syntactic symbol is ignored.")
127 (defvar c-echo-syntactic-information-p nil
128 "*If non-nil, syntactic info is echoed when the line is indented.")
129 (defvar c-basic-offset 4
130 "*Amount of basic offset used by + and - symbols in `c-offsets-alist'.")
131
132 (defvar c-offsets-alist
133 '((string . -1000)
134 (c . c-lineup-C-comments)
135 (defun-open . 0)
136 (defun-close . 0)
137 (defun-block-intro . +)
138 (class-open . 0)
139 (class-close . 0)
140 (inline-open . +)
141 (inline-close . 0)
142 (ansi-funcdecl-cont . +)
143 (knr-argdecl-intro . +)
144 (knr-argdecl . 0)
145 (topmost-intro . 0)
146 (topmost-intro-cont . 0)
147 (member-init-intro . +)
148 (member-init-cont . 0)
149 (inher-intro . +)
150 (inher-cont . c-lineup-multi-inher)
151 (block-open . 0)
152 (block-close . 0)
153 (brace-list-open . 0)
154 (brace-list-close . 0)
155 (brace-list-intro . +)
156 (brace-list-entry . 0)
157 (statement . 0)
158 ;; some people might prefer
159 ;;(statement . c-lineup-runin-statements)
160 (statement-cont . +)
161 ;; some people might prefer
162 ;;(statement-cont . c-lineup-math)
163 (statement-block-intro . +)
164 (statement-case-intro . +)
165 (statement-case-open . 0)
166 (substatement . +)
167 (substatement-open . +)
168 (case-label . 0)
169 (access-label . -)
170 (label . 2)
171 (do-while-closure . 0)
172 (else-clause . 0)
173 (comment-intro . c-lineup-comment)
174 (arglist-intro . +)
175 (arglist-cont . 0)
176 (arglist-cont-nonempty . c-lineup-arglist)
177 (arglist-close . +)
178 (stream-op . c-lineup-streamop)
179 (inclass . +)
180 (cpp-macro . -1000)
181 (friend . 0)
182 (objc-method-intro . -1000)
183 (objc-method-args-cont . c-lineup-ObjC-method-args)
184 (objc-method-call-cont . c-lineup-ObjC-method-call)
185 )
186 "*Association list of syntactic element symbols and indentation offsets.
187 As described below, each cons cell in this list has the form:
188
189 (SYNTACTIC-SYMBOL . OFFSET)
190
191 When a line is indented, cc-mode first determines the syntactic
192 context of the line by generating a list of symbols called syntactic
193 elements. This list can contain more than one syntactic element and
194 the global variable `c-syntactic-context' contains the context list
195 for the line being indented. Each element in this list is actually a
196 cons cell of the syntactic symbol and a buffer position. This buffer
197 position is called the relative indent point for the line. Some
198 syntactic symbols may not have a relative indent point associated with
199 them.
200
201 After the syntactic context list for a line is generated, cc-mode
202 calculates the absolute indentation for the line by looking at each
203 syntactic element in the list. First, it compares the syntactic
204 element against the SYNTACTIC-SYMBOL's in `c-offsets-alist'. When it
205 finds a match, it adds the OFFSET to the column of the relative indent
206 point. The sum of this calculation for each element in the syntactic
207 list is the absolute offset for line being indented.
208
209 If the syntactic element does not match any in the `c-offsets-alist',
210 an error is generated if `c-strict-syntax-p' is non-nil, otherwise
211 the element is ignored.
212
213 Actually, OFFSET can be an integer, a function, a variable, or one of
214 the following symbols: `+', `-', `++', `--', `*', or `/'. These
215 latter designate positive or negative multiples of `c-basic-offset',
216 respectively: *1, *-1, *2, *-2, *0.5, and *-0.5. If OFFSET is a
217 function, it is called with a single argument containing the cons of
218 the syntactic element symbol and the relative indent point. The
219 function should return an integer offset.
220
221 Here is the current list of valid syntactic element symbols:
222
223 string -- inside multi-line string
224 c -- inside a multi-line C style block comment
225 defun-open -- brace that opens a function definition
226 defun-close -- brace that closes a function definition
227 defun-block-intro -- the first line in a top-level defun
228 class-open -- brace that opens a class definition
229 class-close -- brace that closes a class definition
230 inline-open -- brace that opens an in-class inline method
231 inline-close -- brace that closes an in-class inline method
232 ansi-funcdecl-cont -- the nether region between an ANSI function
233 declaration and the defun opening brace
234 knr-argdecl-intro -- first line of a K&R C argument declaration
235 knr-argdecl -- subsequent lines in a K&R C argument declaration
236 topmost-intro -- the first line in a topmost construct definition
237 topmost-intro-cont -- topmost definition continuation lines
238 member-init-intro -- first line in a member initialization list
239 member-init-cont -- subsequent member initialization list lines
240 inher-intro -- first line of a multiple inheritance list
241 inher-cont -- subsequent multiple inheritance lines
242 block-open -- statement block open brace
243 block-close -- statement block close brace
244 brace-list-open -- open brace of an enum or static array list
245 brace-list-close -- close brace of an enum or static array list
246 brace-list-intro -- first line in an enum or static array list
247 brace-list-entry -- subsequent lines in an enum or static array list
248 statement -- a C/C++/ObjC statement
249 statement-cont -- a continuation of a C/C++/ObjC statement
250 statement-block-intro -- the first line in a new statement block
251 statement-case-intro -- the first line in a case `block'
252 statement-case-open -- the first line in a case block starting with brace
253 substatement -- the first line after an if/while/for/do/else
254 substatement-open -- the brace that opens a substatement block
255 case-label -- a case or default label
256 access-label -- C++ private/protected/public access label
257 label -- any non-special C/C++/ObjC label
258 do-while-closure -- the `while' that ends a do/while construct
259 else-clause -- the `else' of an if/else construct
260 comment-intro -- a line containing only a comment introduction
261 arglist-intro -- the first line in an argument list
262 arglist-cont -- subsequent argument list lines when no
263 arguments follow on the same line as the
264 the arglist opening paren
265 arglist-cont-nonempty -- subsequent argument list lines when at
266 least one argument follows on the same
267 line as the arglist opening paren
268 arglist-close -- the solo close paren of an argument list
269 stream-op -- lines continuing a stream operator construct
270 inclass -- the construct is nested inside a class definition
271 cpp-macro -- the start of a cpp macro
272 friend -- a C++ friend declaration
273 objc-method-intro -- the first line of an Objective-C method definition
274 objc-method-args-cont -- lines continuing an Objective-C method definition
275 objc-method-call-cont -- lines continuing an Objective-C method call
276 ")
277
278 (defvar c-tab-always-indent t
279 "*Controls the operation of the TAB key.
280 If t, hitting TAB always just indents the current line. If nil,
281 hitting TAB indents the current line if point is at the left margin or
282 in the line's indentation, otherwise it insert a real tab character.
283 If other than nil or t, then tab is inserted only within literals
284 -- defined as comments and strings -- and inside preprocessor
285 directives, but line is always reindented.
286
287 Note that indentation of lines containing only comments is also
288 controlled by the `c-comment-only-line-offset' variable.")
289
290 (defvar c-comment-only-line-offset 0
291 "*Extra offset for line which contains only the start of a comment.
292 Can contain an integer or a cons cell of the form:
293
294 (NON-ANCHORED-OFFSET . ANCHORED-OFFSET)
295
296 Where NON-ANCHORED-OFFSET is the amount of offset given to
297 non-column-zero anchored comment-only lines, and ANCHORED-OFFSET is
298 the amount of offset to give column-zero anchored comment-only lines.
299 Just an integer as value is equivalent to (<val> . -1000).")
300
301 (defvar c-indent-comments-syntactically-p nil
302 "*Specifies how comment-only lines should be indented.
303 When this variable is non-nil, comment-only lines are indented
304 according to syntactic analysis via `c-offsets-alist', even when
305 \\[indent-for-comment] is used.")
306
307 (defvar c-block-comments-indent-p nil
308 "*Specifies how to re-indent C style block comments.
309
310 Examples of the supported styles of C block comment indentation are
311 shown below. When this variable is nil, block comments are indented
312 as shown in styles 1 through 4. If this variable is non-nil, block
313 comments are indented as shown in style 5.
314
315 Note that cc-mode does not automatically insert any stars or block
316 comment delimiters. You must type these in manually. This variable
317 only controls how the lines within the block comment are indented when
318 you hit ``\\[c-indent-command]''.
319
320 style 1: style 2 (GNU): style 3: style 4: style 5:
321 /* /* Blah /* /* /*
322 blah blah. */ * blah ** blah blah
323 blah * blah ** blah blah
324 */ */ */ */")
325
326 (defvar c-cleanup-list '(scope-operator)
327 "*List of various C/C++/ObjC constructs to \"clean up\".
328 These clean ups only take place when the auto-newline feature is turned
329 on, as evidenced by the `/a' or `/ah' appearing next to the mode name.
330 Valid symbols are:
331
332 brace-else-brace -- cleans up `} else {' constructs by placing entire
333 construct on a single line. This clean up only
334 takes place when there is nothing but white
335 space between the braces and the `else'. Clean
336 up occurs when the open-brace after the `else'
337 is typed.
338 empty-defun-braces -- cleans up empty defun braces by placing the
339 braces on the same line. Clean up occurs when
340 the defun closing brace is typed.
341 defun-close-semi -- cleans up the terminating semi-colon on defuns
342 by placing the semi-colon on the same line as
343 the closing brace. Clean up occurs when the
344 semi-colon is typed.
345 list-close-comma -- cleans up commas following braces in array
346 and aggregate initializers. Clean up occurs
347 when the comma is typed.
348 scope-operator -- cleans up double colons which may designate
349 a C++ scope operator split across multiple
350 lines. Note that certain C++ constructs can
351 generate ambiguous situations. This clean up
352 only takes place when there is nothing but
353 whitespace between colons. Clean up occurs
354 when the second colon is typed.")
355
356 (defvar c-hanging-braces-alist '((brace-list-open)
357 (substatement-open after)
358 (block-close . c-snug-do-while))
359 "*Controls the insertion of newlines before and after braces.
360 This variable contains an association list with elements of the
361 following form: (SYNTACTIC-SYMBOL . ACTION).
362
363 When a brace (either opening or closing) is inserted, the syntactic
364 context it defines is looked up in this list, and if found, the
365 associated ACTION is used to determine where newlines are inserted.
366 If the context is not found, the default is to insert a newline both
367 before and after the brace.
368
369 SYNTACTIC-SYMBOL can be any of: defun-open, defun-close, class-open,
370 class-close, inline-open, inline-close, block-open, block-close,
371 substatement-open, statement-case-open, brace-list-open,
372 brace-list-close, brace-list-intro, or brace-list-entry. See
373 `c-offsets-alist' for details.
374
375 ACTION can be either a function symbol or a list containing any
376 combination of the symbols `before' or `after'. If the list is empty,
377 no newlines are inserted either before or after the brace.
378
379 When ACTION is a function symbol, the function is called with a two
380 arguments: the syntactic symbol for the brace and the buffer position
381 at which the brace was inserted. The function must return a list as
382 described in the preceding paragraph. Note that during the call to
383 the function, the variable `c-syntactic-context' is set to the entire
384 syntactic context for the brace line.")
385
386 (defvar c-hanging-colons-alist nil
387 "*Controls the insertion of newlines before and after certain colons.
388 This variable contains an association list with elements of the
389 following form: (SYNTACTIC-SYMBOL . ACTION).
390
391 See the variable `c-hanging-braces-alist' for the semantics of this
392 variable. Note however that making ACTION a function symbol is
393 currently not supported for this variable.")
394
395 (defvar c-hanging-semi&comma-criteria '(c-semi&comma-inside-parenlist)
396 "*List of functions that decide whether to insert a newline or not.
397 The functions in this list are called, in order, whenever the
398 auto-newline minor mode is activated (as evidenced by a `/a' or `/ah'
399 string in the mode line), and a semicolon or comma is typed (see
400 `c-electric-semi&comma'). Each function in this list is called with
401 no arguments, and should return one of the following values:
402
403 nil -- no determination made, continue checking
404 'stop -- do not insert a newline, and stop checking
405 (anything else) -- insert a newline, and stop checking
406
407 If every function in the list is called with no determination made,
408 then no newline is inserted.")
409
410 (defvar c-hanging-comment-ender-p t
411 "*If nil, `c-fill-paragraph' leaves C block comment enders on their own line.
412 Default value is t, which inhibits leaving block comment ending string
413 `*/' on a line by itself. This is BOCM's sole behavior.")
414
415 (defvar c-backslash-column 48
416 "*Column to insert backslashes when macroizing a region.")
417 (defvar c-special-indent-hook nil
418 "*Hook for user defined special indentation adjustments.
419 This hook gets called after a line is indented by the mode.")
420 (defvar c-delete-function 'backward-delete-char-untabify
421 "*Function called by `c-electric-delete' when deleting characters.")
422 (defvar c-electric-pound-behavior nil
423 "*List of behaviors for electric pound insertion.
424 Only currently supported behavior is `alignleft'.")
425
426 (defvar c-recognize-knr-p nil ; Emacs version uses t
427 "*If non-nil, `c-mode' and `objc-mode' will recognize K&R constructs.
428 This variable is needed because of ambiguities in C syntax that make
429 fast recognition of K&R constructs problematic, and slow. If you are
430 coding with ANSI prototypes, set this variable to nil to speed up
431 recognition of certain constructs. By setting this variable to nil, I
432 have seen an increase of 20 times under some circumstance.")
433
434 (defvar c-progress-interval 5
435 "*Interval used to update progress status during long re-indentation.
436 If a number, percentage complete gets updated after each interval of
437 that many seconds. Set to nil to inhibit updating. This is only
438 useful for Emacs 19.")
439
440 (defvar c-style-alist
441 '(("gnu"
442 (c-basic-offset . 2)
443 (c-comment-only-line-offset . (0 . 0))
444 (c-offsets-alist . ((statement-block-intro . +)
445 (knr-argdecl-intro . 5)
446 (substatement-open . +)
447 (label . 0)
448 (statement-case-open . +)
449 (statement-cont . +)
450 (arglist-intro . c-lineup-arglist-intro-after-paren)
451 (arglist-close . c-lineup-arglist)
452 ))
453 )
454 ("k&r"
455 (c-basic-offset . 5)
456 (c-comment-only-line-offset . 0)
457 (c-offsets-alist . ((statement-block-intro . +)
458 (knr-argdecl-intro . 0)
459 (substatement-open . 0)
460 (label . 0)
461 (statement-cont . +)
462 ))
463 )
464 ("bsd"
465 (c-basic-offset . 4)
466 (c-comment-only-line-offset . 0)
467 (c-offsets-alist . ((statement-block-intro . +)
468 (knr-argdecl-intro . +)
469 (substatement-open . 0)
470 (label . 0)
471 (statement-cont . +)
472 ))
473 )
474 ("stroustrup"
475 (c-basic-offset . 4)
476 (c-comment-only-line-offset . 0)
477 (c-offsets-alist . ((statement-block-intro . +)
478 (substatement-open . 0)
479 (label . 0)
480 (statement-cont . +)
481 ))
482 )
483 ("whitesmith"
484 (c-basic-offset . 4)
485 (c-comment-only-line-offset . 0)
486 (c-offsets-alist . ((statement-block-intro . +)
487 (knr-argdecl-intro . +)
488 (substatement-open . 0)
489 (label . 0)
490 (statement-cont . +)
491 ))
492
493 )
494 ("ellemtel"
495 (c-basic-offset . 3)
496 (c-comment-only-line-offset . 0)
497 (c-hanging-braces-alist . ((substatement-open before after)))
498 (c-offsets-alist . ((topmost-intro . 0)
499 (topmost-intro-cont . 0)
500 (substatement . 3)
501 (substatement-open . 0)
502 (statement-case-intro . 0)
503 (case-label . +)
504 (access-label . -3)
505 (inclass . 6)
506 (inline-open . 0)
507 ))
508 )
509 ("java"
510 (c-basic-offset . 2)
511 (c-comment-only-line-offset . (0 . 0))
512 (c-offsets-alist . ((statement-block-intro . +)
513 (knr-argdecl-intro . 5)
514 (substatement-open . +)
515 (label . 0)
516 (statement-case-open . +)
517 (statement-cont . +)
518 (arglist-intro . c-lineup-arglist-intro-after-paren)
519 (arglist-close . c-lineup-arglist)
520 (access-label . 0)
521 ))
522
523 )
524 )
525 "Styles of Indentation.
526 Elements of this alist are of the form:
527
528 (STYLE-STRING (VARIABLE . VALUE) [(VARIABLE . VALUE) ...])
529
530 where STYLE-STRING is a short descriptive string used to select a
531 style, VARIABLE is any cc-mode variable, and VALUE is the intended
532 value for that variable when using the selected style.
533
534 There is one special case when VARIABLE is `c-offsets-alist'. In this
535 case, the VALUE is a list containing elements of the form:
536
537 (SYNTACTIC-SYMBOL . VALUE)
538
539 as described in `c-offsets-alist'. These are passed directly to
540 `c-set-offset' so there is no need to set every syntactic symbol in
541 your style, only those that are different from the default.
542
543 Note that all styles inherit from the `cc-mode' style, which is
544 computed at the time the mode is loaded.")
545
546 (defvar c-file-style nil
547 "*Variable interface for setting style via File Local Variables.
548 In a file's Local Variable section, you can set this variable to a
549 string suitable for `c-set-style'. When the file is visited, cc-mode
550 will set the style of the file to this value automatically.
551
552 Note that file style settings are applied before file offset settings
553 as designated in the variable `c-file-offsets'.")
554
555 (defvar c-file-offsets nil
556 "*Variable interface for setting offsets via File Local Variables.
557 In a file's Local Variable section, you can set this variable to an
558 association list similar to the values allowed in `c-offsets-alist'.
559 When the file is visited, cc-mode will institute these offset settings
560 automatically.
561
562 Note that file offset settings are applied after file style settings
563 as designated in the variable `c-file-style'.")
564
565 (defvar c-site-default-style "gnu"
566 "Default style for your site.
567 To change the default style at your site, you can set this variable to
568 any style defined in `c-style-alist'. However, if cc-mode is usually
569 loaded into your Emacs at compile time, you will need to set this
570 variable in the `site-init.el' file before cc-mode is loaded, then
571 re-dump Emacs.")
572
573 (defvar c-mode-hook nil
574 "*Hook called by `c-mode'.")
575 (defvar c++-mode-hook nil
576 "*Hook called by `c++-mode'.")
577 (defvar objc-mode-hook nil
578 "*Hook called by `objc-mode'.")
579 (defvar java-mode-hook nil
580 "*Hook called by `java-mode'.")
581
582 (defvar c-mode-common-hook nil
583 "*Hook called by `c-mode', `c++-mode', and 'objc-mode' during common init.")
584
585 (defvar c-mode-menu
586 '(["Comment Out Region" comment-region (mark)]
587 ["Macro Expand Region" c-macro-expand (mark)]
588 ["Backslashify" c-backslash-region (mark)]
589 ["Indent Expression" c-indent-exp
590 (memq (following-char) '(?\( ?\[ ?\{))]
591 ["Indent Line" c-indent-command t]
592 ["Fill Comment Paragraph" c-fill-paragraph t]
593 ["Up Conditional" c-up-conditional t]
594 ["Backward Conditional" c-backward-conditional t]
595 ["Forward Conditional" c-forward-conditional t]
596 ["Backward Statement" c-beginning-of-statement t]
597 ["Forward Statement" c-end-of-statement t]
598 )
599 "XEmacs 19 menu for C/C++/ObjC modes.")
600
601 ;; Sadly we need this for a macro in Emacs 19.
602 (eval-when-compile
603 ;; Imenu isn't used in XEmacs, so just ignore load errors.
604 (condition-case ()
605 (require 'imenu)
606 (error nil)))
607
608 (defvar cc-imenu-c++-generic-expression
609 (`
610 ((nil
611 (,
612 (concat
613 "^" ; beginning of line is required
614 "\\(template[ \t]*<[^>]+>[ \t]*\\)?" ; there may be a "template <...>"
615 "\\([a-zA-Z0-9_:]+[ \t]+\\)?" ; type specs; there can be no
616 "\\([a-zA-Z0-9_:]+[ \t]+\\)?" ; more than 3 tokens, right?
617
618 "\\(" ; last type spec including */&
619 "[a-zA-Z0-9_:]+"
620 "\\([ \t]*[*&]+[ \t]*\\|[ \t]+\\)" ; either pointer/ref sign or whitespace
621 "\\)?" ; if there is a last type spec
622 "\\(" ; name; take that into the imenu entry
623 "[a-zA-Z0-9_:~]+" ; member function, ctor or dtor...
624 ; (may not contain * because then
625 ; "a::operator char*" would become "char*"!)
626 "\\|"
627 "\\([a-zA-Z0-9_:~]*::\\)?operator"
628 "[^a-zA-Z1-9_][^(]*" ; ...or operator
629 " \\)"
630 "[ \t]*([^)]*)[ \t\n]*[^ ;]" ; require something other than a ; after
631 ; the (...) to avoid prototypes. Can't
632 ; catch cases with () inside the parentheses
633 ; surrounding the parameters
634 ; (like "int foo(int a=bar()) {...}"
635
636 )) 6)
637 ("Class"
638 (, (concat
639 "^" ; beginning of line is required
640 "\\(template[ \t]*<[^>]+>[ \t]*\\)?" ; there may be a "template <...>"
641 "class[ \t]+"
642 "\\([a-zA-Z0-9_]+\\)" ; this is the string we want to get
643 "[ \t]*[:{]"
644 )) 2)))
645 "Imenu generic expression for C++ mode. See `imenu-generic-expression'.")
646
647 (defvar cc-imenu-c-generic-expression
648 cc-imenu-c++-generic-expression
649 "Imenu generic expression for C mode. See `imenu-generic-expression'.")
650
651
652 ;; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
653 ;; NO USER DEFINABLE VARIABLES BEYOND THIS POINT
654
655 ;; Shut the byte-compiler up. Requires Emacs 19 or JWZ's improved
656 ;; byte-compiler. Otherwise, comment this line out and ignore
657 ;; any warnings.
658 ;;(byte-compiler-options (warnings nil))
659
660 ;; figure out what features this Emacs has
661 (defconst c-emacs-features
662 (let ((major (and (boundp 'emacs-major-version)
663 emacs-major-version))
664 (minor (and (boundp 'emacs-minor-version)
665 emacs-minor-version))
666 (re-suite 'old-re)
667 flavor comments)
668 ;; figure out version numbers if not already discovered
669 (and (or (not major) (not minor))
670 (string-match "\\([0-9]+\\).\\([0-9]+\\)" emacs-version)
671 (setq major (string-to-int (substring emacs-version
672 (match-beginning 1)
673 (match-end 1)))
674 minor (string-to-int (substring emacs-version
675 (match-beginning 2)
676 (match-end 2)))))
677 (if (not (and major minor))
678 (error "Cannot figure out the major and minor version numbers."))
679 ;; calculate the major version
680 (cond
681 ((= major 18) (setq major 'v18)) ;Emacs 18
682 ((= major 4) (setq major 'v18)) ;Epoch 4
683 ((= major 19) (setq major 'v19 ;Emacs 19
684 flavor (if (or (string-match "Lucid" emacs-version)
685 (string-match "XEmacs" emacs-version))
686 'XEmacs 'FSF)))
687 ;; I don't know
688 (t (error "Cannot recognize major version number: %s" major)))
689 ;; Regular expression suites...
690 (if (and (eq major 'v19)
691 (or (and (eq flavor 'XEmacs) (>= minor 14))
692 (and (eq flavor 'FSF) (>= minor 30))))
693 (setq re-suite 'new-re))
694 ;; XEmacs 19 uses 8-bit modify-syntax-entry flags, as do all
695 ;; patched Emacs 19, Emacs 18, Epoch 4's. Only Emacs 19 uses a
696 ;; 1-bit flag. Let's be as smart as we can about figuring this
697 ;; out.
698 (if (eq major 'v19)
699 (let ((table (copy-syntax-table)))
700 (modify-syntax-entry ?a ". 12345678" table)
701 (cond
702 ;; XEmacs pre 20 and Emacs pre 19.30 use vectors for syntax tables.
703 ((vectorp table)
704 (if (= (logand (lsh (aref table ?a) -16) 255) 255)
705 (setq comments '8-bit)
706 (setq comments '1-bit)))
707 ;; XEmacs 20 is known to be 8-bit
708 ((eq flavor 'XEmacs) (setq comments '8-bit))
709 ;; Emacs 19.30 and beyond are known to be 1-bit
710 ((eq flavor 'FSF) (setq comments '1-bit))
711 ;; Don't know what this is
712 (t (error "Couldn't figure out syntax table format."))
713 ))
714 ;; Emacs 18 has no support for dual comments
715 (setq comments 'no-dual-comments))
716 ;; lets do some minimal sanity checking.
717 (if (and (or
718 ;; Lucid Emacs before 19.6 had bugs
719 (and (eq major 'v19) (eq flavor 'XEmacs) (< minor 6))
720 ;; Emacs 19 before 19.21 has known bugs
721 (and (eq major 'v19) (eq flavor 'FSF) (< minor 21)))
722 (not c-inhibit-startup-warnings-p))
723 (with-output-to-temp-buffer "*cc-mode warnings*"
724 (print (format
725 "The version of Emacs that you are running, %s,
726 has known bugs in its syntax.c parsing routines which will affect the
727 performance of cc-mode. You should strongly consider upgrading to the
728 latest available version. cc-mode may continue to work, after a
729 fashion, but strange indentation errors could be encountered."
730 emacs-version))))
731 ;; Emacs 18, with no patch is not too good
732 (if (and (eq major 'v18) (eq comments 'no-dual-comments)
733 (not c-inhibit-startup-warnings-p))
734 (with-output-to-temp-buffer "*cc-mode warnings*"
735 (print (format
736 "The version of Emacs 18 you are running, %s,
737 has known deficiencies in its ability to handle dual C++ comments,
738 i.e. C++ line style comments and C block style comments. This will
739 not be much of a problem for you if you are only editing C code, but
740 if you are doing much C++ editing, you should strongly consider
741 upgrading to one of the latest Emacs 19's. In Emacs 18, you may also
742 experience performance degradations. Emacs 19 has some new built-in
743 routines which will speed things up for you.
744
745 Because of these inherent problems, cc-mode is no longer being
746 actively maintained for Emacs 18, however, until you can upgrade to
747 Emacs 19, you may want to look at cc-mode-18.el in the cc-mode
748 distribution. THIS FILE IS COMPLETELY UNSUPPORTED! If you use it,
749 you are on your own, although patch contributions will be folded into
750 the main release."
751 emacs-version))))
752 ;; Emacs 18 with the syntax patches are no longer supported
753 (if (and (eq major 'v18) (not (eq comments 'no-dual-comments))
754 (not c-inhibit-startup-warnings-p))
755 (with-output-to-temp-buffer "*cc-mode warnings*"
756 (print (format
757 "You are running a syntax patched Emacs 18 variant. While this should
758 work for you, you may want to consider upgrading to Emacs 19. The
759 syntax patches are no longer supported either for syntax.c or
760 cc-mode."))))
761 (list major comments re-suite))
762 "A list of features extant in the Emacs you are using.
763 There are many flavors of Emacs out there, each with different
764 features supporting those needed by cc-mode. Here's the current
765 supported list, along with the values for this variable:
766
767 Emacs 18/Epoch 4: (v18 no-dual-comments RS)
768 Emacs 18/Epoch 4 (patch2): (v18 8-bit RS)
769 XEmacs 19: (v19 8-bit RS)
770 Emacs 19: (v19 1-bit RS)
771
772 RS is the regular expression suite to use. XEmacs versions after
773 19.13, and Emacs versions after 19.29 use the `new-re' regex suite.
774 All other Emacsen use the `old-re' suite.")
775
776 (defvar c++-mode-abbrev-table nil
777 "Abbrev table in use in c++-mode buffers.")
778 (define-abbrev-table 'c++-mode-abbrev-table ())
779
780 (defvar c-mode-abbrev-table nil
781 "Abbrev table in use in c-mode buffers.")
782 (define-abbrev-table 'c-mode-abbrev-table ())
783
784 (defvar objc-mode-abbrev-table nil
785 "Abbrev table in use in objc-mode buffers.")
786 (define-abbrev-table 'objc-mode-abbrev-table ())
787
788 (defvar java-mode-abbrev-table nil
789 "Abbrev table in use in java-mode buffers.")
790 (define-abbrev-table 'java-mode-abbrev-table ())
791
792 (defun c-mode-fsf-menu (name map)
793 ;; Add menu to a keymap. FSF menus suck. Don't add them for
794 ;; XEmacs. This feature test will fail on other than Emacs 19.
795 (condition-case nil
796 (progn
797 (define-key map [menu-bar] (make-sparse-keymap))
798 (define-key map [menu-bar c] (cons name (make-sparse-keymap name)))
799
800 (define-key map [menu-bar c comment-region]
801 '("Comment Out Region" . comment-region))
802 (define-key map [menu-bar c c-macro-expand]
803 '("Macro Expand Region" . c-macro-expand))
804 (define-key map [menu-bar c c-backslash-region]
805 '("Backslashify" . c-backslash-region))
806 (define-key map [menu-bar c indent-exp]
807 '("Indent Expression" . c-indent-exp))
808 (define-key map [menu-bar c indent-line]
809 '("Indent Line" . c-indent-command))
810 (define-key map [menu-bar c fill]
811 '("Fill Comment Paragraph" . c-fill-paragraph))
812 (define-key map [menu-bar c up]
813 '("Up Conditional" . c-up-conditional))
814 (define-key map [menu-bar c backward]
815 '("Backward Conditional" . c-backward-conditional))
816 (define-key map [menu-bar c forward]
817 '("Forward Conditional" . c-forward-conditional))
818 (define-key map [menu-bar c backward-stmt]
819 '("Backward Statement" . c-beginning-of-statement))
820 (define-key map [menu-bar c forward-stmt]
821 '("Forward Statement" . c-end-of-statement))
822
823 ;; RMS: mouse-3 should not select this menu. mouse-3's global
824 ;; definition is useful in C mode and we should not interfere
825 ;; with that. The menu is mainly for beginners, and for them,
826 ;; the menubar requires less memory than a special click.
827 t)
828 (error nil)))
829
830 (defvar c-mode-map ()
831 "Keymap used in c-mode buffers.")
832 (if c-mode-map
833 ()
834 ;; TBD: should we even worry about naming this keymap. My vote: no,
835 ;; because Emacs and XEmacs do it differently.
836 (setq c-mode-map (make-sparse-keymap))
837 ;; put standard keybindings into MAP
838 ;; the following mappings correspond more or less directly to BOCM
839 (define-key c-mode-map "{" 'c-electric-brace)
840 (define-key c-mode-map "}" 'c-electric-brace)
841 (define-key c-mode-map ";" 'c-electric-semi&comma)
842 (define-key c-mode-map "#" 'c-electric-pound)
843 (define-key c-mode-map ":" 'c-electric-colon)
844 ;; Lucid Emacs 19.9 defined these two, the second of which was
845 ;; commented out...
846 ;; (define-key c-mode-map "\e{" 'c-insert-braces)
847 ;; Commented out electric square brackets because nobody likes them.
848 ;; (define-key c-mode-map "[" 'c-insert-brackets)
849 (define-key c-mode-map "\e\C-h" 'c-mark-function)
850 (define-key c-mode-map "\e\C-q" 'c-indent-exp)
851 (define-key c-mode-map "\ea" 'c-beginning-of-statement)
852 (define-key c-mode-map "\ee" 'c-end-of-statement)
853 ;; Emacs 19.30 introduces fill-paragraph-function, but it's not in
854 ;; every version of Emacs cc-mode supports.
855 (if (not (boundp 'fill-paragraph-function))
856 ;; I'd rather use an adaptive fill program instead of this.
857 (define-key c-mode-map "\eq" 'c-fill-paragraph))
858 (define-key c-mode-map "\C-c\C-n" 'c-forward-conditional)
859 (define-key c-mode-map "\C-c\C-p" 'c-backward-conditional)
860 (define-key c-mode-map "\C-c\C-u" 'c-up-conditional)
861 (define-key c-mode-map "\t" 'c-indent-command)
862 (define-key c-mode-map "\177" 'c-electric-delete)
863 ;; these are new keybindings, with no counterpart to BOCM
864 (define-key c-mode-map "," 'c-electric-semi&comma)
865 (define-key c-mode-map "*" 'c-electric-star)
866 (define-key c-mode-map "\C-c\C-q" 'c-indent-defun)
867 (define-key c-mode-map "\C-c\C-\\" 'c-backslash-region)
868 ;; TBD: where if anywhere, to put c-backward|forward-into-nomenclature
869 (define-key c-mode-map "\C-c\C-a" 'c-toggle-auto-state)
870 (define-key c-mode-map "\C-c\C-b" 'c-submit-bug-report)
871 (define-key c-mode-map "\C-c\C-c" 'comment-region)
872 (define-key c-mode-map "\C-c\C-d" 'c-toggle-hungry-state)
873 (define-key c-mode-map "\C-c\C-e" 'c-macro-expand)
874 (define-key c-mode-map "\C-c\C-o" 'c-set-offset)
875 (define-key c-mode-map "\C-c\C-s" 'c-show-syntactic-information)
876 (define-key c-mode-map "\C-c\C-t" 'c-toggle-auto-hungry-state)
877 ;; conflicts with OOBR
878 ;;(define-key c-mode-map "\C-c\C-v" 'c-version)
879 ;;
880 ;; Emacs 19 defines menus in the mode map. This call will return
881 ;; t on Emacs 19, otherwise no-op and return nil.
882 (if (and (not (c-mode-fsf-menu "C" c-mode-map))
883 ;; in XEmacs 19, we want the menu to popup when the 3rd
884 ;; button is hit. In Lucid Emacs 19.10 and beyond this is
885 ;; done automatically if we put the menu on mode-popup-menu
886 ;; variable, see c-common-init. Emacs 19 uses C-Mouse-3 for
887 ;; this, and it works with no special effort.
888 (boundp 'current-menubar)
889 (not (boundp 'mode-popup-menu)))
890 (define-key c-mode-map 'button3 'c-popup-menu)))
891
892 (defvar c++-mode-map ()
893 "Keymap used in c++-mode buffers.")
894 (if c++-mode-map
895 ()
896 ;; In Emacs 19, it makes more sense to inherit c-mode-map
897 (if (memq 'v19 c-emacs-features)
898 ;; XEmacs and Emacs 19 do this differently
899 (cond
900 ;; XEmacs 19.13
901 ((fboundp 'set-keymap-parents)
902 (setq c++-mode-map (make-sparse-keymap))
903 (set-keymap-parents c++-mode-map c-mode-map))
904 ((fboundp 'set-keymap-parent)
905 (setq c++-mode-map (make-sparse-keymap))
906 (set-keymap-parent c++-mode-map c-mode-map))
907 (t (setq c++-mode-map (cons 'keymap c-mode-map))))
908 ;; Do it the hard way for Emacs 18 -- given by JWZ
909 (setq c++-mode-map (nconc (make-sparse-keymap) c-mode-map)))
910 ;; add bindings which are only useful for C++
911 (define-key c++-mode-map "\C-c:" 'c-scope-operator)
912 (define-key c++-mode-map "/" 'c-electric-slash)
913 (define-key c++-mode-map "<" 'c-electric-lt-gt)
914 (define-key c++-mode-map ">" 'c-electric-lt-gt)
915 ;; Emacs 19 defines menus in the mode map. This call will return
916 ;; t on Emacs 19, otherwise no-op and return nil.
917 (c-mode-fsf-menu "C++" c++-mode-map))
918
919 (defvar objc-mode-map ()
920 "Keymap used in objc-mode buffers.")
921 (if objc-mode-map
922 ()
923 ;; In Emacs 19, it makes more sense to inherit c-mode-map
924 (if (memq 'v19 c-emacs-features)
925 ;; XEmacs and Emacs 19 do this differently
926 (cond
927 ;; XEmacs 19.13
928 ((fboundp 'set-keymap-parents)
929 (setq objc-mode-map (make-sparse-keymap))
930 (set-keymap-parents objc-mode-map c-mode-map))
931 ((fboundp 'set-keymap-parent)
932 (setq objc-mode-map (make-sparse-keymap))
933 (set-keymap-parent objc-mode-map c-mode-map))
934 (t (setq objc-mode-map (cons 'keymap c-mode-map))))
935 ;; Do it the hard way for Emacs 18 -- given by JWZ
936 (setq objc-mode-map (nconc (make-sparse-keymap) c-mode-map)))
937 ;; add bindings which are only useful for Objective-C
938 (define-key objc-mode-map "/" 'c-electric-slash)
939 ;; Emacs 19 defines menus in the mode map. This call will return
940 ;; t on Emacs 19, otherwise no-op and return nil.
941 (c-mode-fsf-menu "ObjC" objc-mode-map))
942
943 (defvar java-mode-map ()
944 "Keymap used in java-mode buffers.")
945 (if java-mode-map
946 ()
947 ;; In Emacs 19, it makes more sense to inherit c-mode-map
948 (if (memq 'v19 c-emacs-features)
949 ;; XEmacs and Emacs 19 do this differently
950 (cond
951 ;; XEmacs 19.13
952 ((fboundp 'set-keymap-parents)
953 (setq java-mode-map (make-sparse-keymap))
954 (set-keymap-parents java-mode-map c-mode-map))
955 ((fboundp 'set-keymap-parent)
956 (setq java-mode-map (make-sparse-keymap))
957 (set-keymap-parent java-mode-map c-mode-map))
958 (t (setq java-mode-map (cons 'keymap c-mode-map)))
959 )
960 ;; Do it the hard way for Emacs 18 -- given by JWZ
961 (setq java-mode-map (nconc (make-sparse-keymap) c-mode-map)))
962 ;; add bindings which are only useful for Java
963 (define-key java-mode-map "/" 'c-electric-slash)
964 ;; Emacs 19 defines menus in the mode map. This call will return t
965 ;; on Emacs 19, otherwise no-op and return nil.
966 (c-mode-fsf-menu "Java" java-mode-map))
967
968 (defun c-populate-syntax-table (table)
969 ;; Populate the syntax TABLE
970 ;; DO NOT TRY TO SET _ (UNDERSCORE) TO WORD CLASS!
971 (modify-syntax-entry ?_ "_" table)
972 (modify-syntax-entry ?\\ "\\" table)
973 (modify-syntax-entry ?+ "." table)
974 (modify-syntax-entry ?- "." table)
975 (modify-syntax-entry ?= "." table)
976 (modify-syntax-entry ?% "." table)
977 (modify-syntax-entry ?< "." table)
978 (modify-syntax-entry ?> "." table)
979 (modify-syntax-entry ?& "." table)
980 (modify-syntax-entry ?| "." table)
981 (modify-syntax-entry ?\' "\"" table))
982
983 (defun c-setup-dual-comments (table)
984 ;; Set up TABLE to handle block and line style comments
985 (cond
986 ((memq '8-bit c-emacs-features)
987 ;; XEmacs 19 has the best implementation
988 (modify-syntax-entry ?/ ". 1456" table)
989 (modify-syntax-entry ?* ". 23" table)
990 (modify-syntax-entry ?\n "> b" table)
991 ;; Give CR the same syntax as newline, for selective-display
992 (modify-syntax-entry ?\^m "> b" table))
993 ((memq '1-bit c-emacs-features)
994 ;; Emacs 19 does things differently, but we can work with it
995 (modify-syntax-entry ?/ ". 124b" table)
996 (modify-syntax-entry ?* ". 23" table)
997 (modify-syntax-entry ?\n "> b" table)
998 ;; Give CR the same syntax as newline, for selective-display
999 (modify-syntax-entry ?\^m "> b" table))
1000 ))
1001
1002 (defvar c-mode-syntax-table nil
1003 "Syntax table used in c-mode buffers.")
1004 (if c-mode-syntax-table
1005 ()
1006 (setq c-mode-syntax-table (make-syntax-table))
1007 (c-populate-syntax-table c-mode-syntax-table)
1008 ;; add extra comment syntax
1009 (modify-syntax-entry ?/ ". 14" c-mode-syntax-table)
1010 (modify-syntax-entry ?* ". 23" c-mode-syntax-table))
1011
1012 (defvar c++-mode-syntax-table nil
1013 "Syntax table used in c++-mode buffers.")
1014 (if c++-mode-syntax-table
1015 ()
1016 (setq c++-mode-syntax-table (make-syntax-table))
1017 (c-populate-syntax-table c++-mode-syntax-table)
1018 ;; add extra comment syntax
1019 (c-setup-dual-comments c++-mode-syntax-table)
1020 ;; TBD: does it make sense for colon to be symbol class in C++?
1021 ;; I'm not so sure, since c-label-key is busted on lines like:
1022 ;; Foo::bar( i );
1023 ;; maybe c-label-key should be fixed instead of commenting this out,
1024 ;; but it also bothers me that this only seems appropriate for C++
1025 ;; and not C.
1026 ;;(modify-syntax-entry ?: "_" c++-mode-syntax-table)
1027 )
1028
1029 (defvar objc-mode-syntax-table nil
1030 "Syntax table used in objc-mode buffers.")
1031 (if objc-mode-syntax-table
1032 ()
1033 (setq objc-mode-syntax-table (make-syntax-table))
1034 (c-populate-syntax-table objc-mode-syntax-table)
1035 ;; add extra comment syntax
1036 (c-setup-dual-comments objc-mode-syntax-table)
1037 ;; everyone gets these
1038 (modify-syntax-entry ?@ "_" objc-mode-syntax-table)
1039 )
1040
1041 (defvar java-mode-syntax-table nil
1042 "Syntax table used in java-mode buffers.")
1043 (if java-mode-syntax-table
1044 ()
1045 (setq java-mode-syntax-table (make-syntax-table))
1046 (c-populate-syntax-table java-mode-syntax-table)
1047 ;; add extra comment syntax
1048 (c-setup-dual-comments java-mode-syntax-table)
1049 ;; everyone gets these
1050 (modify-syntax-entry ?@ "_" java-mode-syntax-table)
1051 )
1052
1053 (defvar c-hungry-delete-key nil
1054 "Internal state of hungry delete key feature.")
1055 (defvar c-auto-newline nil
1056 "Internal state of auto newline feature.")
1057 (defvar c-auto-hungry-string nil
1058 "Internal auto-newline/hungry-delete designation string for mode line.")
1059 (defvar c-syntactic-context nil
1060 "Variable containing syntactic analysis list during indentation.")
1061 (defvar c-comment-start-regexp nil
1062 "Buffer local variable describing how comment are introduced.")
1063 (defvar c-conditional-key nil
1064 "Buffer local language-specific conditional keyword regexp.")
1065 (defvar c-access-key nil
1066 "Buffer local language-specific access key regexp.")
1067 (defvar c-class-key nil
1068 "Buffer local language-specific class key regexp.")
1069 (defvar c-method-key nil
1070 "Buffer local language-specific method regexp.")
1071 (defvar c-double-slash-is-comments-p nil
1072 "Buffer local language-specific comment style flag.")
1073 (defconst c-protection-key
1074 "\\<\\(public\\|protected\\|private\\)\\>"
1075 "Regexp describing protection keywords.")
1076 (defconst c-symbol-key "\\(\\w\\|\\s_\\)+"
1077 "Regexp describing a C/C++/ObjC symbol.
1078 We cannot use just `word' syntax class since `_' cannot be in word
1079 class. Putting underscore in word class breaks forward word movement
1080 behavior that users are familiar with.")
1081 (defconst c-baseclass-key
1082 (concat
1083 ":?[ \t]*\\(virtual[ \t]+\\)?\\("
1084 c-protection-key "[ \t]+\\)" c-symbol-key)
1085 "Regexp describing C++ base classes in a derived class definition.")
1086
1087 ;; minor mode variables
1088 (make-variable-buffer-local 'c-auto-newline)
1089 (make-variable-buffer-local 'c-hungry-delete-key)
1090 (make-variable-buffer-local 'c-auto-hungry-string)
1091 ;; language differences
1092 (make-variable-buffer-local 'c-comment-start-regexp)
1093 (make-variable-buffer-local 'c-conditional-key)
1094 (make-variable-buffer-local 'c-access-key)
1095 (make-variable-buffer-local 'c-class-key)
1096 (make-variable-buffer-local 'c-method-key)
1097 (make-variable-buffer-local 'c-double-slash-is-comments-p)
1098 (make-variable-buffer-local 'c-baseclass-key)
1099 (make-variable-buffer-local 'c-recognize-knr-p)
1100 ;; style variables are made buffer local at tail end of this file.
1101
1102 ;; cmacexp is lame because it uses no preprocessor symbols.
1103 ;; It isn't very extensible either -- hardcodes /lib/cpp.
1104 ;; [I add it here only because c-mode has it -- BAW]
1105 ;;(autoload 'c-macro-expand "cmacexp"
1106 ;; "Display the result of expanding all C macros occurring in the region.
1107 ;;The expansion is entirely correct because it uses the C preprocessor."
1108 ;; t)
1109
1110
1111 ;; constant regular expressions for looking at various constructs
1112 (defconst c-C++-class-key "\\(class\\|struct\\|union\\)"
1113 "Regexp describing a C++ class declaration, including templates.")
1114 (defconst c-C-class-key "\\(struct\\|union\\)"
1115 "Regexp describing a C struct declaration.")
1116 (defconst c-inher-key
1117 (concat "\\(\\<static\\>\\s +\\)?"
1118 c-C++-class-key "[ \t]+" c-symbol-key
1119 "\\([ \t]*:[ \t]*\\)?\\s *[^;]")
1120 "Regexp describing a class inheritance declaration.")
1121 (defconst c-switch-label-key
1122 "\\(\\(case[( \t]+\\S .*\\)\\|default[ \t]*\\):"
1123 "Regexp describing a switch's case or default label")
1124 (defconst c-C++-access-key
1125 (concat c-protection-key ":")
1126 "Regexp describing C++ access specification keywords.")
1127 (defconst c-label-key
1128 (concat c-symbol-key ":\\([^:]\\|$\\)")
1129 "Regexp describing any label.")
1130 (defconst c-C-conditional-key
1131 "\\b\\(for\\|if\\|do\\|else\\|while\\|switch\\)\\b[^_]"
1132 "Regexp describing a conditional control.")
1133 (defconst c-C++-conditional-key
1134 "\\b\\(for\\|if\\|do\\|else\\|while\\|switch\\|try\\|catch\\)\\b[^_]"
1135 "Regexp describing a conditional control for C++.")
1136 (defconst c-C++-friend-key
1137 "friend[ \t]+\\|template[ \t]*<.+>[ \t]*friend[ \t]+"
1138 "Regexp describing friend declarations in C++ classes.")
1139 (defconst c-C++-comment-start-regexp "//\\|/\\*"
1140 "Dual comment value for `c-comment-start-regexp'.")
1141 (defconst c-C-comment-start-regexp "/\\*"
1142 "Single comment style value for `c-comment-start-regexp'.")
1143
1144 (defconst c-ObjC-method-key
1145 (concat
1146 "^\\s *[+-]\\s *"
1147 "\\(([^)]*)\\)?" ; return type
1148 ;; \\s- in objc syntax table does not include \n
1149 ;; since it is considered the end of //-comments.
1150 "[ \t\n]*" c-symbol-key)
1151 "Regexp describing an Objective-C method intro.")
1152 (defconst c-ObjC-access-key
1153 (concat "@" c-protection-key)
1154 "Regexp describing access specification keywords for Objective-C.")
1155 (defconst c-ObjC-class-key
1156 (concat
1157 "@\\(interface\\|implementation\\)\\s +"
1158 c-symbol-key ;name of the class
1159 "\\(\\s *:\\s *" c-symbol-key "\\)?" ;maybe followed by the superclass
1160 "\\(\\s *<[^>]+>\\)?" ;and maybe the adopted protocols list
1161 )
1162 "Regexp describing a class or protocol declaration for Objective-C.")
1163
1164 (defconst c-Java-conditional-key
1165 "\\b\\(for\\|if\\|do\\|else\\|while\\|switch\\|try\\|catch\\|finally\\|synchronized\\)\\b[^_]"
1166 "Regexp describing a conditional control for Java.")
1167
1168 (defconst c-Java-method-key
1169 (concat
1170 "^\\s *[+-]\\s *"
1171 "\\(([^)]*)\\)?" ; return type
1172 ;; \\s- in java syntax table does not include \n
1173 ;; since it is considered the end of //-comments.
1174 "[ \t\n]*" c-symbol-key)
1175 "Regexp describing a Java method intro.")
1176 (defconst c-Java-access-key
1177 (concat c-protection-key)
1178 "Regexp describing access specification keywords for Java.")
1179 (defconst c-Java-class-key
1180 (concat
1181 "\\(interface\\|class\\)\\s +"
1182 c-symbol-key ;name of the class
1183 "\\(\\s *extends\\s *" c-symbol-key "\\)?" ;maybe followed by superclass
1184 ;;"\\(\\s *implements *[^{]+{\\)?" ;and maybe the adopted protocols list
1185 )
1186 "Regexp describing a class or protocol declaration for Java.")
1187
1188 ;; KLUDGE ALERT. We default these variables to their `C' values so
1189 ;; that non-cc-mode-ized modes that depend on c-mode will still work
1190 ;; out of the box. The most glaring example is awk-mode. There ought
1191 ;; to be a better way.
1192 (setq-default c-conditional-key c-C-conditional-key
1193 c-class-key c-C-class-key
1194 c-comment-start-regexp c-C-comment-start-regexp)
1195
1196
1197 ;; main entry points for the modes
1198 (defconst c-list-of-mode-names nil)
1199
1200 (defun c-mode ()
1201 "Major mode for editing K&R and ANSI C code.
1202 To submit a problem report, enter `\\[c-submit-bug-report]' from a
1203 c-mode buffer. This automatically sets up a mail buffer with version
1204 information already added. You just need to add a description of the
1205 problem, including a reproducible test case and send the message.
1206
1207 To see what version of cc-mode you are running, enter `\\[c-version]'.
1208
1209 The hook variable `c-mode-hook' is run with no args, if that value is
1210 bound and has a non-nil value. Also the hook `c-mode-common-hook' is
1211 run first.
1212
1213 Key bindings:
1214 \\{c-mode-map}"
1215 (interactive)
1216 (kill-all-local-variables)
1217 (set-syntax-table c-mode-syntax-table)
1218 (setq major-mode 'c-mode
1219 mode-name "C"
1220 local-abbrev-table c-mode-abbrev-table)
1221 (use-local-map c-mode-map)
1222 (c-common-init)
1223 (setq comment-start "/* "
1224 comment-end " */"
1225 comment-multi-line t
1226 c-conditional-key c-C-conditional-key
1227 c-class-key c-C-class-key
1228 c-baseclass-key nil
1229 c-comment-start-regexp c-C-comment-start-regexp
1230 imenu-generic-expression cc-imenu-c-generic-expression)
1231 (run-hooks 'c-mode-common-hook)
1232 (run-hooks 'c-mode-hook))
1233 (setq c-list-of-mode-names (cons "C" c-list-of-mode-names))
1234
1235 (defun c++-mode ()
1236 "Major mode for editing C++ code.
1237 To submit a problem report, enter `\\[c-submit-bug-report]' from a
1238 c++-mode buffer. This automatically sets up a mail buffer with
1239 version information already added. You just need to add a description
1240 of the problem, including a reproducible test case, and send the
1241 message.
1242
1243 To see what version of cc-mode you are running, enter `\\[c-version]'.
1244
1245 The hook variable `c++-mode-hook' is run with no args, if that
1246 variable is bound and has a non-nil value. Also the hook
1247 `c-mode-common-hook' is run first.
1248
1249 Key bindings:
1250 \\{c++-mode-map}"
1251 (interactive)
1252 (kill-all-local-variables)
1253 (set-syntax-table c++-mode-syntax-table)
1254 (setq major-mode 'c++-mode
1255 mode-name "C++"
1256 local-abbrev-table c++-mode-abbrev-table)
1257 (use-local-map c++-mode-map)
1258 (c-common-init)
1259 (setq comment-start "// "
1260 comment-end ""
1261 comment-multi-line nil
1262 c-conditional-key c-C++-conditional-key
1263 c-comment-start-regexp c-C++-comment-start-regexp
1264 c-class-key c-C++-class-key
1265 c-access-key c-C++-access-key
1266 c-double-slash-is-comments-p t
1267 imenu-generic-expression cc-imenu-c++-generic-expression)
1268 (run-hooks 'c-mode-common-hook)
1269 (run-hooks 'c++-mode-hook))
1270 (setq c-list-of-mode-names (cons "C++" c-list-of-mode-names))
1271
1272 (defun objc-mode ()
1273 "Major mode for editing Objective C code.
1274 To submit a problem report, enter `\\[c-submit-bug-report]' from an
1275 objc-mode buffer. This automatically sets up a mail buffer with
1276 version information already added. You just need to add a description
1277 of the problem, including a reproducible test case, and send the
1278 message.
1279
1280 To see what version of cc-mode you are running, enter `\\[c-version]'.
1281
1282 The hook variable `objc-mode-hook' is run with no args, if that value
1283 is bound and has a non-nil value. Also the hook `c-mode-common-hook'
1284 is run first.
1285
1286 Key bindings:
1287 \\{objc-mode-map}"
1288 (interactive)
1289 (kill-all-local-variables)
1290 (set-syntax-table objc-mode-syntax-table)
1291 (setq major-mode 'objc-mode
1292 mode-name "ObjC"
1293 local-abbrev-table objc-mode-abbrev-table)
1294 (use-local-map objc-mode-map)
1295 (c-common-init)
1296 (setq comment-start "// "
1297 comment-end ""
1298 comment-multi-line nil
1299 c-conditional-key c-C-conditional-key
1300 c-comment-start-regexp c-C++-comment-start-regexp
1301 c-class-key c-ObjC-class-key
1302 c-baseclass-key nil
1303 c-access-key c-ObjC-access-key
1304 c-double-slash-is-comments-p t
1305 c-method-key c-ObjC-method-key)
1306 (run-hooks 'c-mode-common-hook)
1307 (run-hooks 'objc-mode-hook))
1308 (setq c-list-of-mode-names (cons "ObjC" c-list-of-mode-names))
1309
1310 (defun java-mode ()
1311 "Major mode for editing Java code.
1312 To submit a problem report, enter `\\[c-submit-bug-report]' from an
1313 java-mode buffer. This automatically sets up a mail buffer with
1314 version information already added. You just need to add a description
1315 of the problem, including a reproducible test case and send the
1316 message.
1317
1318 To see what version of cc-mode you are running, enter `\\[c-version]'.
1319
1320 The hook variable `java-mode-hook' is run with no args, if that value
1321 is bound and has a non-nil value. Also the common hook
1322 `c-mode-common-hook' is run first.
1323
1324 Key bindings:
1325 \\{java-mode-map}"
1326 (interactive)
1327 (kill-all-local-variables)
1328 (set-syntax-table java-mode-syntax-table)
1329 (setq major-mode 'java-mode
1330 mode-name "Java"
1331 local-abbrev-table java-mode-abbrev-table)
1332 (use-local-map java-mode-map)
1333 (c-common-init)
1334 (setq comment-start "// "
1335 comment-end ""
1336 comment-multi-line nil
1337 c-conditional-key c-Java-conditional-key
1338 c-comment-start-regexp c-C++-comment-start-regexp
1339 c-class-key c-Java-class-key
1340 c-method-key c-Java-method-key
1341 c-double-slash-is-comments-p t
1342 c-baseclass-key nil
1343 c-access-key c-Java-access-key)
1344 (c-set-style "Java")
1345 (run-hooks 'c-mode-common-hook)
1346 (run-hooks 'java-mode-hook))
1347 (setq c-list-of-mode-names (cons "Java" c-list-of-mode-names))
1348
1349 (defun c-common-init ()
1350 ;; Common initializations for c++-mode and c-mode.
1351 ;; make local variables
1352 (make-local-variable 'paragraph-start)
1353 (make-local-variable 'paragraph-separate)
1354 (make-local-variable 'paragraph-ignore-fill-prefix)
1355 (make-local-variable 'require-final-newline)
1356 (make-local-variable 'parse-sexp-ignore-comments)
1357 (make-local-variable 'indent-line-function)
1358 (make-local-variable 'indent-region-function)
1359 (make-local-variable 'comment-start)
1360 (make-local-variable 'comment-end)
1361 (make-local-variable 'comment-column)
1362 (make-local-variable 'comment-start-skip)
1363 (make-local-variable 'comment-multi-line)
1364 (make-local-variable 'outline-regexp)
1365 (make-local-variable 'outline-level)
1366 (make-local-variable 'adaptive-fill-regexp)
1367 (make-local-variable 'imenu-generic-expression) ;set in the mode functions
1368 ;; Emacs 19.30 and beyond only, AFAIK
1369 (if (boundp 'fill-paragraph-function)
1370 (progn
1371 (make-local-variable 'fill-paragraph-function)
1372 (setq fill-paragraph-function 'c-fill-paragraph)))
1373 ;; now set their values
1374 (setq paragraph-start (if (memq 'new-re c-emacs-features)
1375 (concat page-delimiter "\\|$")
1376 (concat "^$\\|" page-delimiter))
1377 paragraph-separate paragraph-start
1378 paragraph-ignore-fill-prefix t
1379 require-final-newline t
1380 parse-sexp-ignore-comments t
1381 indent-line-function 'c-indent-line
1382 indent-region-function 'c-indent-region
1383 outline-regexp "[^#\n\^M]"
1384 outline-level 'c-outline-level
1385 comment-column 32
1386 comment-start-skip "/\\*+ *\\|// *"
1387 adaptive-fill-regexp nil)
1388 ;; we have to do something special for c-offsets-alist so that the
1389 ;; buffer local value has its own alist structure.
1390 (setq c-offsets-alist (copy-alist c-offsets-alist))
1391 ;; setup the comment indent variable in a Emacs version portable way
1392 ;; ignore any byte compiler warnings you might get here
1393 (if (boundp 'comment-indent-function)
1394 (progn
1395 (make-local-variable 'comment-indent-function)
1396 (setq comment-indent-function 'c-comment-indent))
1397 (make-local-variable 'comment-indent-hook)
1398 (setq comment-indent-hook 'c-comment-indent))
1399 ;; Put C menu into menubar and on popup menu for XEmacs 19. I think
1400 ;; this happens automatically for Emacs 19.
1401 (if (and (boundp 'current-menubar)
1402 current-menubar
1403 (not (assoc mode-name current-menubar)))
1404 ;; its possible that this buffer has changed modes from one of
1405 ;; the other cc-mode modes. In that case, only the menubar
1406 ;; title of the menu changes.
1407 (let ((modes (copy-sequence c-list-of-mode-names))
1408 changed-p)
1409 (setq modes (delete major-mode modes))
1410 (while modes
1411 (if (not (assoc (car modes) current-menubar))
1412 (setq modes (cdr modes))
1413 (relabel-menu-item (list (car modes)) mode-name)
1414 (setq modes nil
1415 changed-p t)))
1416 (if (not changed-p)
1417 (progn
1418 (set-buffer-menubar (copy-sequence current-menubar))
1419 (add-menu nil mode-name c-mode-menu)))))
1420 (if (boundp 'mode-popup-menu)
1421 (setq mode-popup-menu
1422 (cons (concat mode-name " Mode Commands") c-mode-menu)))
1423 ;; put auto-hungry designators onto minor-mode-alist, but only once
1424 (or (assq 'c-auto-hungry-string minor-mode-alist)
1425 (setq minor-mode-alist
1426 (cons '(c-auto-hungry-string c-auto-hungry-string)
1427 minor-mode-alist))))
1428
1429 (defun c-postprocess-file-styles ()
1430 "Function that post processes relevant file local variables.
1431 Currently, this function simply applies any style and offset settings
1432 found in the file's Local Variable list. It first applies any style
1433 setting found in `c-file-style', then it applies any offset settings
1434 it finds in `c-file-offsets'."
1435 ;; apply file styles and offsets
1436 (and c-file-style
1437 (c-set-style c-file-style))
1438 (and c-file-offsets
1439 (mapcar
1440 (function
1441 (lambda (langentry)
1442 (let ((langelem (car langentry))
1443 (offset (cdr langentry)))
1444 (c-set-offset langelem offset)
1445 )))
1446 c-file-offsets)))
1447
1448 ;; Add the postprocessing function to hack-local-variables-hook. As
1449 ;; of 28-Aug-1995, XEmacs 19.12 and Emacs 19.29 support this.
1450 (and (fboundp 'add-hook)
1451 (add-hook 'hack-local-variables-hook 'c-postprocess-file-styles))
1452
1453 (defun c-enable-//-in-c-mode ()
1454 "Enables // as a comment delimiter in `c-mode'.
1455 ANSI C currently does *not* allow this, although many C compilers
1456 support optional C++ style comments. To use, call this function from
1457 your `.emacs' file before you visit any C files. The changes are
1458 global and affect all future `c-mode' buffers."
1459 (c-setup-dual-comments c-mode-syntax-table)
1460 (setq-default c-C-comment-start-regexp c-C++-comment-start-regexp))
1461
1462
1463 ;; macros must be defined before first use
1464 (defmacro c-point (position)
1465 ;; Returns the value of point at certain commonly referenced POSITIONs.
1466 ;; POSITION can be one of the following symbols:
1467 ;;
1468 ;; bol -- beginning of line
1469 ;; eol -- end of line
1470 ;; bod -- beginning of defun
1471 ;; boi -- back to indentation
1472 ;; ionl -- indentation of next line
1473 ;; iopl -- indentation of previous line
1474 ;; bonl -- beginning of next line
1475 ;; bopl -- beginning of previous line
1476 ;;
1477 ;; This function does not modify point or mark.
1478 (or (and (eq 'quote (car-safe position))
1479 (null (cdr (cdr position))))
1480 (error "bad buffer position requested: %s" position))
1481 (setq position (nth 1 position))
1482 (` (let ((here (point)))
1483 (,@ (cond
1484 ((eq position 'bol) '((beginning-of-line)))
1485 ((eq position 'eol) '((end-of-line)))
1486 ((eq position 'bod)
1487 '((beginning-of-defun)
1488 ;; if defun-prompt-regexp is non-nil, b-o-d won't leave
1489 ;; us at the open brace.
1490 (and (boundp 'defun-prompt-regexp)
1491 defun-prompt-regexp
1492 (looking-at defun-prompt-regexp)
1493 (goto-char (match-end 0)))
1494 ))
1495 ((eq position 'boi) '((back-to-indentation)))
1496 ((eq position 'bonl) '((forward-line 1)))
1497 ((eq position 'bopl) '((forward-line -1)))
1498 ((eq position 'iopl)
1499 '((forward-line -1)
1500 (back-to-indentation)))
1501 ((eq position 'ionl)
1502 '((forward-line 1)
1503 (back-to-indentation)))
1504 (t (error "unknown buffer position requested: %s" position))
1505 ))
1506 (prog1
1507 (point)
1508 (goto-char here))
1509 ;; workaround for an Emacs18 bug -- blech! Well, at least it
1510 ;; doesn't hurt for v19
1511 (,@ nil)
1512 )))
1513
1514 (defmacro c-auto-newline ()
1515 ;; if auto-newline feature is turned on, insert a newline character
1516 ;; and return t, otherwise return nil.
1517 (` (and c-auto-newline
1518 (not (c-in-literal))
1519 (not (newline)))))
1520
1521 (defmacro c-safe (&rest body)
1522 ;; safely execute BODY, return nil if an error occurred
1523 (` (condition-case nil
1524 (progn (,@ body))
1525 (error nil))))
1526
1527 (defun c-insert-special-chars (arg)
1528 ;; simply call self-insert-command in Emacs 19
1529 (self-insert-command (prefix-numeric-value arg)))
1530
1531 (defun c-intersect-lists (list alist)
1532 ;; return the element of ALIST that matches the first element found
1533 ;; in LIST. Uses assq.
1534 (let (match)
1535 (while (and list
1536 (not (setq match (assq (car list) alist))))
1537 (setq list (cdr list)))
1538 match))
1539
1540 (defun c-lookup-lists (list alist1 alist2)
1541 ;; first, find the first entry from LIST that is present in ALIST1,
1542 ;; then find the entry in ALIST2 for that entry.
1543 (assq (car (c-intersect-lists list alist1)) alist2))
1544
1545
1546 ;; This is used by indent-for-comment to decide how much to indent a
1547 ;; comment in C code based on its context.
1548 (defun c-comment-indent ()
1549 (if (looking-at (concat "^\\(" c-comment-start-regexp "\\)"))
1550 0 ;Existing comment at bol stays there.
1551 (let ((opoint (point))
1552 placeholder)
1553 (save-excursion
1554 (beginning-of-line)
1555 (cond
1556 ;; CASE 1: A comment following a solitary close-brace should
1557 ;; have only one space.
1558 ((looking-at (concat "[ \t]*}[ \t]*\\($\\|"
1559 c-comment-start-regexp
1560 "\\)"))
1561 (search-forward "}")
1562 (1+ (current-column)))
1563 ;; CASE 2: 2 spaces after #endif
1564 ((or (looking-at "^#[ \t]*endif[ \t]*")
1565 (looking-at "^#[ \t]*else[ \t]*"))
1566 7)
1567 ;; CASE 3: when comment-column is nil, calculate the offset
1568 ;; according to c-offsets-alist. E.g. identical to hitting
1569 ;; TAB.
1570 ((and c-indent-comments-syntactically-p
1571 (save-excursion
1572 (skip-chars-forward " \t")
1573 (or (looking-at comment-start)
1574 (eolp))))
1575 (let ((syntax (c-guess-basic-syntax)))
1576 ;; BOGOSITY ALERT: if we're looking at the eol, its
1577 ;; because indent-for-comment hasn't put the comment-start
1578 ;; in the buffer yet. this will screw up the syntactic
1579 ;; analysis so we kludge in the necessary info. Another
1580 ;; kludge is that if we're at the bol, then we really want
1581 ;; to ignore any anchoring as specified by
1582 ;; c-comment-only-line-offset since it doesn't apply here.
1583 (if (save-excursion
1584 (beginning-of-line)
1585 (skip-chars-forward " \t")
1586 (eolp))
1587 (c-add-syntax 'comment-intro))
1588 (let ((c-comment-only-line-offset
1589 (if (consp c-comment-only-line-offset)
1590 c-comment-only-line-offset
1591 (cons c-comment-only-line-offset
1592 c-comment-only-line-offset))))
1593 (apply '+ (mapcar 'c-get-offset syntax)))))
1594 ;; CASE 4: use comment-column if previous line is a
1595 ;; comment-only line indented to the left of comment-column
1596 ((save-excursion
1597 (beginning-of-line)
1598 (and (not (bobp))
1599 (forward-line -1))
1600 (skip-chars-forward " \t")
1601 (prog1
1602 (looking-at c-comment-start-regexp)
1603 (setq placeholder (point))))
1604 (goto-char placeholder)
1605 (if (< (current-column) comment-column)
1606 comment-column
1607 (current-column)))
1608 ;; CASE 5: If comment-column is 0, and nothing but space
1609 ;; before the comment, align it at 0 rather than 1.
1610 ((progn
1611 (goto-char opoint)
1612 (skip-chars-backward " \t")
1613 (and (= comment-column 0) (bolp)))
1614 0)
1615 ;; CASE 6: indent at comment column except leave at least one
1616 ;; space.
1617 (t (max (1+ (current-column))
1618 comment-column))
1619 )))))
1620
1621 ;; used by outline-minor-mode
1622 (defun c-outline-level ()
1623 (save-excursion
1624 (skip-chars-forward "\t ")
1625 (current-column)))
1626
1627 ;; active regions, and auto-newline/hungry delete key
1628 (defun c-keep-region-active ()
1629 ;; Do whatever is necessary to keep the region active in
1630 ;; XEmacs 19. ignore byte-compiler warnings you might see
1631 (and (boundp 'zmacs-region-stays)
1632 (setq zmacs-region-stays t)))
1633
1634 (defun c-update-modeline ()
1635 ;; set the c-auto-hungry-string for the correct designation on the modeline
1636 (setq c-auto-hungry-string
1637 (if c-auto-newline
1638 (if c-hungry-delete-key "/ah" "/a")
1639 (if c-hungry-delete-key "/h" nil)))
1640 ;; updates the modeline for all Emacsen
1641 (if (memq 'v19 c-emacs-features)
1642 (force-mode-line-update)
1643 (set-buffer-modified-p (buffer-modified-p))))
1644
1645 (defun c-calculate-state (arg prevstate)
1646 ;; Calculate the new state of PREVSTATE, t or nil, based on arg. If
1647 ;; arg is nil or zero, toggle the state. If arg is negative, turn
1648 ;; the state off, and if arg is positive, turn the state on
1649 (if (or (not arg)
1650 (zerop (setq arg (prefix-numeric-value arg))))
1651 (not prevstate)
1652 (> arg 0)))
1653
1654 (defun c-toggle-auto-state (arg)
1655 "Toggle auto-newline feature.
1656 Optional numeric ARG, if supplied turns on auto-newline when positive,
1657 turns it off when negative, and just toggles it when zero.
1658
1659 When the auto-newline feature is enabled (as evidenced by the `/a' or
1660 `/ah' on the modeline after the mode name) newlines are automatically
1661 inserted after special characters such as brace, comma, semi-colon,
1662 and colon."
1663 (interactive "P")
1664 (setq c-auto-newline (c-calculate-state arg c-auto-newline))
1665 (c-update-modeline)
1666 (c-keep-region-active))
1667
1668 (defun c-toggle-hungry-state (arg)
1669 "Toggle hungry-delete-key feature.
1670 Optional numeric ARG, if supplied turns on hungry-delete when positive,
1671 turns it off when negative, and just toggles it when zero.
1672
1673 When the hungry-delete-key feature is enabled (as evidenced by the
1674 `/h' or `/ah' on the modeline after the mode name) the delete key
1675 gobbles all preceding whitespace in one fell swoop."
1676 (interactive "P")
1677 (setq c-hungry-delete-key (c-calculate-state arg c-hungry-delete-key))
1678 (c-update-modeline)
1679 (c-keep-region-active))
1680
1681 (defun c-toggle-auto-hungry-state (arg)
1682 "Toggle auto-newline and hungry-delete-key features.
1683 Optional numeric ARG, if supplied turns on auto-newline and
1684 hungry-delete when positive, turns them off when negative, and just
1685 toggles them when zero.
1686
1687 See `c-toggle-auto-state' and `c-toggle-hungry-state' for details."
1688 (interactive "P")
1689 (setq c-auto-newline (c-calculate-state arg c-auto-newline))
1690 (setq c-hungry-delete-key (c-calculate-state arg c-hungry-delete-key))
1691 (c-update-modeline)
1692 (c-keep-region-active))
1693
1694
1695 ;; COMMANDS
1696 (defun c-electric-delete (arg)
1697 "Deletes preceding character or whitespace.
1698 If `c-hungry-delete-key' is non-nil, as evidenced by the \"/h\" or
1699 \"/ah\" string on the mode line, then all preceding whitespace is
1700 consumed. If however an ARG is supplied, or `c-hungry-delete-key' is
1701 nil, or point is inside a literal then the function in the variable
1702 `c-delete-function' is called."
1703 (interactive "P")
1704 (if (or (not c-hungry-delete-key)
1705 arg
1706 (c-in-literal))
1707 (funcall c-delete-function (prefix-numeric-value arg))
1708 (let ((here (point)))
1709 (skip-chars-backward " \t\n")
1710 (if (/= (point) here)
1711 (delete-region (point) here)
1712 (funcall c-delete-function 1)
1713 ))))
1714
1715 (defun c-electric-pound (arg)
1716 "Electric pound (`#') insertion.
1717 Inserts a `#' character specially depending on the variable
1718 `c-electric-pound-behavior'. If a numeric ARG is supplied, or if
1719 point is inside a literal, nothing special happens."
1720 (interactive "P")
1721 (if (or (c-in-literal)
1722 arg
1723 (not (memq 'alignleft c-electric-pound-behavior)))
1724 ;; do nothing special
1725 (self-insert-command (prefix-numeric-value arg))
1726 ;; place the pound character at the left edge
1727 (let ((pos (- (point-max) (point)))
1728 (bolp (bolp)))
1729 (beginning-of-line)
1730 (delete-horizontal-space)
1731 (insert-char last-command-char 1)
1732 (and (not bolp)
1733 (goto-char (- (point-max) pos)))
1734 )))
1735
1736 (defun c-electric-brace (arg)
1737 "Insert a brace.
1738
1739 If the auto-newline feature is turned on, as evidenced by the \"/a\"
1740 or \"/ah\" string on the mode line, newlines are inserted before and
1741 after braces based on the value of `c-hanging-braces-alist'.
1742
1743 Also, the line is re-indented unless a numeric ARG is supplied, there
1744 are non-whitespace characters present on the line after the brace, or
1745 the brace is inserted inside a literal."
1746 (interactive "P")
1747 (let* ((c-state-cache (c-parse-state))
1748 (safepos (c-safe-position (point) c-state-cache))
1749 (literal (c-in-literal safepos)))
1750 ;; if we're in a literal, or we're not at the end of the line, or
1751 ;; a numeric arg is provided, or auto-newlining is turned off,
1752 ;; then just insert the character.
1753 (if (or literal arg
1754 ; (not c-auto-newline)
1755 (not (looking-at "[ \t]*$")))
1756 (c-insert-special-chars arg)
1757 (let* ((syms '(class-open class-close defun-open defun-close
1758 inline-open inline-close brace-list-open brace-list-close
1759 brace-list-intro brace-list-entry block-open block-close
1760 substatement-open statement-case-open))
1761 ;; we want to inhibit blinking the paren since this will
1762 ;; be most disruptive. we'll blink it ourselves later on
1763 (old-blink-paren (if (boundp 'blink-paren-function)
1764 blink-paren-function
1765 blink-paren-hook))
1766 blink-paren-function ; emacs19
1767 blink-paren-hook ; emacs18
1768 (insertion-point (point))
1769 delete-temp-newline
1770 (preserve-p (= 32 (char-syntax (preceding-char))))
1771 ;; shut this up too
1772 (c-echo-syntactic-information-p nil)
1773 (syntax (progn
1774 ;; only insert a newline if there is
1775 ;; non-whitespace behind us
1776 (if (save-excursion
1777 (skip-chars-backward " \t")
1778 (not (bolp)))
1779 (progn (newline)
1780 (setq delete-temp-newline t)))
1781 (self-insert-command (prefix-numeric-value arg))
1782 ;; state cache doesn't change
1783 (c-guess-basic-syntax)))
1784 (newlines (and
1785 c-auto-newline
1786 (or (c-lookup-lists syms syntax c-hanging-braces-alist)
1787 '(ignore before after)))))
1788 ;; If syntax is a function symbol, then call it using the
1789 ;; defined semantics.
1790 (if (and (not (consp (cdr newlines)))
1791 (fboundp (cdr newlines)))
1792 (let ((c-syntactic-context syntax))
1793 (setq newlines
1794 (funcall (cdr newlines) (car newlines) insertion-point))))
1795 ;; does a newline go before the open brace?
1796 (if (memq 'before newlines)
1797 ;; we leave the newline we've put in there before,
1798 ;; but we need to re-indent the line above
1799 (let ((pos (- (point-max) (point)))
1800 (here (point))
1801 (c-state-cache c-state-cache))
1802 (forward-line -1)
1803 ;; we may need to update the cache. this should still be
1804 ;; faster than recalculating the state in many cases
1805 (save-excursion
1806 (save-restriction
1807 (narrow-to-region here (point))
1808 (if (and (c-safe (progn (backward-up-list -1) t))
1809 (memq (preceding-char) '(?\) ?}))
1810 (progn (widen)
1811 (c-safe (progn (forward-sexp -1) t))))
1812 (setq c-state-cache
1813 (c-hack-state (point) 'open c-state-cache))
1814 (if (and (car c-state-cache)
1815 (not (consp (car c-state-cache)))
1816 (<= (point) (car c-state-cache)))
1817 (setq c-state-cache (cdr c-state-cache))
1818 ))))
1819 (let ((here (point))
1820 (shift (c-indent-line)))
1821 (setq c-state-cache (c-adjust-state (c-point 'bol) here
1822 (- shift) c-state-cache)))
1823 (goto-char (- (point-max) pos))
1824 ;; if the buffer has changed due to the indentation, we
1825 ;; need to recalculate syntax for the current line, but
1826 ;; we won't need to update the state cache.
1827 (if (/= (point) here)
1828 (setq syntax (c-guess-basic-syntax))))
1829 ;; must remove the newline we just stuck in (if we really did it)
1830 (and delete-temp-newline
1831 (save-excursion
1832 ;; if there is whitespace before point, then preserve
1833 ;; at least one space.
1834 (delete-indentation)
1835 (just-one-space)
1836 (if (not preserve-p)
1837 (delete-char -1))))
1838 ;; since we're hanging the brace, we need to recalculate
1839 ;; syntax. Update the state to accurately reflect the
1840 ;; beginning of the line. We punt if we cross any open or
1841 ;; closed parens because its just too hard to modify the
1842 ;; known state. This limitation will be fixed in v5.
1843 (save-excursion
1844 (let ((bol (c-point 'bol)))
1845 (if (zerop (car (parse-partial-sexp bol (1- (point)))))
1846 (setq c-state-cache (c-whack-state bol c-state-cache)
1847 syntax (c-guess-basic-syntax))
1848 ;; gotta punt. this requires some horrible kludgery
1849 (beginning-of-line)
1850 (makunbound 'c-state-cache)
1851 (setq c-state-cache (c-parse-state)
1852 syntax nil))))
1853 )
1854 ;; now adjust the line's indentation. don't update the state
1855 ;; cache since c-guess-basic-syntax isn't called when the
1856 ;; syntax is passed to c-indent-line
1857 (let ((here (point))
1858 (shift (c-indent-line syntax)))
1859 (setq c-state-cache (c-adjust-state (c-point 'bol) here
1860 (- shift) c-state-cache)))
1861 ;; Do all appropriate clean ups
1862 (let ((here (point))
1863 (pos (- (point-max) (point)))
1864 mbeg mend)
1865 ;; clean up empty defun braces
1866 (if (and c-auto-newline
1867 (memq 'empty-defun-braces c-cleanup-list)
1868 (= last-command-char ?\})
1869 (c-intersect-lists '(defun-close class-close inline-close)
1870 syntax)
1871 (progn
1872 (forward-char -1)
1873 (skip-chars-backward " \t\n")
1874 (= (preceding-char) ?\{))
1875 ;; make sure matching open brace isn't in a comment
1876 (not (c-in-literal)))
1877 (delete-region (point) (1- here)))
1878 ;; clean up brace-else-brace
1879 (if (and c-auto-newline
1880 (memq 'brace-else-brace c-cleanup-list)
1881 (= last-command-char ?\{)
1882 (re-search-backward "}[ \t\n]*else[ \t\n]*{" nil t)
1883 (progn
1884 (setq mbeg (match-beginning 0)
1885 mend (match-end 0))
1886 (= mend here))
1887 (not (c-in-literal)))
1888 (progn
1889 (delete-region mbeg mend)
1890 (insert "} else {")))
1891 (goto-char (- (point-max) pos))
1892 )
1893 ;; does a newline go after the brace?
1894 (if (memq 'after newlines)
1895 (progn
1896 (newline)
1897 ;; update on c-state-cache
1898 (let* ((bufpos (- (point) 2))
1899 (which (if (= (char-after bufpos) ?{) 'open 'close))
1900 (c-state-cache (c-hack-state bufpos which c-state-cache)))
1901 (c-indent-line))))
1902 ;; blink the paren
1903 (and (= last-command-char ?\})
1904 old-blink-paren
1905 (save-excursion
1906 (c-backward-syntactic-ws safepos)
1907 (if (boundp 'blink-paren-function)
1908 (funcall old-blink-paren)
1909 (run-hooks old-blink-paren))))
1910 ))))
1911
1912 (defun c-electric-slash (arg)
1913 "Insert a slash character.
1914 If slash is second of a double-slash C++ style comment introducing
1915 construct, and we are on a comment-only-line, indent line as comment.
1916 If numeric ARG is supplied or point is inside a literal, indentation
1917 is inhibited."
1918 (interactive "P")
1919 (let ((indentp (and (not arg)
1920 (= (preceding-char) ?/)
1921 (= last-command-char ?/)
1922 (not (c-in-literal))))
1923 ;; shut this up
1924 (c-echo-syntactic-information-p nil))
1925 (self-insert-command (prefix-numeric-value arg))
1926 (if indentp
1927 (c-indent-line))))
1928
1929 (defun c-electric-star (arg)
1930 "Insert a star character.
1931 If the star is the second character of a C style comment introducing
1932 construct, and we are on a comment-only-line, indent line as comment.
1933 If numeric ARG is supplied or point is inside a literal, indentation
1934 is inhibited."
1935 (interactive "P")
1936 (self-insert-command (prefix-numeric-value arg))
1937 ;; if we are in a literal, or if arg is given do not re-indent the
1938 ;; current line, unless this star introduces a comment-only line.
1939 (if (and (not arg)
1940 (memq (c-in-literal) '(c))
1941 (= (preceding-char) ?*)
1942 (save-excursion
1943 (forward-char -1)
1944 (skip-chars-backward "*")
1945 (if (= (preceding-char) ?/)
1946 (forward-char -1))
1947 (skip-chars-backward " \t")
1948 (bolp)))
1949 ;; shut this up
1950 (let (c-echo-syntactic-information-p)
1951 (c-indent-line))
1952 ))
1953
1954 (defun c-electric-semi&comma (arg)
1955 "Insert a comma or semicolon.
1956 When the auto-newline feature is turned on, as evidenced by the \"/a\"
1957 or \"/ah\" string on the mode line, a newline might be inserted. See
1958 the variable `c-hanging-semi&comma-criteria' for how newline insertion
1959 is determined.
1960
1961 When semicolon is inserted, the line is re-indented unless a numeric
1962 arg is supplied, point is inside a literal, or there are
1963 non-whitespace characters on the line following the semicolon."
1964 (interactive "P")
1965 (let* ((lim (c-most-enclosing-brace (c-parse-state)))
1966 (literal (c-in-literal lim))
1967 (here (point))
1968 ;; shut this up
1969 (c-echo-syntactic-information-p nil))
1970 (if (or literal
1971 arg
1972 (not (looking-at "[ \t]*$")))
1973 (c-insert-special-chars arg)
1974 ;; do some special stuff with the character
1975 (self-insert-command (prefix-numeric-value arg))
1976 ;; do all cleanups, reindentations, and newline insertions, but
1977 ;; only if c-auto-newline is turned on
1978 (if (not c-auto-newline) nil
1979 ;; clean ups
1980 (let ((pos (- (point-max) (point))))
1981 (if (and (or (and
1982 (= last-command-char ?,)
1983 (memq 'list-close-comma c-cleanup-list))
1984 (and
1985 (= last-command-char ?\;)
1986 (memq 'defun-close-semi c-cleanup-list)))
1987 (progn
1988 (forward-char -1)
1989 (skip-chars-backward " \t\n")
1990 (= (preceding-char) ?}))
1991 ;; make sure matching open brace isn't in a comment
1992 (not (c-in-literal lim)))
1993 (delete-region (point) here))
1994 (goto-char (- (point-max) pos)))
1995 ;; re-indent line
1996 (c-indent-line)
1997 ;; check to see if a newline should be added
1998 (let ((criteria c-hanging-semi&comma-criteria)
1999 answer add-newline-p)
2000 (while criteria
2001 (setq answer (funcall (car criteria)))
2002 ;; only nil value means continue checking
2003 (if (not answer)
2004 (setq criteria (cdr criteria))
2005 (setq criteria nil)
2006 ;; only 'stop specifically says do not add a newline
2007 (setq add-newline-p (not (eq answer 'stop)))
2008 ))
2009 (if add-newline-p
2010 (progn (newline)
2011 (c-indent-line)))
2012 )))))
2013
2014 (defun c-semi&comma-inside-parenlist ()
2015 "Determine if a newline should be added after a semicolon.
2016 If a comma was inserted, no determination is made. If a semicolon was
2017 inserted inside a parenthesis list, no newline is added otherwise a
2018 newline is added. In either case, checking is stopped. This supports
2019 exactly the old newline insertion behavior."
2020 ;; newline only after semicolon, but only if that semicolon is not
2021 ;; inside a parenthesis list (e.g. a for loop statement)
2022 (if (/= last-command-char ?\;)
2023 nil ; continue checking
2024 (if (condition-case nil
2025 (save-excursion
2026 (up-list -1)
2027 (/= (following-char) ?\())
2028 (error t))
2029 t
2030 'stop)))
2031
2032 (defun c-electric-colon (arg)
2033 "Insert a colon.
2034
2035 If the auto-newline feature is turned on, as evidenced by the \"/a\"
2036 or \"/ah\" string on the mode line, newlines are inserted before and
2037 after colons based on the value of `c-hanging-colons-alist'.
2038
2039 Also, the line is re-indented unless a numeric ARG is supplied, there
2040 are non-whitespace characters present on the line after the colon, or
2041 the colon is inserted inside a literal.
2042
2043 This function cleans up double colon scope operators based on the
2044 value of `c-cleanup-list'."
2045 (interactive "P")
2046 (let* ((bod (c-point 'bod))
2047 (literal (c-in-literal bod))
2048 syntax newlines
2049 ;; shut this up
2050 (c-echo-syntactic-information-p nil))
2051 (if (or literal
2052 arg
2053 (not (looking-at "[ \t]*$")))
2054 (c-insert-special-chars arg)
2055 ;; insert the colon, then do any specified cleanups
2056 (self-insert-command (prefix-numeric-value arg))
2057 (let ((pos (- (point-max) (point)))
2058 (here (point)))
2059 (if (and c-auto-newline
2060 (memq 'scope-operator c-cleanup-list)
2061 (= (preceding-char) ?:)
2062 (progn
2063 (forward-char -1)
2064 (skip-chars-backward " \t\n")
2065 (= (preceding-char) ?:))
2066 (not (c-in-literal))
2067 (not (= (char-after (- (point) 2)) ?:)))
2068 (delete-region (point) (1- here)))
2069 (goto-char (- (point-max) pos)))
2070 ;; lets do some special stuff with the colon character
2071 (setq syntax (c-guess-basic-syntax)
2072 ;; some language elements can only be determined by
2073 ;; checking the following line. Lets first look for ones
2074 ;; that can be found when looking on the line with the
2075 ;; colon
2076 newlines
2077 (and c-auto-newline
2078 (or (c-lookup-lists '(case-label label access-label)
2079 syntax c-hanging-colons-alist)
2080 (c-lookup-lists '(member-init-intro inher-intro)
2081 (prog2
2082 (insert "\n")
2083 (c-guess-basic-syntax)
2084 (delete-char -1))
2085 c-hanging-colons-alist))))
2086 ;; indent the current line
2087 (c-indent-line syntax)
2088 ;; does a newline go before the colon? Watch out for already
2089 ;; non-hung colons. However, we don't unhang them because that
2090 ;; would be a cleanup (and anti-social).
2091 (if (and (memq 'before newlines)
2092 (save-excursion
2093 (skip-chars-backward ": \t")
2094 (not (bolp))))
2095 (let ((pos (- (point-max) (point))))
2096 (forward-char -1)
2097 (newline)
2098 (c-indent-line)
2099 (goto-char (- (point-max) pos))))
2100 ;; does a newline go after the colon?
2101 (if (memq 'after (cdr-safe newlines))
2102 (progn
2103 (newline)
2104 (c-indent-line)))
2105 )))
2106
2107 (defun c-electric-lt-gt (arg)
2108 "Insert a less-than, or greater-than character.
2109 When the auto-newline feature is turned on, as evidenced by the \"/a\"
2110 or \"/ah\" string on the mode line, the line will be re-indented if
2111 the character inserted is the second of a C++ style stream operator
2112 and the buffer is in C++ mode.
2113
2114 The line will also not be re-indented if a numeric argument is
2115 supplied, or point is inside a literal."
2116 (interactive "P")
2117 (let ((indentp (and (not arg)
2118 (= (preceding-char) last-command-char)
2119 (not (c-in-literal))))
2120 ;; shut this up
2121 (c-echo-syntactic-information-p nil))
2122 (self-insert-command (prefix-numeric-value arg))
2123 (if indentp
2124 (c-indent-line))))
2125
2126 ;; set up electric character functions to work with pending-del,
2127 ;; (a.k.a. delsel) mode. All symbols get the t value except
2128 ;; c-electric-delete which gets 'supersede.
2129 (mapcar
2130 (function
2131 (lambda (sym)
2132 (put sym 'delete-selection t) ; for delsel (Emacs)
2133 (put sym 'pending-delete t))) ; for pending-del (XEmacs)
2134 '(c-electric-pound
2135 c-electric-brace
2136 c-electric-slash
2137 c-electric-star
2138 c-electric-semi&comma
2139 c-electric-lt-gt
2140 c-electric-colon))
2141 (put 'c-electric-delete 'delete-selection 'supersede) ; delsel
2142 (put 'c-electric-delete 'pending-delete 'supersede) ; pending-del
2143
2144
2145
2146 (defun c-read-offset (langelem)
2147 ;; read new offset value for LANGELEM from minibuffer. return a
2148 ;; legal value only
2149 (let* ((oldoff (cdr-safe (assq langelem c-offsets-alist)))
2150 (defstr (format "(default %s): " oldoff))
2151 (errmsg (concat "Offset must be int, func, var, "
2152 "or in [+,-,++,--,*,/] "
2153 defstr))
2154 (prompt (concat "Offset " defstr))
2155 offset input interned)
2156 (while (not offset)
2157 (setq input (read-string prompt)
2158 offset (cond ((string-equal "" input) oldoff) ; default
2159 ((string-equal "+" input) '+)
2160 ((string-equal "-" input) '-)
2161 ((string-equal "++" input) '++)
2162 ((string-equal "--" input) '--)
2163 ((string-equal "*" input) '*)
2164 ((string-equal "/" input) '/)
2165 ((string-match "^-?[0-9]+$" input)
2166 (string-to-int input))
2167 ((fboundp (setq interned (intern input)))
2168 interned)
2169 ((boundp interned) interned)
2170 ;; error, but don't signal one, keep trying
2171 ;; to read an input value
2172 (t (ding)
2173 (setq prompt errmsg)
2174 nil))))
2175 offset))
2176
2177 (defun c-set-offset (symbol offset &optional add-p)
2178 "Change the value of a syntactic element symbol in `c-offsets-alist'.
2179 SYMBOL is the syntactic element symbol to change and OFFSET is the new
2180 offset for that syntactic element. Optional ADD says to add SYMBOL to
2181 `c-offsets-alist' if it doesn't already appear there."
2182 (interactive
2183 (let* ((langelem
2184 (intern (completing-read
2185 (concat "Syntactic symbol to change"
2186 (if current-prefix-arg " or add" "")
2187 ": ")
2188 (mapcar
2189 (function
2190 (lambda (langelem)
2191 (cons (format "%s" (car langelem)) nil)))
2192 c-offsets-alist)
2193 nil (not current-prefix-arg)
2194 ;; initial contents tries to be the last element
2195 ;; on the syntactic analysis list for the current
2196 ;; line
2197 (let* ((syntax (c-guess-basic-syntax))
2198 (len (length syntax))
2199 (ic (format "%s" (car (nth (1- len) syntax)))))
2200 (if (memq 'v19 c-emacs-features)
2201 (cons ic 0)
2202 ic))
2203 )))
2204 (offset (c-read-offset langelem)))
2205 (list langelem offset current-prefix-arg)))
2206 ;; sanity check offset
2207 (or (eq offset '+)
2208 (eq offset '-)
2209 (eq offset '++)
2210 (eq offset '--)
2211 (eq offset '*)
2212 (eq offset '/)
2213 (integerp offset)
2214 (fboundp offset)
2215 (boundp offset)
2216 (error "Offset must be int, func, var, or in [+,-,++,--,*,/]: %s"
2217 offset))
2218 (let ((entry (assq symbol c-offsets-alist)))
2219 (if entry
2220 (setcdr entry offset)
2221 (if add-p
2222 (setq c-offsets-alist (cons (cons symbol offset) c-offsets-alist))
2223 (error "%s is not a valid syntactic symbol." symbol))))
2224 (c-keep-region-active))
2225
2226 (defun c-set-style-1 (stylevars)
2227 ;; given a style's variable alist, institute the style
2228 (mapcar
2229 (function
2230 (lambda (conscell)
2231 (let ((attr (car conscell))
2232 (val (cdr conscell)))
2233 ;; KLUDGE ALERT: special case for c-offsets-alist
2234 (if (not (eq attr 'c-offsets-alist))
2235 (set attr val)
2236 (mapcar
2237 (function
2238 (lambda (langentry)
2239 (let ((langelem (car langentry))
2240 (offset (cdr langentry)))
2241 (c-set-offset langelem offset)
2242 )))
2243 val))
2244 )))
2245 stylevars))
2246
2247 (defun c-set-style (stylename)
2248 "Set cc-mode variables to use one of several different indentation styles.
2249 STYLENAME is a string representing the desired style from the list of
2250 styles described in the variable `c-style-alist'. See that variable
2251 for details of setting up styles."
2252 (interactive (list (let ((completion-ignore-case t)
2253 (prompt (format "Which %s indentation style? "
2254 mode-name)))
2255 (completing-read prompt c-style-alist nil t))))
2256 (let ((vars (cdr (or (assoc (downcase stylename) c-style-alist)
2257 ;; backwards compatibility
2258 (assoc (upcase stylename) c-style-alist)
2259 )))
2260 (default (cdr (assoc "cc-mode" c-style-alist))))
2261 (or vars (error "Invalid indentation style `%s'" stylename))
2262 (or default (error "No `cc-mode' style found!"))
2263 ;; first reset the style to `cc-mode' to give every style a common
2264 ;; base. Then institute the new style.
2265 (c-set-style-1 default)
2266 (if (not (string= stylename "cc-mode"))
2267 (c-set-style-1 vars)))
2268 (c-keep-region-active))
2269
2270 (defun c-add-style (style descrip &optional set-p)
2271 "Adds a style to `c-style-alist', or updates an existing one.
2272 STYLE is a string identifying the style to add or update. DESCRIP is
2273 an association list describing the style and must be of the form:
2274
2275 ((VARIABLE . VALUE) [(VARIABLE . VALUE) ...])
2276
2277 See the variable `c-style-alist' for the semantics of VARIABLE and
2278 VALUE. This function also sets the current style to STYLE using
2279 `c-set-style' if the optional SET-P flag is non-nil."
2280 (interactive
2281 (let ((stylename (completing-read "Style to add: " c-style-alist))
2282 (description (eval-minibuffer "Style description: ")))
2283 (list stylename description
2284 (y-or-n-p "Set the style too? "))))
2285 (setq style (downcase style))
2286 (let ((s (assoc style c-style-alist)))
2287 (if s
2288 (setcdr s (copy-alist descrip)) ; replace
2289 (setq c-style-alist (cons (cons style descrip) c-style-alist))))
2290 (and set-p (c-set-style style)))
2291
2292 (defun c-fill-paragraph (&optional arg)
2293 "Like \\[fill-paragraph] but handles C and C++ style comments.
2294 If any of the current line is a comment or within a comment,
2295 fill the comment or the paragraph of it that point is in,
2296 preserving the comment indentation or line-starting decorations.
2297
2298 Optional prefix ARG means justify paragraph as well."
2299 (interactive "P")
2300 (let* (comment-start-place
2301 (first-line
2302 ;; Check for obvious entry to comment.
2303 (save-excursion
2304 (beginning-of-line)
2305 (skip-chars-forward " \t\n")
2306 (and (looking-at comment-start-skip)
2307 (setq comment-start-place (point)))))
2308 (re1 (if (memq 'new-re c-emacs-features)
2309 "\\|[ \t]*/\\*[ \t]*$\\|[ \t]*\\*/[ \t]*$\\|[ \t/*]*$"
2310 "\\|^[ \t]*/\\*[ \t]*$\\|^[ \t]*\\*/[ \t]*$\\|^[ \t/*]*$"))
2311 )
2312 (if (and c-double-slash-is-comments-p
2313 (save-excursion
2314 (beginning-of-line)
2315 (looking-at ".*//")))
2316 (let (fill-prefix
2317 ;; Lines containing just a comment start or just an end
2318 ;; should not be filled into paragraphs they are next
2319 ;; to.
2320 (paragraph-start (concat paragraph-start re1))
2321 (paragraph-separate (concat paragraph-separate re1)))
2322 (save-excursion
2323 (beginning-of-line)
2324 ;; Move up to first line of this comment.
2325 (while (and (not (bobp))
2326 (looking-at "[ \t]*//"))
2327 (forward-line -1))
2328 (if (not (looking-at ".*//"))
2329 (forward-line 1))
2330 ;; Find the comment start in this line.
2331 (re-search-forward "[ \t]*//[ \t]*")
2332 ;; Set the fill-prefix to be what all lines except the first
2333 ;; should start with.
2334 (setq fill-prefix (buffer-substring (match-beginning 0)
2335 (match-end 0)))
2336 (save-restriction
2337 ;; Narrow down to just the lines of this comment.
2338 (narrow-to-region (c-point 'bol)
2339 (save-excursion
2340 (forward-line 1)
2341 (while (looking-at fill-prefix)
2342 (forward-line 1))
2343 (point)))
2344 (fill-paragraph arg)
2345 t)))
2346 ;; else C style comments
2347 (if (or first-line
2348 ;; t if we enter a comment between start of function and
2349 ;; this line.
2350 (eq (c-in-literal) 'c)
2351 ;; t if this line contains a comment starter.
2352 (setq first-line
2353 (save-excursion
2354 (beginning-of-line)
2355 (prog1
2356 (re-search-forward comment-start-skip
2357 (save-excursion (end-of-line)
2358 (point))
2359 t)
2360 (setq comment-start-place (point))))))
2361 ;; Inside a comment: fill one comment paragraph.
2362 (let ((fill-prefix
2363 ;; The prefix for each line of this paragraph
2364 ;; is the appropriate part of the start of this line,
2365 ;; up to the column at which text should be indented.
2366 (save-excursion
2367 (beginning-of-line)
2368 (if (looking-at "[ \t]*/\\*.*\\*/")
2369 (progn (re-search-forward comment-start-skip)
2370 (make-string (current-column) ?\ ))
2371 (if first-line (forward-line 1))
2372
2373 (let ((line-width (progn (end-of-line) (current-column))))
2374 (beginning-of-line)
2375 (prog1
2376 (buffer-substring
2377 (point)
2378
2379 ;; How shall we decide where the end of the
2380 ;; fill-prefix is?
2381 (progn
2382 (beginning-of-line)
2383 (skip-chars-forward " \t*" (c-point 'eol))
2384 (point)))
2385
2386 ;; If the comment is only one line followed
2387 ;; by a blank line, calling move-to-column
2388 ;; above may have added some spaces and tabs
2389 ;; to the end of the line; the fill-paragraph
2390 ;; function will then delete it and the
2391 ;; newline following it, so we'll lose a
2392 ;; blank line when we shouldn't. So delete
2393 ;; anything move-to-column added to the end
2394 ;; of the line. We record the line width
2395 ;; instead of the position of the old line
2396 ;; end because move-to-column might break a
2397 ;; tab into spaces, and the new characters
2398 ;; introduced there shouldn't be deleted.
2399
2400 ;; If you can see a better way to do this,
2401 ;; please make the change. This seems very
2402 ;; messy to me.
2403 (delete-region (progn (move-to-column line-width)
2404 (point))
2405 (progn (end-of-line) (point))))))))
2406
2407 ;; Lines containing just a comment start or just an end
2408 ;; should not be filled into paragraphs they are next
2409 ;; to.
2410 (paragraph-start (concat paragraph-start re1))
2411 (paragraph-separate (concat paragraph-separate re1))
2412 (chars-to-delete 0))
2413 (save-restriction
2414 ;; Don't fill the comment together with the code
2415 ;; following it. So temporarily exclude everything
2416 ;; before the comment start, and everything after the
2417 ;; line where the comment ends. If comment-start-place
2418 ;; is non-nil, the comment starter is there. Otherwise,
2419 ;; point is inside the comment.
2420 (narrow-to-region (save-excursion
2421 (if comment-start-place
2422 (goto-char comment-start-place)
2423 (search-backward "/*"))
2424 ;; Protect text before the comment
2425 ;; start by excluding it. Add
2426 ;; spaces to bring back proper
2427 ;; indentation of that point.
2428 (let ((column (current-column)))
2429 (prog1 (point)
2430 (setq chars-to-delete column)
2431 (insert-char ?\ column))))
2432 (save-excursion
2433 (if comment-start-place
2434 (goto-char (+ comment-start-place 2)))
2435 (search-forward "*/" nil 'move)
2436 (forward-line 1)
2437 (point)))
2438 (fill-paragraph arg)
2439 (save-excursion
2440 ;; Delete the chars we inserted to avoid clobbering
2441 ;; the stuff before the comment start.
2442 (goto-char (point-min))
2443 (if (> chars-to-delete 0)
2444 (delete-region (point) (+ (point) chars-to-delete)))
2445 ;; Find the comment ender (should be on last line of
2446 ;; buffer, given the narrowing) and don't leave it on
2447 ;; its own line, unless that's the style that's desired.
2448 (goto-char (point-max))
2449 (forward-line -1)
2450 (search-forward "*/" nil 'move)
2451 (beginning-of-line)
2452 (if (and c-hanging-comment-ender-p
2453 (looking-at "[ \t]*\\*/"))
2454 ;(delete-indentation)))))
2455 (let ((fill-column (+ fill-column 9999)))
2456 (forward-line -1)
2457 (fill-region-as-paragraph (point) (point-max))))))
2458 t)))))
2459
2460 ;; better movement routines for ThisStyleOfVariablesCommonInCPlusPlus
2461 ;; originally contributed by Terry_Glanfield.Southern@rxuk.xerox.com
2462 (defun c-forward-into-nomenclature (&optional arg)
2463 "Move forward to end of a nomenclature section or word.
2464 With arg, to it arg times."
2465 (interactive "p")
2466 (let ((case-fold-search nil))
2467 (if (> arg 0)
2468 (re-search-forward "\\W*\\([A-Z]*[a-z0-9]*\\)" (point-max) t arg)
2469 (while (and (< arg 0)
2470 (re-search-backward
2471 "\\(\\(\\W\\|[a-z0-9]\\)[A-Z]+\\|\\W\\w+\\)"
2472 (point-min) 0))
2473 (forward-char 1)
2474 (setq arg (1+ arg)))))
2475 (c-keep-region-active))
2476
2477 (defun c-backward-into-nomenclature (&optional arg)
2478 "Move backward to beginning of a nomenclature section or word.
2479 With optional ARG, move that many times. If ARG is negative, move
2480 forward."
2481 (interactive "p")
2482 (c-forward-into-nomenclature (- arg))
2483 (c-keep-region-active))
2484
2485 (defun c-scope-operator ()
2486 "Insert a double colon scope operator at point.
2487 No indentation or other \"electric\" behavior is performed."
2488 (interactive)
2489 (insert "::"))
2490
2491
2492 (defun c-beginning-of-statement (&optional count lim sentence-flag)
2493 "Go to the beginning of the innermost C statement.
2494 With prefix arg, go back N - 1 statements. If already at the
2495 beginning of a statement then go to the beginning of the preceding
2496 one. If within a string or comment, or next to a comment (only
2497 whitespace between), move by sentences instead of statements.
2498
2499 When called from a program, this function takes 3 optional args: the
2500 repetition count, a buffer position limit which is the farthest back
2501 to search, and a flag saying whether to do sentence motion when in a
2502 comment."
2503 (interactive (list (prefix-numeric-value current-prefix-arg)
2504 nil t))
2505 (let ((here (point))
2506 (count (or count 1))
2507 (lim (or lim (c-point 'bod)))
2508 state)
2509 (save-excursion
2510 (goto-char lim)
2511 (setq state (parse-partial-sexp (point) here nil nil)))
2512 (if (and sentence-flag
2513 (or (nth 3 state)
2514 (nth 4 state)
2515 (looking-at (concat "[ \t]*" comment-start-skip))
2516 (save-excursion
2517 (skip-chars-backward " \t")
2518 (goto-char (- (point) 2))
2519 (looking-at "\\*/"))))
2520 (forward-sentence (- count))
2521 (while (> count 0)
2522 (c-beginning-of-statement-1 lim)
2523 (setq count (1- count)))
2524 (while (< count 0)
2525 (c-end-of-statement-1)
2526 (setq count (1+ count))))
2527 ;; its possible we've been left up-buf of lim
2528 (goto-char (max (point) lim))
2529 )
2530 (c-keep-region-active))
2531
2532 (defun c-end-of-statement (&optional count lim sentence-flag)
2533 "Go to the end of the innermost C statement.
2534
2535 With prefix arg, go forward N - 1 statements. Move forward to end of
2536 the next statement if already at end. If within a string or comment,
2537 move by sentences instead of statements.
2538
2539 When called from a program, this function takes 3 optional args: the
2540 repetition count, a buffer position limit which is the farthest back
2541 to search, and a flag saying whether to do sentence motion when in a
2542 comment."
2543 (interactive (list (prefix-numeric-value current-prefix-arg)
2544 nil t))
2545 (c-beginning-of-statement (- (or count 1)) lim sentence-flag)
2546 (c-keep-region-active))
2547
2548 (defun c-beginning-of-statement-1 (&optional lim)
2549 ;; move to the start of the current statement, or the previous
2550 ;; statement if already at the beginning of one.
2551 (let ((firstp t)
2552 (substmt-p t)
2553 donep c-in-literal-cache
2554 ;; KLUDGE ALERT: maybe-labelp is used to pass information
2555 ;; between c-crosses-statement-barrier-p and
2556 ;; c-beginning-of-statement-1. A better way should be
2557 ;; implemented.
2558 maybe-labelp
2559 (last-begin (point)))
2560 (while (not donep)
2561 ;; stop at beginning of buffer
2562 (if (bobp) (setq donep t)
2563 ;; go backwards one balanced expression, but be careful of
2564 ;; unbalanced paren being reached
2565 (if (not (c-safe (progn (backward-sexp 1) t)))
2566 (progn
2567 (if firstp
2568 (backward-up-list 1)
2569 (goto-char last-begin))
2570 ;; skip over any unary operators, or other special
2571 ;; characters appearing at front of identifier
2572 (save-excursion
2573 (c-backward-syntactic-ws lim)
2574 (skip-chars-backward "-+!*&:.~ \t\n")
2575 (if (= (preceding-char) ?\()
2576 (setq last-begin (point))))
2577 (goto-char last-begin)
2578 (setq last-begin (point)
2579 donep t)))
2580
2581 (setq maybe-labelp nil)
2582 ;; see if we're in a literal. if not, then this bufpos may be
2583 ;; a candidate for stopping
2584 (cond
2585 ;; CASE 0: did we hit the error condition above?
2586 (donep)
2587 ;; CASE 1: are we in a literal?
2588 ((eq (c-in-literal lim) 'pound)
2589 (beginning-of-line))
2590 ;; CASE 2: some other kind of literal?
2591 ((c-in-literal lim))
2592 ;; CASE 3: are we looking at a conditional keyword?
2593 ((or (looking-at c-conditional-key)
2594 (and (= (following-char) ?\()
2595 (save-excursion
2596 (forward-sexp 1)
2597 (c-forward-syntactic-ws)
2598 (/= (following-char) ?\;))
2599 (let ((here (point))
2600 (foundp (progn
2601 (c-backward-syntactic-ws lim)
2602 (forward-word -1)
2603 (and lim
2604 (<= lim (point))
2605 (not (c-in-literal lim))
2606 (looking-at c-conditional-key)
2607 ))))
2608 ;; did we find a conditional?
2609 (if (not foundp)
2610 (goto-char here))
2611 foundp)))
2612 ;; are we in the middle of an else-if clause?
2613 (if (save-excursion
2614 (and (not substmt-p)
2615 (c-safe (progn (forward-sexp -1) t))
2616 (looking-at "\\<else\\>[ \t\n]+\\<if\\>")
2617 (not (c-in-literal lim))))
2618 (progn
2619 (forward-sexp -1)
2620 (c-backward-to-start-of-if lim)))
2621 ;; are we sitting at an else clause, that we are not a
2622 ;; substatement of?
2623 (if (and (not substmt-p)
2624 (looking-at "\\<else\\>[^_]"))
2625 (c-backward-to-start-of-if lim))
2626 ;; are we sitting at the while of a do-while?
2627 (if (and (looking-at "\\<while\\>[^_]")
2628 (c-backward-to-start-of-do lim))
2629 (setq substmt-p nil))
2630 (setq last-begin (point)
2631 donep substmt-p))
2632 ;; CASE 4: are we looking at a label?
2633 ((looking-at c-label-key))
2634 ;; CASE 5: is this the first time we're checking?
2635 (firstp (setq firstp nil
2636 substmt-p (not (c-crosses-statement-barrier-p
2637 (point) last-begin))
2638 last-begin (point)))
2639 ;; CASE 6: have we crossed a statement barrier?
2640 ((c-crosses-statement-barrier-p (point) last-begin)
2641 (setq donep t))
2642 ;; CASE 7: ignore labels
2643 ((and maybe-labelp
2644 (or (and c-access-key (looking-at c-access-key))
2645 ;; with switch labels, we have to go back further
2646 ;; to try to pick up the case or default
2647 ;; keyword. Potential bogosity alert: we assume
2648 ;; `case' or `default' is first thing on line
2649 (let ((here (point)))
2650 (beginning-of-line)
2651 (c-forward-syntactic-ws)
2652 (if (looking-at c-switch-label-key)
2653 t
2654 (goto-char here)
2655 nil))
2656 (looking-at c-label-key))))
2657 ;; CASE 8: ObjC or Java method def
2658 ((and c-method-key
2659 (setq last-begin (c-in-method-def-p)))
2660 (setq donep t))
2661 ;; CASE 9: nothing special
2662 (t (setq last-begin (point)))
2663 )))
2664 (goto-char last-begin)
2665 ;; we always do want to skip over non-whitespace modifier
2666 ;; characters that didn't get skipped above
2667 (skip-chars-backward "-+!*&:.~" (c-point 'boi))))
2668
2669 (defun c-end-of-statement-1 ()
2670 (condition-case ()
2671 (progn
2672 (while (and (not (eobp))
2673 (let ((beg (point)))
2674 (forward-sexp 1)
2675 (let ((end (point)))
2676 (save-excursion
2677 (goto-char beg)
2678 (not (re-search-forward "[;{}]" end t)))))))
2679 (re-search-backward "[;}]")
2680 (forward-char 1))
2681 (error
2682 (let ((beg (point)))
2683 (backward-up-list -1)
2684 (let ((end (point)))
2685 (goto-char beg)
2686 (search-forward ";" end 'move))))))
2687
2688 (defun c-crosses-statement-barrier-p (from to)
2689 ;; Does buffer positions FROM to TO cross a C statement boundary?
2690 (let ((here (point))
2691 (lim from)
2692 crossedp)
2693 (condition-case ()
2694 (progn
2695 (goto-char from)
2696 (while (and (not crossedp)
2697 (< (point) to))
2698 (skip-chars-forward "^;{}:" to)
2699 (if (not (c-in-literal lim))
2700 (progn
2701 (if (memq (following-char) '(?\; ?{ ?}))
2702 (setq crossedp t)
2703 (if (= (following-char) ?:)
2704 (setq maybe-labelp t))
2705 (forward-char 1))
2706 (setq lim (point)))
2707 (forward-char 1))))
2708 (error (setq crossedp nil)))
2709 (goto-char here)
2710 crossedp))
2711
2712
2713 (defun c-up-conditional (count)
2714 "Move back to the containing preprocessor conditional, leaving mark behind.
2715 A prefix argument acts as a repeat count. With a negative argument,
2716 move forward to the end of the containing preprocessor conditional.
2717 When going backwards, `#elif' is treated like `#else' followed by
2718 `#if'. When going forwards, `#elif' is ignored."
2719 (interactive "p")
2720 (c-forward-conditional (- count) t)
2721 (c-keep-region-active))
2722
2723 (defun c-backward-conditional (count &optional up-flag)
2724 "Move back across a preprocessor conditional, leaving mark behind.
2725 A prefix argument acts as a repeat count. With a negative argument,
2726 move forward across a preprocessor conditional."
2727 (interactive "p")
2728 (c-forward-conditional (- count) up-flag)
2729 (c-keep-region-active))
2730
2731 (defun c-forward-conditional (count &optional up-flag)
2732 "Move forward across a preprocessor conditional, leaving mark behind.
2733 A prefix argument acts as a repeat count. With a negative argument,
2734 move backward across a preprocessor conditional."
2735 (interactive "p")
2736 (let* ((forward (> count 0))
2737 (increment (if forward -1 1))
2738 (search-function (if forward 're-search-forward 're-search-backward))
2739 (new))
2740 (save-excursion
2741 (while (/= count 0)
2742 (let ((depth (if up-flag 0 -1)) found)
2743 (save-excursion
2744 ;; Find the "next" significant line in the proper direction.
2745 (while (and (not found)
2746 ;; Rather than searching for a # sign that
2747 ;; comes at the beginning of a line aside from
2748 ;; whitespace, search first for a string
2749 ;; starting with # sign. Then verify what
2750 ;; precedes it. This is faster on account of
2751 ;; the fastmap feature of the regexp matcher.
2752 (funcall search-function
2753 "#[ \t]*\\(if\\|elif\\|endif\\)"
2754 nil t))
2755 (beginning-of-line)
2756 ;; Now verify it is really a preproc line.
2757 (if (looking-at "^[ \t]*#[ \t]*\\(if\\|elif\\|endif\\)")
2758 (let ((prev depth))
2759 ;; Update depth according to what we found.
2760 (beginning-of-line)
2761 (cond ((looking-at "[ \t]*#[ \t]*endif")
2762 (setq depth (+ depth increment)))
2763 ((looking-at "[ \t]*#[ \t]*elif")
2764 (if (and forward (= depth 0))
2765 (setq found (point))))
2766 (t (setq depth (- depth increment))))
2767 ;; If we are trying to move across, and we find an
2768 ;; end before we find a beginning, get an error.
2769 (if (and (< prev 0) (< depth prev))
2770 (error (if forward
2771 "No following conditional at this level"
2772 "No previous conditional at this level")))
2773 ;; When searching forward, start from next line so
2774 ;; that we don't find the same line again.
2775 (if forward (forward-line 1))
2776 ;; If this line exits a level of conditional, exit
2777 ;; inner loop.
2778 (if (< depth 0)
2779 (setq found (point))))
2780 ;; else
2781 (if forward (forward-line 1))
2782 )))
2783 (or found
2784 (error "No containing preprocessor conditional"))
2785 (goto-char (setq new found)))
2786 (setq count (+ count increment))))
2787 (push-mark)
2788 (goto-char new))
2789 (c-keep-region-active))
2790
2791
2792 ;; commands to indent lines, regions, defuns, and expressions
2793 (defun c-indent-command (&optional whole-exp)
2794 "Indent current line as C++ code, or in some cases insert a tab character.
2795
2796 If `c-tab-always-indent' is t, always just indent the current line.
2797 If nil, indent the current line only if point is at the left margin or
2798 in the line's indentation; otherwise insert a tab. If other than nil
2799 or t, then tab is inserted only within literals (comments and strings)
2800 and inside preprocessor directives, but line is always reindented.
2801
2802 A numeric argument, regardless of its value, means indent rigidly all
2803 the lines of the expression starting after point so that this line
2804 becomes properly indented. The relative indentation among the lines
2805 of the expression are preserved."
2806 (interactive "P")
2807 (let ((bod (c-point 'bod)))
2808 (if whole-exp
2809 ;; If arg, always indent this line as C
2810 ;; and shift remaining lines of expression the same amount.
2811 (let ((shift-amt (c-indent-line))
2812 beg end)
2813 (save-excursion
2814 (if (eq c-tab-always-indent t)
2815 (beginning-of-line))
2816 (setq beg (point))
2817 (forward-sexp 1)
2818 (setq end (point))
2819 (goto-char beg)
2820 (forward-line 1)
2821 (setq beg (point)))
2822 (if (> end beg)
2823 (indent-code-rigidly beg end (- shift-amt) "#")))
2824 ;; No arg supplied, use c-tab-always-indent to determine
2825 ;; behavior
2826 (cond
2827 ;; CASE 1: indent when at column zero or in lines indentation,
2828 ;; otherwise insert a tab
2829 ((not c-tab-always-indent)
2830 (if (save-excursion
2831 (skip-chars-backward " \t")
2832 (not (bolp)))
2833 (insert-tab)
2834 (c-indent-line)))
2835 ;; CASE 2: just indent the line
2836 ((eq c-tab-always-indent t)
2837 (c-indent-line))
2838 ;; CASE 3: if in a literal, insert a tab, but always indent the
2839 ;; line
2840 (t
2841 (if (c-in-literal bod)
2842 (insert-tab))
2843 (c-indent-line)
2844 )))))
2845
2846 (defun c-indent-exp (&optional shutup-p)
2847 "Indent each line in balanced expression following point.
2848 Optional SHUTUP-P if non-nil, inhibits message printing and error checking."
2849 (interactive "P")
2850 (let ((here (point))
2851 end progress-p)
2852 (unwind-protect
2853 (let ((c-echo-syntactic-information-p nil) ;keep quiet for speed
2854 (start (progn
2855 ;; try to be smarter about finding the range of
2856 ;; lines to indent. skip all following
2857 ;; whitespace. failing that, try to find any
2858 ;; opening brace on the current line
2859 (skip-chars-forward " \t\n")
2860 (if (memq (following-char) '(?\( ?\[ ?\{))
2861 (point)
2862 (let ((state (parse-partial-sexp (point)
2863 (c-point 'eol))))
2864 (and (nth 1 state)
2865 (goto-char (nth 1 state))
2866 (memq (following-char) '(?\( ?\[ ?\{))
2867 (point)))))))
2868 ;; find balanced expression end
2869 (setq end (and (c-safe (progn (forward-sexp 1) t))
2870 (point-marker)))
2871 ;; sanity check
2872 (and (not start)
2873 (not shutup-p)
2874 (error "Cannot find start of balanced expression to indent."))
2875 (and (not end)
2876 (not shutup-p)
2877 (error "Cannot find end of balanced expression to indent."))
2878 (c-progress-init start end 'c-indent-exp)
2879 (setq progress-p t)
2880 (goto-char start)
2881 (beginning-of-line)
2882 (while (< (point) end)
2883 (if (not (looking-at "[ \t]*$"))
2884 (c-indent-line))
2885 (c-progress-update)
2886 (forward-line 1)))
2887 ;; make sure marker is deleted
2888 (and end
2889 (set-marker end nil))
2890 (and progress-p
2891 (c-progress-fini 'c-indent-exp))
2892 (goto-char here))))
2893
2894 (defun c-indent-defun ()
2895 "Re-indents the current top-level function def, struct or class declaration."
2896 (interactive)
2897 (let ((here (point-marker))
2898 (c-echo-syntactic-information-p nil)
2899 (brace (c-least-enclosing-brace (c-parse-state))))
2900 (if brace
2901 (goto-char brace)
2902 (beginning-of-defun))
2903 ;; if we're sitting at b-o-b, it might be because there was no
2904 ;; least enclosing brace and we were sitting on the defun's open
2905 ;; brace.
2906 (if (and (bobp) (not (= (following-char) ?\{)))
2907 (goto-char here))
2908 ;; if defun-prompt-regexp is non-nil, b-o-d might not leave us at
2909 ;; the open brace. I consider this an Emacs bug.
2910 (and (boundp 'defun-prompt-regexp)
2911 defun-prompt-regexp
2912 (looking-at defun-prompt-regexp)
2913 (goto-char (match-end 0)))
2914 ;; catch all errors in c-indent-exp so we can 1. give more
2915 ;; meaningful error message, and 2. restore point
2916 (unwind-protect
2917 (c-indent-exp)
2918 (goto-char here)
2919 (set-marker here nil))))
2920
2921 (defun c-indent-region (start end)
2922 ;; Indent every line whose first char is between START and END inclusive.
2923 (save-excursion
2924 (goto-char start)
2925 ;; Advance to first nonblank line.
2926 (skip-chars-forward " \t\n")
2927 (beginning-of-line)
2928 (let (endmark)
2929 (unwind-protect
2930 (let ((c-tab-always-indent t)
2931 ;; shut up any echo msgs on indiv lines
2932 (c-echo-syntactic-information-p nil))
2933 (c-progress-init start end 'c-indent-region)
2934 (setq endmark (copy-marker end))
2935 (while (and (bolp)
2936 (not (eobp))
2937 (< (point) endmark))
2938 ;; update progress
2939 (c-progress-update)
2940 ;; Indent one line as with TAB.
2941 (let (nextline sexpend sexpbeg)
2942 ;; skip blank lines
2943 (skip-chars-forward " \t\n")
2944 (beginning-of-line)
2945 ;; indent the current line
2946 (c-indent-line)
2947 (if (save-excursion
2948 (beginning-of-line)
2949 (looking-at "[ \t]*#"))
2950 (forward-line 1)
2951 (save-excursion
2952 ;; Find beginning of following line.
2953 (setq nextline (c-point 'bonl))
2954 ;; Find first beginning-of-sexp for sexp extending past
2955 ;; this line.
2956 (beginning-of-line)
2957 (while (< (point) nextline)
2958 (condition-case nil
2959 (progn
2960 (forward-sexp 1)
2961 (setq sexpend (point)))
2962 (error (setq sexpend nil)
2963 (goto-char nextline)))
2964 (c-forward-syntactic-ws))
2965 (if sexpend
2966 (progn
2967 ;; make sure the sexp we found really starts on the
2968 ;; current line and extends past it
2969 (goto-char sexpend)
2970 (setq sexpend (point-marker))
2971 (c-safe (backward-sexp 1))
2972 (setq sexpbeg (point)))))
2973 ;; check to see if the next line starts a
2974 ;; comment-only line
2975 (save-excursion
2976 (forward-line 1)
2977 (skip-chars-forward " \t")
2978 (if (looking-at c-comment-start-regexp)
2979 (setq sexpbeg (c-point 'bol))))
2980 ;; If that sexp ends within the region, indent it all at
2981 ;; once, fast.
2982 (condition-case nil
2983 (if (and sexpend
2984 (> sexpend nextline)
2985 (<= sexpend endmark))
2986 (progn
2987 (goto-char sexpbeg)
2988 (c-indent-exp 'shutup)
2989 (c-progress-update)
2990 (goto-char sexpend)))
2991 (error
2992 (goto-char sexpbeg)
2993 (c-indent-line)))
2994 ;; Move to following line and try again.
2995 (and sexpend
2996 (markerp sexpend)
2997 (set-marker sexpend nil))
2998 (forward-line 1)))))
2999 (set-marker endmark nil)
3000 (c-progress-fini 'c-indent-region)
3001 ))))
3002
3003 (defun c-mark-function ()
3004 "Put mark at end of a C, C++, or Objective-C defun, point at beginning."
3005 (interactive)
3006 (let ((here (point))
3007 ;; there should be a c-point position for 'eod
3008 (eod (save-excursion (end-of-defun) (point)))
3009 (state (c-parse-state))
3010 brace)
3011 (while state
3012 (setq brace (car state))
3013 (if (consp brace)
3014 (goto-char (cdr brace))
3015 (goto-char brace))
3016 (setq state (cdr state)))
3017 (if (= (following-char) ?{)
3018 (progn
3019 (forward-line -1)
3020 (while (not (or (bobp)
3021 (looking-at "[ \t]*$")))
3022 (forward-line -1)))
3023 (forward-line 1)
3024 (skip-chars-forward " \t\n"))
3025 (push-mark here)
3026 (push-mark eod nil t)))
3027
3028
3029 ;; for progress reporting
3030 (defvar c-progress-info nil)
3031
3032 (defun c-progress-init (start end context)
3033 ;; start the progress update messages. if this emacs doesn't have a
3034 ;; built-in timer, just be dumb about it
3035 (if (not (fboundp 'current-time))
3036 (message "indenting region... (this may take a while)")
3037 ;; if progress has already been initialized, do nothing. otherwise
3038 ;; initialize the counter with a vector of:
3039 ;; [start end lastsec context]
3040 (if c-progress-info
3041 ()
3042 (setq c-progress-info (vector start
3043 (save-excursion
3044 (goto-char end)
3045 (point-marker))
3046 (nth 1 (current-time))
3047 context))
3048 (message "indenting region..."))))
3049
3050 (defun c-progress-update ()
3051 ;; update progress
3052 (if (not (and c-progress-info c-progress-interval))
3053 nil
3054 (let ((now (nth 1 (current-time)))
3055 (start (aref c-progress-info 0))
3056 (end (aref c-progress-info 1))
3057 (lastsecs (aref c-progress-info 2)))
3058 ;; should we update? currently, update happens every 2 seconds,
3059 ;; what's the right value?
3060 (if (< c-progress-interval (- now lastsecs))
3061 (progn
3062 (message "indenting region... (%d%% complete)"
3063 (/ (* 100 (- (point) start)) (- end start)))
3064 (aset c-progress-info 2 now)))
3065 )))
3066
3067 (defun c-progress-fini (context)
3068 ;; finished
3069 (if (or (eq context (aref c-progress-info 3))
3070 (eq context t))
3071 (progn
3072 (set-marker (aref c-progress-info 1) nil)
3073 (setq c-progress-info nil)
3074 (message "indenting region...done"))))
3075
3076
3077 ;; Skipping of "syntactic whitespace" for Emacs 19. Syntactic
3078 ;; whitespace is defined as lexical whitespace, C and C++ style
3079 ;; comments, and preprocessor directives. Search no farther back or
3080 ;; forward than optional LIM. If LIM is omitted, `beginning-of-defun'
3081 ;; is used for backward skipping, point-max is used for forward
3082 ;; skipping. Note that Emacs 18 support has been moved to cc-mode-18.el.
3083
3084 (defun c-forward-syntactic-ws (&optional lim)
3085 ;; Forward skip of syntactic whitespace for Emacs 19.
3086 (save-restriction
3087 (let* ((lim (or lim (point-max)))
3088 (here lim)
3089 (hugenum (point-max)))
3090 (narrow-to-region lim (point))
3091 (while (/= here (point))
3092 (setq here (point))
3093 (forward-comment hugenum)
3094 ;; skip preprocessor directives
3095 (if (and (= (following-char) ?#)
3096 (= (c-point 'boi) (point)))
3097 (end-of-line)
3098 )))))
3099
3100 (defun c-backward-syntactic-ws (&optional lim)
3101 ;; Backward skip over syntactic whitespace for Emacs 19.
3102 (save-restriction
3103 (let* ((lim (or lim (c-point 'bod)))
3104 (here lim)
3105 (hugenum (- (point-max))))
3106 (if (< lim (point))
3107 (progn
3108 (narrow-to-region lim (point))
3109 (while (/= here (point))
3110 (setq here (point))
3111 (forward-comment hugenum)
3112 (if (eq (c-in-literal lim) 'pound)
3113 (beginning-of-line))
3114 )))
3115 )))
3116
3117
3118 ;; Return `c' if in a C-style comment, `c++' if in a C++ style
3119 ;; comment, `string' if in a string literal, `pound' if on a
3120 ;; preprocessor line, or nil if not in a comment at all. Optional LIM
3121 ;; is used as the backward limit of the search. If omitted, or nil,
3122 ;; `beginning-of-defun' is used."
3123
3124 ;; This is for all v19 Emacsen supporting either 1-bit or 8-bit syntax
3125 (defun c-in-literal (&optional lim)
3126 ;; Determine if point is in a C++ literal. we cache the last point
3127 ;; calculated if the cache is enabled
3128 (if (and (boundp 'c-in-literal-cache)
3129 c-in-literal-cache
3130 (= (point) (aref c-in-literal-cache 0)))
3131 (aref c-in-literal-cache 1)
3132 (let ((rtn (save-excursion
3133 (let* ((lim (or lim (c-point 'bod)))
3134 (here (point))
3135 (state (parse-partial-sexp lim (point))))
3136 (cond
3137 ((nth 3 state) 'string)
3138 ((nth 4 state) (if (nth 7 state) 'c++ 'c))
3139 ((progn
3140 (goto-char here)
3141 (beginning-of-line)
3142 (looking-at "[ \t]*#"))
3143 'pound)
3144 (t nil))))))
3145 ;; cache this result if the cache is enabled
3146 (and (boundp 'c-in-literal-cache)
3147 (setq c-in-literal-cache (vector (point) rtn)))
3148 rtn)))
3149
3150
3151 ;; utilities for moving and querying around syntactic elements
3152 (defun c-parse-state ()
3153 ;; Finds and records all open parens between some important point
3154 ;; earlier in the file and point.
3155 ;;
3156 ;; if there's a state cache, return it
3157 (if (boundp 'c-state-cache) c-state-cache
3158 (let* (at-bob
3159 (pos (save-excursion
3160 ;; go back 2 bods, but ignore any bogus positions
3161 ;; returned by beginning-of-defun (i.e. open paren
3162 ;; in column zero)
3163 (let ((cnt 2))
3164 (while (not (or at-bob (zerop cnt)))
3165 (beginning-of-defun)
3166 (if (= (following-char) ?\{)
3167 (setq cnt (1- cnt)))
3168 (if (bobp)
3169 (setq at-bob t))))
3170 (point)))
3171 (here (save-excursion
3172 ;;(skip-chars-forward " \t}")
3173 (point)))
3174 (last-bod pos) (last-pos pos)
3175 placeholder state sexp-end)
3176 ;; cache last bod position
3177 (while (catch 'backup-bod
3178 (setq state nil)
3179 (while (and pos (< pos here))
3180 (setq last-pos pos)
3181 (if (and (setq pos (c-safe (scan-lists pos 1 -1)))
3182 (<= pos here))
3183 (progn
3184 (setq sexp-end (c-safe (scan-sexps (1- pos) 1)))
3185 (if (and sexp-end
3186 (<= sexp-end here))
3187 ;; we want to record both the start and end
3188 ;; of this sexp, but we only want to record
3189 ;; the last-most of any of them before here
3190 (progn
3191 (if (= (char-after (1- pos)) ?\{)
3192 (setq state (cons (cons (1- pos) sexp-end)
3193 (if (consp (car state))
3194 (cdr state)
3195 state))))
3196 (setq pos sexp-end))
3197 ;; we're contained in this sexp so put pos on
3198 ;; front of list
3199 (setq state (cons (1- pos) state))))
3200 ;; something bad happened. check to see if we
3201 ;; crossed an unbalanced close brace. if so, we
3202 ;; didn't really find the right `important bufpos'
3203 ;; so lets back up and try again
3204 (if (and (not pos) (not at-bob)
3205 (setq placeholder
3206 (c-safe (scan-lists last-pos 1 1)))
3207 ;;(char-after (1- placeholder))
3208 (<= placeholder here)
3209 (= (char-after (1- placeholder)) ?\}))
3210 (while t
3211 (setq last-bod (c-safe (scan-lists last-bod -1 1)))
3212 (if (not last-bod)
3213 (error "unbalanced close brace at position %d"
3214 (1- placeholder))
3215 (setq at-bob (= last-bod (point-min))
3216 pos last-bod)
3217 (if (= (char-after last-bod) ?\{)
3218 (throw 'backup-bod t)))
3219 )) ;end-if
3220 )) ;end-while
3221 nil))
3222 state)))
3223
3224 (defun c-whack-state (bufpos state)
3225 ;; whack off any state information that appears on STATE which lies
3226 ;; after the bounds of BUFPOS.
3227 (let (newstate car)
3228 (while state
3229 (setq car (car state)
3230 state (cdr state))
3231 (if (consp car)
3232 ;; just check the car, because in a balanced brace
3233 ;; expression, it must be impossible for the corresponding
3234 ;; close brace to be before point, but the open brace to be
3235 ;; after.
3236 (if (<= bufpos (car car))
3237 nil ; whack it off
3238 ;; its possible that the open brace is before bufpos, but
3239 ;; the close brace is after. In that case, convert this
3240 ;; to a non-cons element.
3241 (if (<= bufpos (cdr car))
3242 (setq newstate (append newstate (list (car car))))
3243 ;; we know that both the open and close braces are
3244 ;; before bufpos, so we also know that everything else
3245 ;; on state is before bufpos, so we can glom up the
3246 ;; whole thing and exit.
3247 (setq newstate (append newstate (list car) state)
3248 state nil)))
3249 (if (<= bufpos car)
3250 nil ; whack it off
3251 ;; it's before bufpos, so everything else should too
3252 (setq newstate (append newstate (list car) state)
3253 state nil))))
3254 newstate))
3255
3256 (defun c-hack-state (bufpos which state)
3257 ;; Using BUFPOS buffer position, and WHICH (must be 'open or
3258 ;; 'close), hack the c-parse-state STATE and return the results.
3259 (if (eq which 'open)
3260 (let ((car (car state)))
3261 (if (or (null car)
3262 (consp car)
3263 (/= bufpos car))
3264 (cons bufpos state)
3265 state))
3266 (if (not (eq which 'close))
3267 (error "c-hack-state, bad argument: %s" which))
3268 ;; 'close brace
3269 (let ((car (car state))
3270 (cdr (cdr state)))
3271 (if (consp car)
3272 (setq car (car cdr)
3273 cdr (cdr cdr)))
3274 ;; TBD: is this test relevant???
3275 (if (consp car)
3276 state ;on error, don't change
3277 ;; watch out for balanced expr already on cdr of list
3278 (cons (cons car bufpos)
3279 (if (consp (car cdr))
3280 (cdr cdr) cdr))
3281 ))))
3282
3283 (defun c-adjust-state (from to shift state)
3284 ;; Adjust all points in state that lie in the region FROM..TO by
3285 ;; SHIFT amount (as would be returned by c-indent-line).
3286 (mapcar
3287 (function
3288 (lambda (e)
3289 (if (consp e)
3290 (let ((car (car e))
3291 (cdr (cdr e)))
3292 (if (and (<= from car) (< car to))
3293 (setcar e (+ shift car)))
3294 (if (and (<= from cdr) (< cdr to))
3295 (setcdr e (+ shift cdr))))
3296 (if (and (<= from e) (< e to))
3297 (setq e (+ shift e))))
3298 e))
3299 state))
3300
3301
3302 (defun c-beginning-of-inheritance-list (&optional lim)
3303 ;; Go to the first non-whitespace after the colon that starts a
3304 ;; multiple inheritance introduction. Optional LIM is the farthest
3305 ;; back we should search.
3306 (let ((lim (or lim (c-point 'bod)))
3307 (placeholder (progn
3308 (back-to-indentation)
3309 (point))))
3310 (c-backward-syntactic-ws lim)
3311 (while (and (> (point) lim)
3312 (memq (preceding-char) '(?, ?:))
3313 (progn
3314 (beginning-of-line)
3315 (setq placeholder (point))
3316 (skip-chars-forward " \t")
3317 (not (looking-at c-class-key))
3318 ))
3319 (c-backward-syntactic-ws lim))
3320 (goto-char placeholder)
3321 (skip-chars-forward "^:" (c-point 'eol))))
3322
3323 (defun c-beginning-of-macro (&optional lim)
3324 ;; Go to the beginning of the macro. Right now we don't support
3325 ;; multi-line macros too well
3326 (back-to-indentation))
3327
3328 (defun c-in-method-def-p ()
3329 ;; Return nil if we aren't in a method definition, otherwise the
3330 ;; position of the initial [+-].
3331 (save-excursion
3332 (beginning-of-line)
3333 (and c-method-key
3334 (looking-at c-method-key)
3335 (point))
3336 ))
3337
3338 (defun c-just-after-func-arglist-p (&optional containing)
3339 ;; Return t if we are between a function's argument list closing
3340 ;; paren and its opening brace. Note that the list close brace
3341 ;; could be followed by a "const" specifier or a member init hanging
3342 ;; colon. Optional CONTAINING is position of containing s-exp open
3343 ;; brace. If not supplied, point is used as search start.
3344 (save-excursion
3345 (c-backward-syntactic-ws)
3346 (let ((checkpoint (or containing (point))))
3347 (goto-char checkpoint)
3348 ;; could be looking at const specifier
3349 (if (and (= (preceding-char) ?t)
3350 (forward-word -1)
3351 (looking-at "\\<const\\>"))
3352 (c-backward-syntactic-ws)
3353 ;; otherwise, we could be looking at a hanging member init
3354 ;; colon
3355 (goto-char checkpoint)
3356 (if (and (= (preceding-char) ?:)
3357 (progn
3358 (forward-char -1)
3359 (c-backward-syntactic-ws)
3360 (looking-at "[ \t\n]*:\\([^:]+\\|$\\)")))
3361 nil
3362 (goto-char checkpoint))
3363 )
3364 (and (= (preceding-char) ?\))
3365 ;; check if we are looking at a method def
3366 (or (not c-method-key)
3367 (progn
3368 (forward-sexp -1)
3369 (forward-char -1)
3370 (c-backward-syntactic-ws)
3371 (not (or (= (preceding-char) ?-)
3372 (= (preceding-char) ?+)
3373 ;; or a class category
3374 (progn
3375 (forward-sexp -2)
3376 (looking-at c-class-key))
3377 )))))
3378 )))
3379
3380 ;; defuns to look backwards for things
3381 (defun c-backward-to-start-of-do (&optional lim)
3382 ;; Move to the start of the last "unbalanced" do expression.
3383 ;; Optional LIM is the farthest back to search. If none is found,
3384 ;; nil is returned and point is left unchanged, otherwise t is returned.
3385 (let ((do-level 1)
3386 (case-fold-search nil)
3387 (lim (or lim (c-point 'bod)))
3388 (here (point))
3389 foundp)
3390 (while (not (zerop do-level))
3391 ;; we protect this call because trying to execute this when the
3392 ;; while is not associated with a do will throw an error
3393 (condition-case nil
3394 (progn
3395 (backward-sexp 1)
3396 (cond
3397 ((memq (c-in-literal lim) '(c c++)))
3398 ((looking-at "while\\b[^_]")
3399 (setq do-level (1+ do-level)))
3400 ((looking-at "do\\b[^_]")
3401 (if (zerop (setq do-level (1- do-level)))
3402 (setq foundp t)))
3403 ((<= (point) lim)
3404 (setq do-level 0)
3405 (goto-char lim))))
3406 (error
3407 (goto-char lim)
3408 (setq do-level 0))))
3409 (if (not foundp)
3410 (goto-char here))
3411 foundp))
3412
3413 (defun c-backward-to-start-of-if (&optional lim)
3414 ;; Move to the start of the last "unbalanced" if and return t. If
3415 ;; none is found, and we are looking at an if clause, nil is
3416 ;; returned. If none is found and we are looking at an else clause,
3417 ;; an error is thrown.
3418 (let ((if-level 1)
3419 (here (c-point 'bol))
3420 (case-fold-search nil)
3421 (lim (or lim (c-point 'bod)))
3422 (at-if (looking-at "if\\b[^_]")))
3423 (catch 'orphan-if
3424 (while (and (not (bobp))
3425 (not (zerop if-level)))
3426 (c-backward-syntactic-ws)
3427 (condition-case nil
3428 (backward-sexp 1)
3429 (error
3430 (if at-if
3431 (throw 'orphan-if nil)
3432 (error "No matching `if' found for `else' on line %d."
3433 (1+ (count-lines 1 here))))))
3434 (cond
3435 ((looking-at "else\\b[^_]")
3436 (setq if-level (1+ if-level)))
3437 ((looking-at "if\\b[^_]")
3438 ;; check for else if... skip over
3439 (let ((here (point)))
3440 (c-safe (forward-sexp -1))
3441 (if (looking-at "\\<else\\>[ \t]+\\<if\\>")
3442 nil
3443 (setq if-level (1- if-level))
3444 (goto-char here))))
3445 ((< (point) lim)
3446 (setq if-level 0)
3447 (goto-char lim))
3448 ))
3449 t)))
3450
3451 (defun c-skip-conditional ()
3452 ;; skip forward over conditional at point, including any predicate
3453 ;; statements in parentheses. No error checking is performed.
3454 (forward-sexp
3455 ;; else if()
3456 (if (looking-at "\\<else\\>[ \t]+\\<if\\>")
3457 3
3458 ;; do and else aren't followed by parens
3459 (if (looking-at "\\<\\(do\\|else\\)\\>")
3460 1 2))))
3461
3462 (defun c-skip-case-statement-forward (state &optional lim)
3463 ;; skip forward over case/default bodies, with optional maximal
3464 ;; limit. if no next case body is found, nil is returned and point
3465 ;; is not moved
3466 (let ((lim (or lim (point-max)))
3467 (here (point))
3468 donep foundp bufpos
3469 (safepos (point))
3470 (balanced (car state)))
3471 ;; search until we've passed the limit, or we've found our match
3472 (while (and (< (point) lim)
3473 (not donep))
3474 (setq safepos (point))
3475 ;; see if we can find a case statement, not in a literal
3476 (if (and (re-search-forward c-switch-label-key lim 'move)
3477 (setq bufpos (match-beginning 0))
3478 (not (c-in-literal safepos))
3479 (/= bufpos here))
3480 ;; if we crossed into a balanced sexp, we know the case is
3481 ;; not part of our switch statement, so just bound over the
3482 ;; sexp and keep looking.
3483 (if (and (consp balanced)
3484 (> bufpos (car balanced))
3485 (< bufpos (cdr balanced)))
3486 (goto-char (cdr balanced))
3487 (goto-char bufpos)
3488 (setq donep t
3489 foundp t))))
3490 (if (not foundp)
3491 (goto-char here))
3492 foundp))
3493
3494 (defun c-search-uplist-for-classkey (brace-state)
3495 ;; search for the containing class, returning a 2 element vector if
3496 ;; found. aref 0 contains the bufpos of the class key, and aref 1
3497 ;; contains the bufpos of the open brace.
3498 (if (null brace-state)
3499 ;; no brace-state means we cannot be inside a class
3500 nil
3501 (let ((carcache (car brace-state))
3502 search-start search-end)
3503 (if (consp carcache)
3504 ;; a cons cell in the first element means that there is some
3505 ;; balanced sexp before the current bufpos. this we can
3506 ;; ignore. the nth 1 and nth 2 elements define for us the
3507 ;; search boundaries
3508 (setq search-start (nth 2 brace-state)
3509 search-end (nth 1 brace-state))
3510 ;; if the car was not a cons cell then nth 0 and nth 1 define
3511 ;; for us the search boundaries
3512 (setq search-start (nth 1 brace-state)
3513 search-end (nth 0 brace-state)))
3514 ;; search-end cannot be a cons cell
3515 (and (consp search-end)
3516 (error "consp search-end: %s" search-end))
3517 ;; if search-end is nil, or if the search-end character isn't an
3518 ;; open brace, we are definitely not in a class
3519 (if (or (not search-end)
3520 (< search-end (point-min))
3521 (/= (char-after search-end) ?{))
3522 nil
3523 ;; now, we need to look more closely at search-start. if
3524 ;; search-start is nil, then our start boundary is really
3525 ;; point-min.
3526 (if (not search-start)
3527 (setq search-start (point-min))
3528 ;; if search-start is a cons cell, then we can start
3529 ;; searching from the end of the balanced sexp just ahead of
3530 ;; us
3531 (if (consp search-start)
3532 (setq search-start (cdr search-start))))
3533 ;; now we can do a quick regexp search from search-start to
3534 ;; search-end and see if we can find a class key. watch for
3535 ;; class like strings in literals
3536 (save-excursion
3537 (save-restriction
3538 (goto-char search-start)
3539 (let (foundp class match-end)
3540 (while (and (not foundp)
3541 (progn
3542 (c-forward-syntactic-ws)
3543 (> search-end (point)))
3544 (re-search-forward c-class-key search-end t))
3545 (setq class (match-beginning 0)
3546 match-end (match-end 0))
3547 (if (c-in-literal search-start)
3548 nil ; its in a comment or string, ignore
3549 (goto-char class)
3550 (skip-chars-forward " \t\n")
3551 (setq foundp (vector (c-point 'boi) search-end))
3552 (cond
3553 ;; check for embedded keywords
3554 ((let ((char (char-after (1- class))))
3555 (and char
3556 (memq (char-syntax char) '(?w ?_))))
3557 (goto-char match-end)
3558 (setq foundp nil))
3559 ;; make sure we're really looking at the start of a
3560 ;; class definition, and not a forward decl, return
3561 ;; arg, template arg list, or an ObjC or Java method.
3562 ((and c-method-key
3563 (re-search-forward c-method-key search-end t))
3564 (setq foundp nil))
3565 ;; Its impossible to define a regexp for this, and
3566 ;; nearly so to do it programmatically.
3567 ;;
3568 ;; ; picks up forward decls
3569 ;; = picks up init lists
3570 ;; ) picks up return types
3571 ;; > picks up templates, but remember that we can
3572 ;; inherit from templates!
3573 ((let ((skipchars "^;=)"))
3574 ;; try to see if we found the `class' keyword
3575 ;; inside a template arg list
3576 (save-excursion
3577 (skip-chars-backward "^<>" search-start)
3578 (if (= (preceding-char) ?<)
3579 (setq skipchars (concat skipchars ">"))))
3580 (skip-chars-forward skipchars search-end)
3581 (/= (point) search-end))
3582 (setq foundp nil))
3583 )))
3584 foundp))
3585 )))))
3586
3587 (defun c-inside-bracelist-p (containing-sexp brace-state)
3588 ;; return the buffer position of the beginning of the brace list
3589 ;; statement if we're inside a brace list, otherwise return nil.
3590 ;; CONTAINING-SEXP is the buffer pos of the innermost containing
3591 ;; paren. BRACE-STATE is the remainder of the state of enclosing braces
3592 ;;
3593 ;; N.B.: This algorithm can potentially get confused by cpp macros
3594 ;; places in inconvenient locations. Its a trade-off we make for
3595 ;; speed.
3596 (or
3597 ;; this will pick up enum lists
3598 (condition-case ()
3599 (save-excursion
3600 (goto-char containing-sexp)
3601 (forward-sexp -1)
3602 (if (or (looking-at "enum[\t\n ]+")
3603 (progn (forward-sexp -1)
3604 (looking-at "enum[\t\n ]+")))
3605 (point)))
3606 (error nil))
3607 ;; this will pick up array/aggregate init lists, even if they are nested.
3608 (save-excursion
3609 (let (bufpos failedp)
3610 (while (and (not bufpos)
3611 containing-sexp)
3612 (if (consp containing-sexp)
3613 (setq containing-sexp (car brace-state)
3614 brace-state (cdr brace-state))
3615 ;; see if significant character just before brace is an equal
3616 (goto-char containing-sexp)
3617 (setq failedp nil)
3618 (condition-case ()
3619 (progn
3620 (forward-sexp -1)
3621 (forward-sexp 1)
3622 (c-forward-syntactic-ws containing-sexp))
3623 (error (setq failedp t)))
3624 (if (or failedp (/= (following-char) ?=))
3625 ;; lets see if we're nested. find the most nested
3626 ;; containing brace
3627 (setq containing-sexp (car brace-state)
3628 brace-state (cdr brace-state))
3629 ;; we've hit the beginning of the aggregate list
3630 (c-beginning-of-statement-1 (c-most-enclosing-brace brace-state))
3631 (setq bufpos (point)))
3632 ))
3633 bufpos))
3634 ))
3635
3636
3637 ;; defuns for calculating the syntactic state and indenting a single
3638 ;; line of C/C++/ObjC code
3639 (defmacro c-add-syntax (symbol &optional relpos)
3640 ;; a simple macro to append the syntax in symbol to the syntax list.
3641 ;; try to increase performance by using this macro
3642 (` (setq syntax (cons (cons (, symbol) (, relpos)) syntax))))
3643
3644 (defun c-most-enclosing-brace (state)
3645 ;; return the bufpos of the most enclosing brace that hasn't been
3646 ;; narrowed out by any enclosing class, or nil if none was found
3647 (let (enclosingp)
3648 (while (and state (not enclosingp))
3649 (setq enclosingp (car state)
3650 state (cdr state))
3651 (if (consp enclosingp)
3652 (setq enclosingp nil)
3653 (if (> (point-min) enclosingp)
3654 (setq enclosingp nil))
3655 (setq state nil)))
3656 enclosingp))
3657
3658 (defun c-least-enclosing-brace (state)
3659 ;; return the bufpos of the least (highest) enclosing brace that
3660 ;; hasn't been narrowed out by any enclosing class, or nil if none
3661 ;; was found.
3662 (c-most-enclosing-brace (nreverse state)))
3663
3664 (defun c-safe-position (bufpos state)
3665 ;; return the closest known safe position higher up than point
3666 (let ((safepos nil))
3667 (while state
3668 (setq safepos
3669 (if (consp (car state))
3670 (cdr (car state))
3671 (car state)))
3672 (if (< safepos bufpos)
3673 (setq state nil)
3674 (setq state (cdr state))))
3675 safepos))
3676
3677 (defun c-narrow-out-enclosing-class (state lim)
3678 ;; narrow the buffer so that the enclosing class is hidden
3679 (let (inclass-p)
3680 (and state
3681 (setq inclass-p (c-search-uplist-for-classkey state))
3682 (narrow-to-region
3683 (progn
3684 (goto-char (1+ (aref inclass-p 1)))
3685 (skip-chars-forward " \t\n" lim)
3686 ;; if point is now left of the class opening brace, we're
3687 ;; hosed, so try a different tact
3688 (if (<= (point) (aref inclass-p 1))
3689 (progn
3690 (goto-char (1+ (aref inclass-p 1)))
3691 (c-forward-syntactic-ws lim)))
3692 (point))
3693 ;; end point is the end of the current line
3694 (progn
3695 (goto-char lim)
3696 (c-point 'eol))))
3697 ;; return the class vector
3698 inclass-p))
3699
3700 (defun c-guess-basic-syntax ()
3701 ;; guess the syntactic description of the current line of C++ code.
3702 (save-excursion
3703 (save-restriction
3704 (beginning-of-line)
3705 (let* ((indent-point (point))
3706 (case-fold-search nil)
3707 (fullstate (c-parse-state))
3708 (state fullstate)
3709 (in-method-intro-p (and c-method-key
3710 (looking-at c-method-key)))
3711 literal containing-sexp char-before-ip char-after-ip lim
3712 syntax placeholder c-in-literal-cache inswitch-p
3713 ;; narrow out any enclosing class
3714 (inclass-p (c-narrow-out-enclosing-class state indent-point))
3715 )
3716
3717 ;; get the buffer position of the most nested opening brace,
3718 ;; if there is one, and it hasn't been narrowed out
3719 (save-excursion
3720 (goto-char indent-point)
3721 (skip-chars-forward " \t}")
3722 (skip-chars-backward " \t")
3723 (while (and state
3724 (not in-method-intro-p)
3725 (not containing-sexp))
3726 (setq containing-sexp (car state)
3727 state (cdr state))
3728 (if (consp containing-sexp)
3729 ;; if cdr == point, then containing sexp is the brace
3730 ;; that opens the sexp we close
3731 (if (= (cdr containing-sexp) (point))
3732 (setq containing-sexp (car containing-sexp))
3733 ;; otherwise, ignore this element
3734 (setq containing-sexp nil))
3735 ;; ignore the bufpos if its been narrowed out by the
3736 ;; containing class
3737 (if (<= containing-sexp (point-min))
3738 (setq containing-sexp nil)))))
3739
3740 ;; set the limit on the farthest back we need to search
3741 (setq lim (or containing-sexp
3742 (if (consp (car fullstate))
3743 (cdr (car fullstate))
3744 nil)
3745 (point-min)))
3746
3747 ;; cache char before and after indent point, and move point to
3748 ;; the most likely position to perform the majority of tests
3749 (goto-char indent-point)
3750 (skip-chars-forward " \t")
3751 (setq char-after-ip (following-char))
3752 (c-backward-syntactic-ws lim)
3753 (setq char-before-ip (preceding-char))
3754 (goto-char indent-point)
3755 (skip-chars-forward " \t")
3756
3757 ;; are we in a literal?
3758 (setq literal (c-in-literal lim))
3759
3760 ;; now figure out syntactic qualities of the current line
3761 (cond
3762 ;; CASE 1: in a string.
3763 ((memq literal '(string))
3764 (c-add-syntax 'string (c-point 'bopl)))
3765 ;; CASE 2: in a C or C++ style comment.
3766 ((memq literal '(c c++))
3767 ;; we need to catch multi-paragraph C comments
3768 (while (and (zerop (forward-line -1))
3769 (looking-at "^[ \t]*$")))
3770 (c-add-syntax literal (c-point 'bol)))
3771 ;; CASE 3: in a cpp preprocessor
3772 ((eq literal 'pound)
3773 (c-beginning-of-macro lim)
3774 (c-add-syntax 'cpp-macro (c-point 'boi)))
3775 ;; CASE 4: in an objective-c method intro
3776 (in-method-intro-p
3777 (c-add-syntax 'objc-method-intro (c-point 'boi)))
3778 ;; CASE 5: Line is at top level.
3779 ((null containing-sexp)
3780 (cond
3781 ;; CASE 5A: we are looking at a defun, class, or
3782 ;; inline-inclass method opening brace
3783 ((= char-after-ip ?{)
3784 (cond
3785 ;; CASE 5A.1: we are looking at a class opening brace
3786 ((save-excursion
3787 (goto-char indent-point)
3788 (skip-chars-forward " \t{")
3789 ;; TBD: watch out! there could be a bogus
3790 ;; c-state-cache in place when we get here. we have
3791 ;; to go through much chicanery to ignore the cache.
3792 ;; But of course, there may not be! BLECH! BOGUS!
3793 (let ((decl
3794 (if (boundp 'c-state-cache)
3795 (let ((old-cache c-state-cache))
3796 (prog2
3797 (makunbound 'c-state-cache)
3798 (c-search-uplist-for-classkey (c-parse-state))
3799 (setq c-state-cache old-cache)))
3800 (c-search-uplist-for-classkey (c-parse-state))
3801 )))
3802 (and decl
3803 (setq placeholder (aref decl 0)))
3804 ))
3805 (c-add-syntax 'class-open placeholder))
3806 ;; CASE 5A.2: brace list open
3807 ((save-excursion
3808 (c-beginning-of-statement-1 lim)
3809 ;; c-b-o-s could have left us at point-min
3810 (and (bobp)
3811 (c-forward-syntactic-ws indent-point))
3812 (setq placeholder (point))
3813 (and (or (looking-at "enum[ \t\n]+")
3814 (= char-before-ip ?=))
3815 (save-excursion
3816 (skip-chars-forward "^;(" indent-point)
3817 (not (memq (following-char) '(?\; ?\()))
3818 )))
3819 (c-add-syntax 'brace-list-open placeholder))
3820 ;; CASE 5A.3: inline defun open
3821 (inclass-p
3822 (c-add-syntax 'inline-open (aref inclass-p 0)))
3823 ;; CASE 5A.4: ordinary defun open
3824 (t
3825 (goto-char placeholder)
3826 (c-add-syntax 'defun-open (c-point 'bol))
3827 )))
3828 ;; CASE 5B: first K&R arg decl or member init
3829 ((c-just-after-func-arglist-p)
3830 (cond
3831 ;; CASE 5B.1: a member init
3832 ((or (= char-before-ip ?:)
3833 (= char-after-ip ?:))
3834 ;; this line should be indented relative to the beginning
3835 ;; of indentation for the topmost-intro line that contains
3836 ;; the prototype's open paren
3837 ;; TBD: is the following redundant?
3838 (if (= char-before-ip ?:)
3839 (forward-char -1))
3840 (c-backward-syntactic-ws lim)
3841 ;; TBD: is the preceding redundant?
3842 (if (= (preceding-char) ?:)
3843 (progn (forward-char -1)
3844 (c-backward-syntactic-ws lim)))
3845 (if (= (preceding-char) ?\))
3846 (backward-sexp 1))
3847 (c-add-syntax 'member-init-intro (c-point 'boi))
3848 ;; we don't need to add any class offset since this
3849 ;; should be relative to the ctor's indentation
3850 )
3851 ;; CASE 5B.2: K&R arg decl intro
3852 (c-recognize-knr-p
3853 (c-add-syntax 'knr-argdecl-intro (c-point 'boi))
3854 (and inclass-p (c-add-syntax 'inclass (aref inclass-p 0))))
3855 ;; CASE 5B.3: Nether region after a C++ func decl, which
3856 ;; could include a `throw' declaration.
3857 (t
3858 (c-beginning-of-statement-1 lim)
3859 (c-add-syntax 'ansi-funcdecl-cont (c-point 'boi))
3860 )))
3861 ;; CASE 5C: inheritance line. could be first inheritance
3862 ;; line, or continuation of a multiple inheritance
3863 ((or (and c-baseclass-key (looking-at c-baseclass-key))
3864 (and (or (= char-before-ip ?:)
3865 (= char-after-ip ?:))
3866 (save-excursion
3867 (c-backward-syntactic-ws lim)
3868 (if (= char-before-ip ?:)
3869 (progn
3870 (forward-char -1)
3871 (c-backward-syntactic-ws lim)))
3872 (back-to-indentation)
3873 (looking-at c-class-key))))
3874 (cond
3875 ;; CASE 5C.1: non-hanging colon on an inher intro
3876 ((= char-after-ip ?:)
3877 (c-backward-syntactic-ws lim)
3878 (c-add-syntax 'inher-intro (c-point 'boi))
3879 ;; don't add inclass symbol since relative point already
3880 ;; contains any class offset
3881 )
3882 ;; CASE 5C.2: hanging colon on an inher intro
3883 ((= char-before-ip ?:)
3884 (c-add-syntax 'inher-intro (c-point 'boi))
3885 (and inclass-p (c-add-syntax 'inclass (aref inclass-p 0))))
3886 ;; CASE 5C.3: a continued inheritance line
3887 (t
3888 (c-beginning-of-inheritance-list lim)
3889 (c-add-syntax 'inher-cont (point))
3890 ;; don't add inclass symbol since relative point already
3891 ;; contains any class offset
3892 )))
3893 ;; CASE 5D: this could be a top-level compound statement or a
3894 ;; member init list continuation
3895 ((= char-before-ip ?,)
3896 (goto-char indent-point)
3897 (c-backward-syntactic-ws lim)
3898 (while (and (< lim (point))
3899 (= (preceding-char) ?,))
3900 ;; this will catch member inits with multiple
3901 ;; line arglists
3902 (forward-char -1)
3903 (c-backward-syntactic-ws (c-point 'bol))
3904 (if (= (preceding-char) ?\))
3905 (backward-sexp 1))
3906 ;; now continue checking
3907 (beginning-of-line)
3908 (c-backward-syntactic-ws lim))
3909 (cond
3910 ;; CASE 5D.1: hanging member init colon, but watch out
3911 ;; for bogus matches on access specifiers inside classes.
3912 ((and (= (preceding-char) ?:)
3913 (save-excursion
3914 (forward-word -1)
3915 (not (looking-at c-access-key))))
3916 (goto-char indent-point)
3917 (c-backward-syntactic-ws lim)
3918 (c-safe (backward-sexp 1))
3919 (c-add-syntax 'member-init-cont (c-point 'boi))
3920 ;; we do not need to add class offset since relative
3921 ;; point is the member init above us
3922 )
3923 ;; CASE 5D.2: non-hanging member init colon
3924 ((progn
3925 (c-forward-syntactic-ws indent-point)
3926 (= (following-char) ?:))
3927 (skip-chars-forward " \t:")
3928 (c-add-syntax 'member-init-cont (point)))
3929 ;; CASE 5D.3: perhaps a multiple inheritance line?
3930 ((looking-at c-inher-key)
3931 (c-add-syntax 'inher-cont (c-point 'boi)))
3932 ;; CASE 5D.4: perhaps a template list continuation?
3933 ((save-excursion
3934 (skip-chars-backward "^<" lim)
3935 ;; not sure if this is the right test, but it should
3936 ;; be fast and mostly accurate.
3937 (and (= (preceding-char) ?<)
3938 (not (c-in-literal lim))))
3939 ;; we can probably indent it just like and arglist-cont
3940 (c-add-syntax 'arglist-cont (point)))
3941 ;; CASE 5D.5: perhaps a top-level statement-cont
3942 (t
3943 (c-beginning-of-statement-1 lim)
3944 ;; skip over any access-specifiers
3945 (and inclass-p c-access-key
3946 (while (looking-at c-access-key)
3947 (forward-line 1)))
3948 ;; skip over comments, whitespace
3949 (c-forward-syntactic-ws indent-point)
3950 (c-add-syntax 'statement-cont (c-point 'boi)))
3951 ))
3952 ;; CASE 5E: we are looking at a access specifier
3953 ((and inclass-p
3954 c-access-key
3955 (looking-at c-access-key))
3956 (c-add-syntax 'access-label (c-point 'bonl))
3957 (c-add-syntax 'inclass (aref inclass-p 0)))
3958 ;; CASE 5F: we are looking at the brace which closes the
3959 ;; enclosing nested class decl
3960 ((and inclass-p
3961 (= char-after-ip ?})
3962 (save-excursion
3963 (save-restriction
3964 (widen)
3965 (forward-char 1)
3966 (and
3967 (condition-case nil
3968 (progn (backward-sexp 1) t)
3969 (error nil))
3970 (= (point) (aref inclass-p 1))
3971 ))))
3972 (save-restriction
3973 (widen)
3974 (goto-char (aref inclass-p 0))
3975 (c-add-syntax 'class-close (c-point 'boi))))
3976 ;; CASE 5G: we could be looking at subsequent knr-argdecls
3977 ((and c-recognize-knr-p
3978 (save-excursion
3979 (c-backward-syntactic-ws lim)
3980 (while (memq (preceding-char) '(?\; ?,))
3981 (beginning-of-line)
3982 (setq placeholder (point))
3983 (c-backward-syntactic-ws lim))
3984 (and (= (preceding-char) ?\))
3985 (or (not c-method-key)
3986 (progn
3987 (forward-sexp -1)
3988 (forward-char -1)
3989 (c-backward-syntactic-ws)
3990 (not (or (= (preceding-char) ?-)
3991 (= (preceding-char) ?+)
3992 ;; or a class category
3993 (progn
3994 (forward-sexp -2)
3995 (looking-at c-class-key))
3996 )))))
3997 )
3998 (save-excursion
3999 (c-beginning-of-statement-1)
4000 (not (looking-at "typedef[ \t\n]+"))))
4001 (goto-char placeholder)
4002 (c-add-syntax 'knr-argdecl (c-point 'boi)))
4003 ;; CASE 5H: we are at the topmost level, make sure we skip
4004 ;; back past any access specifiers
4005 ((progn
4006 (c-backward-syntactic-ws lim)
4007 (while (and inclass-p
4008 c-access-key
4009 (not (bobp))
4010 (save-excursion
4011 (c-safe (progn (backward-sexp 1) t))
4012 (looking-at c-access-key)))
4013 (backward-sexp 1)
4014 (c-backward-syntactic-ws lim))
4015 (or (bobp)
4016 (memq (preceding-char) '(?\; ?\}))))
4017 ;; real beginning-of-line could be narrowed out due to
4018 ;; enclosure in a class block
4019 (save-restriction
4020 (widen)
4021 (c-add-syntax 'topmost-intro (c-point 'bol))
4022 (if inclass-p
4023 (progn
4024 (goto-char (aref inclass-p 1))
4025 (c-add-syntax 'inclass (c-point 'boi))))))
4026 ;; CASE 5I: we are at an ObjC or Java method definition
4027 ;; continuation line.
4028 ((and c-method-key
4029 (progn
4030 (c-beginning-of-statement-1 lim)
4031 (beginning-of-line)
4032 (looking-at c-method-key)))
4033 (c-add-syntax 'objc-method-args-cont (point)))
4034 ;; CASE 5J: we are at a topmost continuation line
4035 (t
4036 (c-beginning-of-statement-1 lim)
4037 (c-forward-syntactic-ws)
4038 (c-add-syntax 'topmost-intro-cont (c-point 'boi)))
4039 )) ; end CASE 5
4040 ;; CASE 6: line is an expression, not a statement. Most
4041 ;; likely we are either in a function prototype or a function
4042 ;; call argument list
4043 ((/= (char-after containing-sexp) ?{)
4044 (c-backward-syntactic-ws containing-sexp)
4045 (cond
4046 ;; CASE 6A: we are looking at the arglist closing paren or
4047 ;; at an Objective-C or Java method call closing bracket.
4048 ((and (/= char-before-ip ?,)
4049 (memq char-after-ip '(?\) ?\])))
4050 (if (and c-method-key
4051 (progn
4052 (goto-char (1- containing-sexp))
4053 (c-backward-syntactic-ws lim)
4054 (not (looking-at c-symbol-key))))
4055 (c-add-syntax 'statement-cont containing-sexp)
4056 (goto-char containing-sexp)
4057 (c-add-syntax 'arglist-close (c-point 'boi))))
4058 ;; CASE 6B: we are looking at the first argument in an empty
4059 ;; argument list. Use arglist-close if we're actually
4060 ;; looking at a close paren or bracket.
4061 ((memq char-before-ip '(?\( ?\[))
4062 (goto-char containing-sexp)
4063 (c-add-syntax 'arglist-intro (c-point 'boi)))
4064 ;; CASE 6C: we are inside a conditional test clause. treat
4065 ;; these things as statements
4066 ((save-excursion
4067 (goto-char containing-sexp)
4068 (and (c-safe (progn (forward-sexp -1) t))
4069 (looking-at "\\<for\\>")))
4070 (goto-char (1+ containing-sexp))
4071 (c-forward-syntactic-ws indent-point)
4072 (c-beginning-of-statement-1 containing-sexp)
4073 (if (= char-before-ip ?\;)
4074 (c-add-syntax 'statement (point))
4075 (c-add-syntax 'statement-cont (point))
4076 ))
4077 ;; CASE 6D: maybe a continued method call. This is the case
4078 ;; when we are inside a [] bracketed exp, and what precede
4079 ;; the opening bracket is not an identifier.
4080 ((and c-method-key
4081 (= (char-after containing-sexp) ?\[)
4082 (save-excursion
4083 (goto-char (1- containing-sexp))
4084 (c-backward-syntactic-ws (c-point 'bod))
4085 (if (not (looking-at c-symbol-key))
4086 (c-add-syntax 'objc-method-call-cont containing-sexp))
4087 )))
4088 ;; CASE 6E: we are looking at an arglist continuation line,
4089 ;; but the preceding argument is on the same line as the
4090 ;; opening paren. This case includes multi-line
4091 ;; mathematical paren groupings, but we could be on a
4092 ;; for-list continuation line
4093 ((and (save-excursion
4094 (goto-char (1+ containing-sexp))
4095 (skip-chars-forward " \t")
4096 (not (eolp)))
4097 (save-excursion
4098 (c-beginning-of-statement-1 lim)
4099 (skip-chars-backward " \t([")
4100 (<= (point) containing-sexp)))
4101 (goto-char containing-sexp)
4102 (c-add-syntax 'arglist-cont-nonempty (c-point 'boi)))
4103 ;; CASE 6F: we are looking at just a normal arglist
4104 ;; continuation line
4105 (t (c-beginning-of-statement-1 containing-sexp)
4106 (forward-char 1)
4107 (c-forward-syntactic-ws indent-point)
4108 (c-add-syntax 'arglist-cont (c-point 'boi)))
4109 ))
4110 ;; CASE 7: func-local multi-inheritance line
4111 ((and c-baseclass-key
4112 (save-excursion
4113 (goto-char indent-point)
4114 (skip-chars-forward " \t")
4115 (looking-at c-baseclass-key)))
4116 (goto-char indent-point)
4117 (skip-chars-forward " \t")
4118 (cond
4119 ;; CASE 7A: non-hanging colon on an inher intro
4120 ((= char-after-ip ?:)
4121 (c-backward-syntactic-ws lim)
4122 (c-add-syntax 'inher-intro (c-point 'boi)))
4123 ;; CASE 7B: hanging colon on an inher intro
4124 ((= char-before-ip ?:)
4125 (c-add-syntax 'inher-intro (c-point 'boi)))
4126 ;; CASE 7C: a continued inheritance line
4127 (t
4128 (c-beginning-of-inheritance-list lim)
4129 (c-add-syntax 'inher-cont (point))
4130 )))
4131 ;; CASE 8: we are inside a brace-list
4132 ((setq placeholder (c-inside-bracelist-p containing-sexp state))
4133 (cond
4134 ;; CASE 8A: brace-list-close brace
4135 ((and (= char-after-ip ?})
4136 (c-safe (progn (forward-char 1)
4137 (backward-sexp 1)
4138 t))
4139 (= (point) containing-sexp))
4140 (c-add-syntax 'brace-list-close (c-point 'boi)))
4141 ;; CASE 8B: we're looking at the first line in a brace-list
4142 ((save-excursion
4143 (goto-char indent-point)
4144 (c-backward-syntactic-ws containing-sexp)
4145 (= (point) (1+ containing-sexp)))
4146 (goto-char containing-sexp)
4147 ;;(if (= char-after-ip ?{)
4148 ;;(c-add-syntax 'brace-list-open (c-point 'boi))
4149 (c-add-syntax 'brace-list-intro (c-point 'boi))
4150 )
4151 ;;)) ; end CASE 8B
4152 ;; CASE 8C: this is just a later brace-list-entry
4153 (t (goto-char (1+ containing-sexp))
4154 (c-forward-syntactic-ws indent-point)
4155 (if (= char-after-ip ?{)
4156 (c-add-syntax 'brace-list-open (point))
4157 (c-add-syntax 'brace-list-entry (point))
4158 )) ; end CASE 8C
4159 )) ; end CASE 8
4160 ;; CASE 9: A continued statement
4161 ((and (not (memq char-before-ip '(?\; ?} ?:)))
4162 (> (point)
4163 (save-excursion
4164 (c-beginning-of-statement-1 containing-sexp)
4165 (setq placeholder (point))))
4166 (/= placeholder containing-sexp))
4167 (goto-char indent-point)
4168 (skip-chars-forward " \t")
4169 (let ((after-cond-placeholder
4170 (save-excursion
4171 (goto-char placeholder)
4172 (if (looking-at c-conditional-key)
4173 (progn
4174 (c-safe (c-skip-conditional))
4175 (c-forward-syntactic-ws)
4176 (if (memq (following-char) '(?\;))
4177 (progn
4178 (forward-char 1)
4179 (c-forward-syntactic-ws)))
4180 (point))
4181 nil))))
4182 (cond
4183 ;; CASE 9A: substatement
4184 ((and after-cond-placeholder
4185 (>= after-cond-placeholder indent-point))
4186 (goto-char placeholder)
4187 (if (= char-after-ip ?{)
4188 (c-add-syntax 'substatement-open (c-point 'boi))
4189 (c-add-syntax 'substatement (c-point 'boi))))
4190 ;; CASE 9B: open braces for class or brace-lists
4191 ((= char-after-ip ?{)
4192 (cond
4193 ;; CASE 9B.1: class-open
4194 ((save-excursion
4195 (goto-char indent-point)
4196 (skip-chars-forward " \t{")
4197 (let ((decl (c-search-uplist-for-classkey (c-parse-state))))
4198 (and decl
4199 (setq placeholder (aref decl 0)))
4200 ))
4201 (c-add-syntax 'class-open placeholder))
4202 ;; CASE 9B.2: brace-list-open
4203 ((or (save-excursion
4204 (goto-char placeholder)
4205 (looking-at "\\<enum\\>"))
4206 (= char-before-ip ?=))
4207 (c-add-syntax 'brace-list-open placeholder))
4208 ;; CASE 9B.3: catch-all for unknown construct.
4209 (t
4210 ;; Can and should I add an extensibility hook here?
4211 ;; Something like c-recognize-hook so support for
4212 ;; unknown constructs could be added. It's probably a
4213 ;; losing proposition, so I dunno.
4214 (goto-char placeholder)
4215 (c-add-syntax 'statement-cont (c-point 'boi))
4216 (c-add-syntax 'block-open))
4217 ))
4218 ;; CASE 9C: iostream insertion or extraction operator
4219 ((looking-at "<<\\|>>")
4220 (goto-char placeholder)
4221 (and after-cond-placeholder
4222 (goto-char after-cond-placeholder))
4223 (while (and (re-search-forward "<<\\|>>" indent-point 'move)
4224 (c-in-literal placeholder)))
4225 ;; if we ended up at indent-point, then the first
4226 ;; streamop is on a separate line. Indent the line like
4227 ;; a statement-cont instead
4228 (if (/= (point) indent-point)
4229 (c-add-syntax 'stream-op (c-point 'boi))
4230 (c-backward-syntactic-ws lim)
4231 (c-add-syntax 'statement-cont (c-point 'boi))))
4232 ;; CASE 9D: continued statement. find the accurate
4233 ;; beginning of statement or substatement
4234 (t
4235 (c-beginning-of-statement-1 after-cond-placeholder)
4236 ;; KLUDGE ALERT! c-beginning-of-statement-1 can leave
4237 ;; us before the lim we're passing in. It should be
4238 ;; fixed, but I'm worried about side-effects at this
4239 ;; late date. Fix for v5.
4240 (goto-char (or (and after-cond-placeholder
4241 (max after-cond-placeholder (point)))
4242 (point)))
4243 (c-add-syntax 'statement-cont (point)))
4244 )))
4245 ;; CASE 10: an else clause?
4246 ((looking-at "\\<else\\>[^_]")
4247 (c-backward-to-start-of-if containing-sexp)
4248 (c-add-syntax 'else-clause (c-point 'boi)))
4249 ;; CASE 11: Statement. But what kind? Lets see if its a
4250 ;; while closure of a do/while construct
4251 ((progn
4252 (goto-char indent-point)
4253 (skip-chars-forward " \t")
4254 (and (looking-at "while\\b[^_]")
4255 (save-excursion
4256 (c-backward-to-start-of-do containing-sexp)
4257 (setq placeholder (point))
4258 (looking-at "do\\b[^_]"))
4259 ))
4260 (c-add-syntax 'do-while-closure placeholder))
4261 ;; CASE 12: A case or default label
4262 ((looking-at c-switch-label-key)
4263 (goto-char containing-sexp)
4264 ;; check for hanging braces
4265 (if (/= (point) (c-point 'boi))
4266 (forward-sexp -1))
4267 (c-add-syntax 'case-label (c-point 'boi)))
4268 ;; CASE 13: any other label
4269 ((looking-at c-label-key)
4270 (goto-char containing-sexp)
4271 (c-add-syntax 'label (c-point 'boi)))
4272 ;; CASE 14: block close brace, possibly closing the defun or
4273 ;; the class
4274 ((= char-after-ip ?})
4275 (let* ((lim (c-safe-position containing-sexp fullstate))
4276 (relpos (save-excursion
4277 (goto-char containing-sexp)
4278 (if (/= (point) (c-point 'boi))
4279 (c-beginning-of-statement-1 lim))
4280 (c-point 'boi))))
4281 (cond
4282 ;; CASE 14A: does this close an inline?
4283 ((progn
4284 (goto-char containing-sexp)
4285 (c-search-uplist-for-classkey state))
4286 (c-add-syntax 'inline-close relpos))
4287 ;; CASE 14B: if there an enclosing brace that hasn't
4288 ;; been narrowed out by a class, then this is a
4289 ;; block-close
4290 ((c-most-enclosing-brace state)
4291 (c-add-syntax 'block-close relpos))
4292 ;; CASE 14C: find out whether we're closing a top-level
4293 ;; class or a defun
4294 (t
4295 (save-restriction
4296 (narrow-to-region (point-min) indent-point)
4297 (let ((decl (c-search-uplist-for-classkey (c-parse-state))))
4298 (if decl
4299 (c-add-syntax 'class-close (aref decl 0))
4300 (c-add-syntax 'defun-close relpos)))))
4301 )))
4302 ;; CASE 15: statement catchall
4303 (t
4304 ;; we know its a statement, but we need to find out if it is
4305 ;; the first statement in a block
4306 (goto-char containing-sexp)
4307 (forward-char 1)
4308 (c-forward-syntactic-ws indent-point)
4309 ;; now skip forward past any case/default clauses we might find.
4310 (while (or (c-skip-case-statement-forward fullstate indent-point)
4311 (and (looking-at c-switch-label-key)
4312 (not inswitch-p)))
4313 (setq inswitch-p t))
4314 ;; we want to ignore non-case labels when skipping forward
4315 (while (and (looking-at c-label-key)
4316 (goto-char (match-end 0)))
4317 (c-forward-syntactic-ws indent-point))
4318 (cond
4319 ;; CASE 15A: we are inside a case/default clause inside a
4320 ;; switch statement. find out if we are at the statement
4321 ;; just after the case/default label.
4322 ((and inswitch-p
4323 (progn
4324 (goto-char indent-point)
4325 (c-backward-syntactic-ws containing-sexp)
4326 (back-to-indentation)
4327 (setq placeholder (point))
4328 (looking-at c-switch-label-key)))
4329 (goto-char indent-point)
4330 (skip-chars-forward " \t")
4331 (if (= (following-char) ?{)
4332 (c-add-syntax 'statement-case-open placeholder)
4333 (c-add-syntax 'statement-case-intro placeholder)))
4334 ;; CASE 15B: continued statement
4335 ((= char-before-ip ?,)
4336 (c-add-syntax 'statement-cont (c-point 'boi)))
4337 ;; CASE 15C: a question/colon construct? But make sure
4338 ;; what came before was not a label, and what comes after
4339 ;; is not a globally scoped function call!
4340 ((or (and (memq char-before-ip '(?: ??))
4341 (save-excursion
4342 (goto-char indent-point)
4343 (c-backward-syntactic-ws lim)
4344 (back-to-indentation)
4345 (not (looking-at c-label-key))))
4346 (and (memq char-after-ip '(?: ??))
4347 (save-excursion
4348 (goto-char indent-point)
4349 (skip-chars-forward " \t")
4350 ;; watch out for scope operator
4351 (not (looking-at "::")))))
4352 (c-add-syntax 'statement-cont (c-point 'boi)))
4353 ;; CASE 15D: any old statement
4354 ((< (point) indent-point)
4355 (let ((safepos (c-most-enclosing-brace fullstate)))
4356 (goto-char indent-point)
4357 (c-beginning-of-statement-1 safepos)
4358 ;; It is possible we're on the brace that opens a nested
4359 ;; function.
4360 (if (and (= (following-char) ?{)
4361 (save-excursion
4362 (c-backward-syntactic-ws safepos)
4363 (/= (preceding-char) ?\;)))
4364 (c-beginning-of-statement-1 safepos))
4365 (c-add-syntax 'statement (c-point 'boi))
4366 (if (= char-after-ip ?{)
4367 (c-add-syntax 'block-open))))
4368 ;; CASE 15E: first statement in an inline, or first
4369 ;; statement in a top-level defun. we can tell this is it
4370 ;; if there are no enclosing braces that haven't been
4371 ;; narrowed out by a class (i.e. don't use bod here!)
4372 ((save-excursion
4373 (save-restriction
4374 (widen)
4375 (goto-char containing-sexp)
4376 (c-narrow-out-enclosing-class state containing-sexp)
4377 (not (c-most-enclosing-brace state))))
4378 (goto-char containing-sexp)
4379 ;; if not at boi, then defun-opening braces are hung on
4380 ;; right side, so we need a different relpos
4381 (if (/= (point) (c-point 'boi))
4382 (progn
4383 (c-backward-syntactic-ws)
4384 (c-safe (forward-sexp (if (= (preceding-char) ?\))
4385 -1 -2)))
4386 ))
4387 (c-add-syntax 'defun-block-intro (c-point 'boi)))
4388 ;; CASE 15F: first statement in a block
4389 (t (goto-char containing-sexp)
4390 (if (/= (point) (c-point 'boi))
4391 (c-beginning-of-statement-1
4392 (if (= (point) lim)
4393 (c-safe-position (point) state) lim)))
4394 (c-add-syntax 'statement-block-intro (c-point 'boi))
4395 (if (= char-after-ip ?{)
4396 (c-add-syntax 'block-open)))
4397 ))
4398 )
4399
4400 ;; now we need to look at any modifiers
4401 (goto-char indent-point)
4402 (skip-chars-forward " \t")
4403 ;; are we looking at a comment only line?
4404 (if (looking-at c-comment-start-regexp)
4405 (c-add-syntax 'comment-intro))
4406 ;; we might want to give additional offset to friends (in C++).
4407 (if (and (eq major-mode 'c++-mode)
4408 (looking-at c-C++-friend-key))
4409 (c-add-syntax 'friend))
4410 ;; return the syntax
4411 syntax))))
4412
4413
4414 ;; indent via syntactic language elements
4415 (defun c-get-offset (langelem)
4416 ;; Get offset from LANGELEM which is a cons cell of the form:
4417 ;; (SYMBOL . RELPOS). The symbol is matched against
4418 ;; c-offsets-alist and the offset found there is either returned,
4419 ;; or added to the indentation at RELPOS. If RELPOS is nil, then
4420 ;; the offset is simply returned.
4421 (let* ((symbol (car langelem))
4422 (relpos (cdr langelem))
4423 (match (assq symbol c-offsets-alist))
4424 (offset (cdr-safe match)))
4425 ;; offset can be a number, a function, a variable, or one of the
4426 ;; symbols + or -
4427 (cond
4428 ((not match)
4429 (if c-strict-syntax-p
4430 (error "don't know how to indent a %s" symbol)
4431 (setq offset 0
4432 relpos 0)))
4433 ((eq offset '+) (setq offset c-basic-offset))
4434 ((eq offset '-) (setq offset (- c-basic-offset)))
4435 ((eq offset '++) (setq offset (* 2 c-basic-offset)))
4436 ((eq offset '--) (setq offset (* 2 (- c-basic-offset))))
4437 ((eq offset '*) (setq offset (/ c-basic-offset 2)))
4438 ((eq offset '/) (setq offset (/ (- c-basic-offset) 2)))
4439 ((and (not (numberp offset))
4440 (fboundp offset))
4441 (setq offset (funcall offset langelem)))
4442 ((not (numberp offset))
4443 (setq offset (eval offset)))
4444 )
4445 (+ (if (and relpos
4446 (< relpos (c-point 'bol)))
4447 (save-excursion
4448 (goto-char relpos)
4449 (current-column))
4450 0)
4451 offset)))
4452
4453 (defun c-indent-line (&optional syntax)
4454 ;; indent the current line as C/C++/ObjC code. Optional SYNTAX is the
4455 ;; syntactic information for the current line. Returns the amount of
4456 ;; indentation change
4457 (let* ((c-syntactic-context (or syntax (c-guess-basic-syntax)))
4458 (pos (- (point-max) (point)))
4459 (indent (apply '+ (mapcar 'c-get-offset c-syntactic-context)))
4460 (shift-amt (- (current-indentation) indent)))
4461 (and c-echo-syntactic-information-p
4462 (message "syntax: %s, indent= %d" c-syntactic-context indent))
4463 (if (zerop shift-amt)
4464 nil
4465 (delete-region (c-point 'bol) (c-point 'boi))
4466 (beginning-of-line)
4467 (indent-to indent))
4468 (if (< (point) (c-point 'boi))
4469 (back-to-indentation)
4470 ;; If initial point was within line's indentation, position after
4471 ;; the indentation. Else stay at same point in text.
4472 (if (> (- (point-max) pos) (point))
4473 (goto-char (- (point-max) pos)))
4474 )
4475 (run-hooks 'c-special-indent-hook)
4476 shift-amt))
4477
4478 (defun c-show-syntactic-information ()
4479 "Show syntactic information for current line."
4480 (interactive)
4481 (message "syntactic analysis: %s" (c-guess-basic-syntax))
4482 (c-keep-region-active))
4483
4484
4485 ;; Standard indentation line-ups
4486 (defun c-lineup-arglist (langelem)
4487 ;; lineup the current arglist line with the arglist appearing just
4488 ;; after the containing paren which starts the arglist.
4489 (save-excursion
4490 (let* ((containing-sexp
4491 (save-excursion
4492 ;; arglist-cont-nonempty gives relpos ==
4493 ;; to boi of containing-sexp paren. This
4494 ;; is good when offset is +, but bad
4495 ;; when it is c-lineup-arglist, so we
4496 ;; have to special case a kludge here.
4497 (if (memq (car langelem) '(arglist-intro arglist-cont-nonempty))
4498 (progn
4499 (beginning-of-line)
4500 (backward-up-list 1)
4501 (skip-chars-forward " \t" (c-point 'eol)))
4502 (goto-char (cdr langelem)))
4503 (point)))
4504 (cs-curcol (save-excursion
4505 (goto-char (cdr langelem))
4506 (current-column))))
4507 (if (save-excursion
4508 (beginning-of-line)
4509 (looking-at "[ \t]*)"))
4510 (progn (goto-char (match-end 0))
4511 (forward-sexp -1)
4512 (forward-char 1)
4513 (c-forward-syntactic-ws)
4514 (- (current-column) cs-curcol))
4515 (goto-char containing-sexp)
4516 (or (eolp)
4517 (not (memq (following-char) '(?{ ?\( )))
4518 (let ((eol (c-point 'eol))
4519 (here (progn
4520 (forward-char 1)
4521 (skip-chars-forward " \t")
4522 (point))))
4523 (c-forward-syntactic-ws)
4524 (if (< (point) eol)
4525 (goto-char here))))
4526 (- (current-column) cs-curcol)
4527 ))))
4528
4529 (defun c-lineup-arglist-intro-after-paren (langelem)
4530 ;; lineup an arglist-intro line to just after the open paren
4531 (save-excursion
4532 (let ((cs-curcol (save-excursion
4533 (goto-char (cdr langelem))
4534 (current-column)))
4535 (ce-curcol (save-excursion
4536 (beginning-of-line)
4537 (backward-up-list 1)
4538 (skip-chars-forward " \t" (c-point 'eol))
4539 (current-column))))
4540 (- ce-curcol cs-curcol -1))))
4541
4542 (defun c-lineup-streamop (langelem)
4543 ;; lineup stream operators
4544 (save-excursion
4545 (let* ((relpos (cdr langelem))
4546 (curcol (progn (goto-char relpos)
4547 (current-column))))
4548 (re-search-forward "<<\\|>>" (c-point 'eol) 'move)
4549 (goto-char (match-beginning 0))
4550 (- (current-column) curcol))))
4551
4552 (defun c-lineup-multi-inher (langelem)
4553 ;; line up multiple inheritance lines
4554 (save-excursion
4555 (let (cs-curcol
4556 (eol (c-point 'eol))
4557 (here (point)))
4558 (goto-char (cdr langelem))
4559 (setq cs-curcol (current-column))
4560 (skip-chars-forward "^:" eol)
4561 (skip-chars-forward " \t:" eol)
4562 (if (or (eolp)
4563 (looking-at c-comment-start-regexp))
4564 (c-forward-syntactic-ws here))
4565 (- (current-column) cs-curcol)
4566 )))
4567
4568 (defun c-lineup-C-comments (langelem)
4569 ;; line up C block comment continuation lines
4570 (save-excursion
4571 (let ((stars (progn
4572 (beginning-of-line)
4573 (skip-chars-forward " \t")
4574 (if (looking-at "\\*\\*?")
4575 (- (match-end 0) (match-beginning 0))
4576 0)))
4577 (cs-curcol (progn (goto-char (cdr langelem))
4578 (current-column))))
4579 (back-to-indentation)
4580 (if (re-search-forward "/\\*[ \t]*" (c-point 'eol) t)
4581 (goto-char (+ (match-beginning 0)
4582 (cond
4583 (c-block-comments-indent-p 0)
4584 ((= stars 1) 1)
4585 ((= stars 2) 0)
4586 (t (- (match-end 0) (match-beginning 0)))))))
4587 (- (current-column) cs-curcol))))
4588
4589 (defun c-lineup-comment (langelem)
4590 ;; support old behavior for comment indentation. we look at
4591 ;; c-comment-only-line-offset to decide how to indent comment
4592 ;; only-lines
4593 (save-excursion
4594 (back-to-indentation)
4595 ;; indent as specified by c-comment-only-line-offset
4596 (if (not (bolp))
4597 (or (car-safe c-comment-only-line-offset)
4598 c-comment-only-line-offset)
4599 (or (cdr-safe c-comment-only-line-offset)
4600 (car-safe c-comment-only-line-offset)
4601 -1000 ;jam it against the left side
4602 ))))
4603
4604 (defun c-lineup-runin-statements (langelem)
4605 ;; line up statements in coding standards which place the first
4606 ;; statement on the same line as the block opening brace.
4607 (if (= (char-after (cdr langelem)) ?{)
4608 (save-excursion
4609 (let ((curcol (progn
4610 (goto-char (cdr langelem))
4611 (current-column))))
4612 (forward-char 1)
4613 (skip-chars-forward " \t")
4614 (- (current-column) curcol)))
4615 0))
4616
4617 (defun c-lineup-math (langelem)
4618 ;; line up math statement-cont after the equals
4619 (save-excursion
4620 (let* ((relpos (cdr langelem))
4621 (equalp (save-excursion
4622 (goto-char (c-point 'boi))
4623 (skip-chars-forward "^=" (c-point 'eol))
4624 (and (= (following-char) ?=)
4625 (- (point) (c-point 'boi)))))
4626 (curcol (progn
4627 (goto-char relpos)
4628 (current-column)))
4629 donep)
4630 (while (and (not donep)
4631 (< (point) (c-point 'eol)))
4632 (skip-chars-forward "^=" (c-point 'eol))
4633 (if (c-in-literal (cdr langelem))
4634 (forward-char 1)
4635 (setq donep t)))
4636 (if (/= (following-char) ?=)
4637 ;; there's no equal sign on the line
4638 c-basic-offset
4639 ;; calculate indentation column after equals and ws, unless
4640 ;; our line contains an equals sign
4641 (if (not equalp)
4642 (progn
4643 (forward-char 1)
4644 (skip-chars-forward " \t")
4645 (setq equalp 0)))
4646 (- (current-column) equalp curcol))
4647 )))
4648
4649 (defun c-lineup-ObjC-method-call (langelem)
4650 ;; Line up methods args as elisp-mode does with function args: go to
4651 ;; the position right after the message receiver, and if you are at
4652 ;; (eolp) indent the current line by a constant offset from the
4653 ;; opening bracket; otherwise we are looking at the first character
4654 ;; of the first method call argument, so lineup the current line
4655 ;; with it.
4656 (save-excursion
4657 (let* ((extra (save-excursion
4658 (back-to-indentation)
4659 (c-backward-syntactic-ws (cdr langelem))
4660 (if (= (preceding-char) ?:)
4661 (- c-basic-offset)
4662 0)))
4663 (open-bracket-pos (cdr langelem))
4664 (open-bracket-col (progn
4665 (goto-char open-bracket-pos)
4666 (current-column)))
4667 (target-col (progn
4668 (forward-char)
4669 (forward-sexp)
4670 (skip-chars-forward " \t")
4671 (if (eolp)
4672 (+ open-bracket-col c-basic-offset)
4673 (current-column))))
4674 )
4675 (- target-col open-bracket-col extra))))
4676
4677 (defun c-lineup-ObjC-method-args (langelem)
4678 ;; Line up the colons that separate args. This is done trying to
4679 ;; align colons vertically.
4680 (save-excursion
4681 (let* ((here (c-point 'boi))
4682 (curcol (progn (goto-char here) (current-column)))
4683 (eol (c-point 'eol))
4684 (relpos (cdr langelem))
4685 (first-col-column (progn
4686 (goto-char relpos)
4687 (skip-chars-forward "^:" eol)
4688 (and (= (following-char) ?:)
4689 (current-column)))))
4690 (if (not first-col-column)
4691 c-basic-offset
4692 (goto-char here)
4693 (skip-chars-forward "^:" eol)
4694 (if (= (following-char) ?:)
4695 (+ curcol (- first-col-column (current-column)))
4696 c-basic-offset)))))
4697
4698 (defun c-lineup-ObjC-method-args-2 (langelem)
4699 ;; Line up the colons that separate args. This is done trying to
4700 ;; align the colon on the current line with the previous one.
4701 (save-excursion
4702 (let* ((here (c-point 'boi))
4703 (curcol (progn (goto-char here) (current-column)))
4704 (eol (c-point 'eol))
4705 (relpos (cdr langelem))
4706 (prev-col-column (progn
4707 (skip-chars-backward "^:" relpos)
4708 (and (= (preceding-char) ?:)
4709 (- (current-column) 1)))))
4710 (if (not prev-col-column)
4711 c-basic-offset
4712 (goto-char here)
4713 (skip-chars-forward "^:" eol)
4714 (if (= (following-char) ?:)
4715 (+ curcol (- prev-col-column (current-column)))
4716 c-basic-offset)))))
4717
4718 (defun c-snug-do-while (syntax pos)
4719 "Dynamically calculate brace hanginess for do-while statements.
4720 Using this function, `while' clauses that end a `do-while' block will
4721 remain on the same line as the brace that closes that block.
4722
4723 See `c-hanging-braces-alist' for how to utilize this function as an
4724 ACTION associated with `block-close' syntax."
4725 (save-excursion
4726 (let (langelem)
4727 (if (and (eq syntax 'block-close)
4728 (setq langelem (assq 'block-close c-syntactic-context))
4729 (progn (goto-char (cdr langelem))
4730 (if (= (following-char) ?{)
4731 (c-safe (forward-sexp -1)))
4732 (looking-at "\\<do\\>[^_]")))
4733 '(before)
4734 '(before after)))))
4735
4736
4737 ;;; This page handles insertion and removal of backslashes for C macros.
4738
4739 (defun c-backslash-region (from to delete-flag)
4740 "Insert, align, or delete end-of-line backslashes on the lines in the region.
4741 With no argument, inserts backslashes and aligns existing backslashes.
4742 With an argument, deletes the backslashes.
4743
4744 This function does not modify the last line of the region if the region ends
4745 right at the start of the following line; it does not modify blank lines
4746 at the start of the region. So you can put the region around an entire macro
4747 definition and conveniently use this command."
4748 (interactive "r\nP")
4749 (save-excursion
4750 (goto-char from)
4751 (let ((column c-backslash-column)
4752 (endmark (make-marker)))
4753 (move-marker endmark to)
4754 ;; Compute the smallest column number past the ends of all the lines.
4755 (if (not delete-flag)
4756 (while (< (point) to)
4757 (end-of-line)
4758 (if (= (preceding-char) ?\\)
4759 (progn (forward-char -1)
4760 (skip-chars-backward " \t")))
4761 (setq column (max column (1+ (current-column))))
4762 (forward-line 1)))
4763 ;; Adjust upward to a tab column, if that doesn't push past the margin.
4764 (if (> (% column tab-width) 0)
4765 (let ((adjusted (* (/ (+ column tab-width -1) tab-width) tab-width)))
4766 (if (< adjusted (window-width))
4767 (setq column adjusted))))
4768 ;; Don't modify blank lines at start of region.
4769 (goto-char from)
4770 (while (and (< (point) endmark) (eolp))
4771 (forward-line 1))
4772 ;; Add or remove backslashes on all the lines.
4773 (while (and (< (point) endmark)
4774 ;; Don't backslashify the last line
4775 ;; if the region ends right at the start of the next line.
4776 (save-excursion
4777 (forward-line 1)
4778 (< (point) endmark)))
4779 (if (not delete-flag)
4780 (c-append-backslash column)
4781 (c-delete-backslash))
4782 (forward-line 1))
4783 (move-marker endmark nil))))
4784
4785 (defun c-append-backslash (column)
4786 (end-of-line)
4787 ;; Note that "\\\\" is needed to get one backslash.
4788 (if (= (preceding-char) ?\\)
4789 (progn (forward-char -1)
4790 (delete-horizontal-space)
4791 (indent-to column))
4792 (indent-to column)
4793 (insert "\\")))
4794
4795 (defun c-delete-backslash ()
4796 (end-of-line)
4797 (or (bolp)
4798 (progn
4799 (forward-char -1)
4800 (if (looking-at "\\\\")
4801 (delete-region (1+ (point))
4802 (progn (skip-chars-backward " \t") (point)))))))
4803
4804
4805 ;; defuns for submitting bug reports
4806
4807 (defconst c-version "4.282"
4808 "cc-mode version number.")
4809 (defconst c-mode-help-address "bug-gnu-emacs@prep.ai.mit.edu"
4810 "Address for cc-mode bug reports.")
4811
4812 (defun c-version ()
4813 "Echo the current version of cc-mode in the minibuffer."
4814 (interactive)
4815 (message "Using cc-mode version %s" c-version)
4816 (c-keep-region-active))
4817
4818 ;; get reporter-submit-bug-report when byte-compiling
4819 (eval-when-compile
4820 (require 'reporter))
4821
4822 (defun c-submit-bug-report ()
4823 "Submit via mail a bug report on cc-mode."
4824 (interactive)
4825 ;; load in reporter
4826 (let ((reporter-prompt-for-summary-p t)
4827 (reporter-dont-compact-list '(c-offsets-alist)))
4828 (and
4829 (if (y-or-n-p "Do you want to submit a report on cc-mode? ")
4830 t (message "") nil)
4831 (require 'reporter)
4832 (reporter-submit-bug-report
4833 c-mode-help-address
4834 (concat "cc-mode " c-version " ("
4835 (cond ((eq major-mode 'c++-mode) "C++")
4836 ((eq major-mode 'c-mode) "C")
4837 ((eq major-mode 'objc-mode) "ObjC")
4838 ((eq major-mode 'java-mode) "Java")
4839 )
4840 ")")
4841 (let ((vars (list
4842 ;; report only the vars that affect indentation
4843 'c-basic-offset
4844 'c-offsets-alist
4845 'c-block-comments-indent-p
4846 'c-cleanup-list
4847 'c-comment-only-line-offset
4848 'c-backslash-column
4849 'c-delete-function
4850 'c-electric-pound-behavior
4851 'c-hanging-braces-alist
4852 'c-hanging-colons-alist
4853 'c-hanging-comment-ender-p
4854 'c-tab-always-indent
4855 'c-recognize-knr-p
4856 'defun-prompt-regexp
4857 'tab-width
4858 )))
4859 (if (not (boundp 'defun-prompt-regexp))
4860 (delq 'defun-prompt-regexp vars)
4861 vars))
4862 (function
4863 (lambda ()
4864 (insert
4865 (if c-special-indent-hook
4866 (concat "\n@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"
4867 "c-special-indent-hook is set to '"
4868 (format "%s" c-special-indent-hook)
4869 ".\nPerhaps this is your problem?\n"
4870 "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n\n")
4871 "\n")
4872 (format "c-emacs-features: %s\n" c-emacs-features)
4873 )))
4874 nil
4875 "Dear Barry,"
4876 ))))
4877
4878
4879 ;; menus for XEmacs 19
4880 (defun c-popup-menu (e)
4881 "Pops up the C/C++/ObjC menu."
4882 (interactive "@e")
4883 (popup-menu (cons (concat mode-name " Mode Commands") c-mode-menu))
4884 (c-keep-region-active))
4885
4886
4887 (defun c-copy-tree (tree)
4888 ;; Lift XEmacs 19.12's copy-tree
4889 (if (consp tree)
4890 (cons (c-copy-tree (car tree))
4891 (c-copy-tree (cdr tree)))
4892 (if (vectorp tree)
4893 (let* ((new (copy-sequence tree))
4894 (i (1- (length new))))
4895 (while (>= i 0)
4896 (aset new i (c-copy-tree (aref new i)))
4897 (setq i (1- i)))
4898 new)
4899 tree)))
4900
4901 (defun c-mapcar-defun (var)
4902 (let ((val (symbol-value var)))
4903 (cons var (if (atom val) val
4904 ;; XEmacs 19.12 and Emacs 19 + lucid.el have this
4905 (if (fboundp 'copy-tree)
4906 (copy-tree val)
4907 ;; Emacs 19 and Emacs 18
4908 (c-copy-tree val)
4909 )))
4910 ))
4911
4912 ;; Dynamically append the default value of most variables. This is
4913 ;; crucial because future c-set-style calls will always reset the
4914 ;; variables first to the `cc-mode' style before instituting the new
4915 ;; style. Only do this once!
4916 (or (assoc "cc-mode" c-style-alist)
4917 (progn
4918 (c-add-style "cc-mode"
4919 (mapcar 'c-mapcar-defun
4920 '(c-backslash-column
4921 c-basic-offset
4922 c-block-comments-indent-p
4923 c-cleanup-list
4924 c-comment-only-line-offset
4925 c-echo-syntactic-information-p
4926 c-electric-pound-behavior
4927 c-hanging-braces-alist
4928 c-hanging-colons-alist
4929 c-hanging-comment-ender-p
4930 c-offsets-alist
4931 c-recognize-knr-p
4932 c-strict-syntax-p
4933 c-tab-always-indent
4934 c-inhibit-startup-warnings-p
4935 )))
4936 ;; the default style is now GNU. This can be overridden in
4937 ;; c-mode-common-hook or {c,c++,objc}-mode-hook.
4938 (c-set-style c-site-default-style)))
4939
4940 ;; style variables
4941 (make-variable-buffer-local 'c-offsets-alist)
4942 (make-variable-buffer-local 'c-basic-offset)
4943 (make-variable-buffer-local 'c-file-style)
4944 (make-variable-buffer-local 'c-file-offsets)
4945 (make-variable-buffer-local 'c-comment-only-line-offset)
4946 (make-variable-buffer-local 'c-block-comments-indent-p)
4947 (make-variable-buffer-local 'c-cleanup-list)
4948 (make-variable-buffer-local 'c-hanging-braces-alist)
4949 (make-variable-buffer-local 'c-hanging-colons-alist)
4950 (make-variable-buffer-local 'c-hanging-comment-ender-p)
4951 (make-variable-buffer-local 'c-backslash-column)
4952
4953
4954
4955 ;; fsets for compatibility with BOCM
4956 (fset 'electric-c-brace 'c-electric-brace)
4957 (fset 'electric-c-semi 'c-electric-semi&comma)
4958 (fset 'electric-c-sharp-sign 'c-electric-pound)
4959 ;; there is no cc-mode equivalent for electric-c-terminator
4960 (fset 'mark-c-function 'c-mark-function)
4961 (fset 'indent-c-exp 'c-indent-exp)
4962 (fset 'set-c-style 'c-set-style)
4963 ;; Lucid Emacs 19.9 + font-lock + cc-mode - c++-mode lossage
4964 (fset 'c++-beginning-of-defun 'beginning-of-defun)
4965 (fset 'c++-end-of-defun 'end-of-defun)
4966
4967 ;; set up bc warnings for obsolete variables, but for now lets not
4968 ;; worry about obsolete functions. maybe later some will be important
4969 ;; to flag
4970 (and (memq 'v19 c-emacs-features)
4971 (let* ((na "Nothing appropriate.")
4972 (vars
4973 (list
4974 (cons 'c++-c-mode-syntax-table 'c-mode-syntax-table)
4975 (cons 'c++-tab-always-indent 'c-tab-always-indent)
4976 (cons 'c++-always-arglist-indent-p na)
4977 (cons 'c++-block-close-brace-offset 'c-offsets-alist)
4978 (cons 'c++-paren-as-block-close-p na)
4979 (cons 'c++-continued-member-init-offset 'c-offsets-alist)
4980 (cons 'c++-member-init-indent 'c-offsets-alist)
4981 (cons 'c++-friend-offset na)
4982 (cons 'c++-access-specifier-offset 'c-offsets-alist)
4983 (cons 'c++-empty-arglist-indent 'c-offsets-alist)
4984 (cons 'c++-comment-only-line-offset 'c-comment-only-line-offset)
4985 (cons 'c++-C-block-comments-indent-p 'c-block-comments-indent-p)
4986 (cons 'c++-cleanup-list 'c-cleanup-list)
4987 (cons 'c++-hanging-braces 'c-hanging-braces-alist)
4988 (cons 'c++-hanging-member-init-colon 'c-hanging-colons-alist)
4989 (cons 'c++-auto-hungry-initial-state
4990 "Use `c-auto-newline' and `c-hungry-delete-key' instead.")
4991 (cons 'c++-auto-hungry-toggle na)
4992 (cons 'c++-relative-offset-p na)
4993 (cons 'c++-special-indent-hook 'c-special-indent-hook)
4994 (cons 'c++-delete-function 'c-delete-function)
4995 (cons 'c++-electric-pound-behavior 'c-electric-pound-behavior)
4996 (cons 'c++-hungry-delete-key 'c-hungry-delete-key)
4997 (cons 'c++-auto-newline 'c-auto-newline)
4998 (cons 'c++-match-header-strongly na)
4999 (cons 'c++-defun-header-strong-struct-equivs na)
5000 (cons 'c++-version 'c-version)
5001 (cons 'c++-mode-help-address 'c-mode-help-address)
5002 (cons 'c-indent-level 'c-basic-offset)
5003 (cons 'c-brace-imaginary-offset na)
5004 (cons 'c-brace-offset 'c-offsets-alist)
5005 (cons 'c-argdecl-indent 'c-offsets-alist)
5006 (cons 'c-label-offset 'c-offsets-alist)
5007 (cons 'c-continued-statement-offset 'c-offsets-alist)
5008 (cons 'c-continued-brace-offset 'c-offsets-alist)
5009 (cons 'c-default-macroize-column 'c-backslash-column)
5010 (cons 'c++-default-macroize-column 'c-backslash-column)
5011 )))
5012 (mapcar
5013 (function
5014 (lambda (elt)
5015 (make-obsolete-variable (car elt) (cdr elt))))
5016 vars)))
5017
5018 (provide 'cc-mode)
5019 ;;; cc-mode.el ends here