home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 7 / FreshFishVol7.bin / bbs / gnu / libg++-2.6-fsf.lha / libg++-2.6 / libg++ / utils / c++-mode.el < prev    next >
Lisp/Scheme  |  1992-09-01  |  88KB  |  2,278 lines

  1. ;;; c++-mode.el --- major mode for editing C++ (and C) code
  2.  
  3. ;; Author: 1992 Barry A. Warsaw, Century Computing Inc. <baw@cen.com>
  4. ;;         1987 Dave Detlefs and Stewart Clamen
  5. ;;         1985 Richard M. Stallman
  6. ;; Maintainer: c++-mode-help@anthem.nlm.nih.gov
  7. ;; Created: a long, long, time ago. adapted from the original c-mode.el
  8. ;; Version:         Revision: 2.195
  9. ;; Last Modified:   Date: 1992/08/28 22:07:39
  10. ;; Keywords: C++ C editing major-mode
  11.  
  12. ;; Copyright (C) 1992 Free Software Foundation, Inc.
  13.  
  14. ;; This file is part of GNU Emacs.
  15.  
  16. ;; GNU Emacs is free software; you can redistribute it and/or modify
  17. ;; it under the terms of the GNU General Public License as published by
  18. ;; the Free Software Foundation; either version 2, or (at your option)
  19. ;; any later version.
  20.  
  21. ;; GNU Emacs is distributed in the hope that it will be useful,
  22. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  23. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  24. ;; GNU General Public License for more details.
  25.  
  26. ;; You should have received a copy of the GNU General Public License
  27. ;; along with GNU Emacs; see the file COPYING.  If not, write to
  28. ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  29.  
  30. ;; Introduction
  31. ;; ============
  32. ;; Do a "C-h m" in a c++-mode buffer for more information on
  33. ;; customizing c++-mode. To submit bug reports hit "C-c C-b" in a
  34. ;; c++-mode buffer. This runs the command c++-submit-bug-report and
  35. ;; automatically sets up the mail buffer with all the necessary
  36. ;; information.  If you have other questions contact me at the
  37. ;; following address: c++-mode-help@anthem.nlm.nih.gov. Please don't
  38. ;; send bug reports to my personal account, I may not get it for a
  39. ;; long time.
  40.  
  41. ;; Important Note about Escapes in Comments, and Performance
  42. ;; =========================================================
  43. ;; You will notice that certain characters, when typed in comment
  44. ;; regions, get escaped with a backslash.  This is a workaround for an
  45. ;; emacs bug.  In brief, GNU emacs 18 and its derivatives cannot
  46. ;; handle more than 1 comment style per mode, and as you know, C++
  47. ;; supports 2 orthogonal comment styles.  Thus emacs' syntax parsing
  48. ;; code will sometimes choke on unbalanced parentheses and single
  49. ;; quotes in comments.  Please do a "C-h v c++-untame-characters" for
  50. ;; more information. Note further that workarounds for this bug
  51. ;; require that some buffer parsing be performed in elisp where it
  52. ;; would normally be more efficient to do via the C primitives. I've
  53. ;; chosen accuracy over performance but have worked hard to give
  54. ;; acceptable performance in all but the most uncommon situations. You
  55. ;; will most likely notice c++-mode becoming slow when you're editing
  56. ;; a file of preprocessor commands, where the file contains few if any
  57. ;; function definitions. None of this can be changed until emacs
  58. ;; itself is fixed.
  59.  
  60. ;; Notes for Novice Users
  61. ;; ======================
  62. ;; c++-mode facilitates editing of C++ code by automatically handling
  63. ;; the indentation of lines of code in a manner very similar to c-mode
  64. ;; as distributed with GNU emacs. Refer to the GNU Emacs manual,
  65. ;; chapter 21 for more information on "Editing Programs".  In fact,
  66. ;; c++-mode can also be used to edit C code!
  67. ;;
  68. ;; To use c++-mode you need to do two things: get this file loaded
  69. ;; into your emacs sessions at the right time; and tell emacs what
  70. ;; type of files are C++ files.  To do the former, make sure that
  71. ;; c++-mode.el{c} is on your load-path, and add the following lines to
  72. ;; your .emacs file:
  73. ;; (autoload 'c++-mode   "c++-mode" "C++ Editing Mode" t)
  74. ;; (autoload 'c++-c-mode "c++-mode" "C Editing Mode" t)
  75. ;; 
  76. ;; To do the latter, set up your auto-mode-alist file to recognize C++
  77. ;; file extensions. For example, if you use .C and .cc as C++ source
  78. ;; code files, add this to your .emacs file:
  79. ;; (setq auto-mode-alist
  80. ;;   (append '(("\\.C$"  . c++-mode)
  81. ;;             ("\\.cc$" . c++-mode))
  82. ;;           auto-mode-alist))
  83. ;;
  84. ;; This retains the original value of auto-mode-alist.  Finally, you
  85. ;; may want to customize certain c++-mode variables.  The best place
  86. ;; to do this is in the mode hook variable called c++-mode-hook.
  87. ;; Again, see the Emacs manual, chapter 21 for more information.
  88. ;;
  89. ;; If you want to use c++-mode to edit C code, use the entry point
  90. ;; c++-c-mode. Change the above setq in your .emacs file with:
  91. ;;
  92. ;; (setq auto-mode-alist
  93. ;;   (append '(("\\.c$"  . c++-c-mode)  ; use c++-mode to edit C code
  94. ;;             ("\\.h$"  . c++-c-mode)  ; instead of built-in c-mode
  95. ;;             ("\\.C$"  . c++-mode)
  96. ;;             ("\\.cc$" . c++-mode))
  97. ;;           auto-mode-alist))
  98.  
  99. ;; Beta Testers Mailing List
  100. ;; =========================
  101. ;; Want to be a c++-mode victim, er, beta-tester?  Send add/drop
  102. ;; requests to c++-mode-victims-request@anthem.nlm.nih.gov.
  103. ;; Discussions go to c++-mode-victims@anthem.nlm.nih.gov, but bug
  104. ;; reports and such should still be sent to c++-mode-help only.
  105.  
  106. ;; Getting c++-mode.el
  107. ;; ===================
  108. ;; The latest public release version of this file should always be
  109. ;; available for anon-ftp on ftp.cme.nist.gov:pub/gnu/c++-mode.el. It
  110. ;; will also most likely be available on the elisp archive machine:
  111. ;; archive.cis.ohio-state.edu.  Look around.
  112. ;; 
  113. ;; For those of you without aftp access, try sending a message to the
  114. ;; mail-server at library@cme.nist.gov.  Put this message in the body
  115. ;; of your email: "send pub/gnu/c++-mode.el" (without the quotes) to
  116. ;; get the file in uuencoded format, or send the message "help" to get
  117. ;; more information about using the mail-server.  Please don't email
  118. ;; me asking for the latest version, I may not have it readily
  119. ;; available to send to you. The mail-server should get it to you
  120. ;; pretty quickly.  Remember that if you want advanced access to beta
  121. ;; releases, get on the victims list -- but be forewarned, you should
  122. ;; be elisp and C++ fluent, and should have anon-ftp access.
  123.  
  124. ;; LCD Archive Entry
  125. ;; =================
  126. ;; c++-mode|Barry A. Warsaw|c++-mode-help@anthem.nlm.nih.gov
  127. ;; |Mode for editing C++ code (was Detlefs' c++-mode.el)
  128. ;; | Date: 1992/08/28 22:07:39 Revision: 2.195 |
  129.  
  130. ;;; Code:
  131.  
  132.  
  133. ;; ======================================================================
  134. ;; user definable variables
  135. ;; vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
  136.  
  137. (defvar c++-mode-abbrev-table nil
  138.   "Abbrev table in use in C++-mode buffers.")
  139. (define-abbrev-table 'c++-mode-abbrev-table ())
  140.  
  141. (defvar c++-mode-map ()
  142.   "Keymap used in C++ mode.")
  143. (if c++-mode-map
  144.     ()
  145.   (setq c++-mode-map (make-sparse-keymap))
  146.   (define-key c++-mode-map "\C-j"      'reindent-then-newline-and-indent)
  147.   (define-key c++-mode-map "{"         'c++-electric-brace)
  148.   (define-key c++-mode-map "}"         'c++-electric-brace)
  149.   (define-key c++-mode-map ";"         'c++-electric-semi)
  150.   (define-key c++-mode-map "#"         'c++-electric-pound)
  151.   (define-key c++-mode-map "\e\C-h"    'mark-c-function)
  152.   (define-key c++-mode-map "\e\C-q"    'c++-indent-exp)
  153.   (define-key c++-mode-map "\t"        'c++-indent-command)
  154.   (define-key c++-mode-map "\C-c\C-i"  'c++-insert-header)
  155.   (define-key c++-mode-map "\C-c\C-\\" 'c++-macroize-region)
  156.   (define-key c++-mode-map "\C-c\C-c"  'c++-comment-region)
  157.   (define-key c++-mode-map "\C-c\C-u"  'c++-uncomment-region)
  158.   (define-key c++-mode-map "\C-c\C-x"  'c++-match-paren)
  159.   (define-key c++-mode-map "\e\C-a"    'c++-beginning-of-defun)
  160.   (define-key c++-mode-map "\e\C-e"    'c++-end-of-defun)
  161.   (define-key c++-mode-map "\e\C-x"    'c++-indent-defun)
  162.   (define-key c++-mode-map "/"         'c++-electric-slash)
  163.   (define-key c++-mode-map "*"         'c++-electric-star)
  164.   (define-key c++-mode-map ":"         'c++-electric-colon)
  165.   (define-key c++-mode-map "\177"      'c++-electric-delete)
  166.   (define-key c++-mode-map "\C-c\C-t"  'c++-toggle-auto-hungry-state)
  167.   (define-key c++-mode-map "\C-c\C-h"  'c++-toggle-hungry-state)
  168.   (define-key c++-mode-map "\C-c\C-a"  'c++-toggle-auto-state)
  169.   (define-key c++-mode-map "\C-c'"     'c++-tame-comments)
  170.   (define-key c++-mode-map "'"         'c++-tame-insert)
  171.   (define-key c++-mode-map "["         'c++-tame-insert)
  172.   (define-key c++-mode-map "]"         'c++-tame-insert)
  173.   (define-key c++-mode-map "("         'c++-tame-insert)
  174.   (define-key c++-mode-map ")"         'c++-tame-insert)
  175.   (define-key c++-mode-map "\C-c\C-b"  'c++-submit-bug-report)
  176.   (define-key c++-mode-map "\C-c\C-v"  'c++-version)
  177.   )
  178.  
  179. (defvar c++-mode-syntax-table nil
  180.   "Syntax table used in c++-mode buffers.")
  181. (defvar c++-c-mode-syntax-table nil
  182.   "Syntax table used in c++-c-mode buffers.")
  183.  
  184. (if c++-mode-syntax-table
  185.     ()
  186.   (setq c++-mode-syntax-table (make-syntax-table))
  187.   (modify-syntax-entry ?\\ "\\"    c++-mode-syntax-table)
  188.   (modify-syntax-entry ?/  ". 124" c++-mode-syntax-table)
  189.   (modify-syntax-entry ?*  ". 23b" c++-mode-syntax-table)
  190.   (modify-syntax-entry ?+  "."     c++-mode-syntax-table)
  191.   (modify-syntax-entry ?-  "."     c++-mode-syntax-table)
  192.   (modify-syntax-entry ?=  "."     c++-mode-syntax-table)
  193.   (modify-syntax-entry ?%  "."     c++-mode-syntax-table)
  194.   (modify-syntax-entry ?<  "."     c++-mode-syntax-table)
  195.   (modify-syntax-entry ?>  "."     c++-mode-syntax-table)
  196.   (modify-syntax-entry ?&  "."     c++-mode-syntax-table)
  197.   (modify-syntax-entry ?|  "."     c++-mode-syntax-table)
  198.   (modify-syntax-entry ?\' "\""    c++-mode-syntax-table)
  199.   (modify-syntax-entry ?\n ">"     c++-mode-syntax-table)
  200.   )
  201.  
  202. (if c++-c-mode-syntax-table
  203.     ()
  204.   (setq c++-c-mode-syntax-table (make-syntax-table))
  205.   (modify-syntax-entry ?\\ "\\"    c++-c-mode-syntax-table)
  206.   (modify-syntax-entry ?/  ". 14"  c++-c-mode-syntax-table)
  207.   (modify-syntax-entry ?*  ". 23"  c++-c-mode-syntax-table)
  208.   (modify-syntax-entry ?+  "."     c++-c-mode-syntax-table)
  209.   (modify-syntax-entry ?-  "."     c++-c-mode-syntax-table)
  210.   (modify-syntax-entry ?=  "."     c++-c-mode-syntax-table)
  211.   (modify-syntax-entry ?%  "."     c++-c-mode-syntax-table)
  212.   (modify-syntax-entry ?<  "."     c++-c-mode-syntax-table)
  213.   (modify-syntax-entry ?>  "."     c++-c-mode-syntax-table)
  214.   (modify-syntax-entry ?&  "."     c++-c-mode-syntax-table)
  215.   (modify-syntax-entry ?|  "."     c++-c-mode-syntax-table)
  216.   (modify-syntax-entry ?\' "\""    c++-c-mode-syntax-table)
  217.   )
  218.  
  219. (defvar c++-tab-always-indent
  220.   (if (boundp 'c-tab-always-indent) c-tab-always-indent t)
  221.   "*Controls the operation of the TAB key.
  222. If t (the default), always just indent the current line.  If nil,
  223. indent the current line only if point is at the left margin or in the
  224. line's indentation; otherwise insert a tab.  If not-nil-or-t, then tab
  225. is inserted only within literals (comments and strings) and inside
  226. preprocessor directives, but line is always reindented.")
  227. (defvar c++-always-arglist-indent-p nil
  228.   "*Control indentation of continued arglists.
  229. When non-nil, arglists continued on subsequent lines will always
  230. indent c++-empty-arglist-indent spaces, otherwise, they will indent to
  231. just under previous line's argument indentation.")
  232. (defvar c++-class-member-indent c-indent-level
  233.   "*Extra indentation given to each member of a class, relative to the
  234. enclosing class's indentation.  Note that if you change c-indent-level
  235. in your c++-mode-hook, you will probably want to set this variable to
  236. the same value.")
  237. (defvar c++-block-close-brace-offset 0
  238.   "*Extra indentation given to close braces which close a block. This
  239. does not affect braces which close a top-level construct (e.g. function).")
  240. (defvar c++-paren-as-block-close-p nil
  241.   "*Treat a parenthesis which is the first non-whitespace on a line as
  242. a paren which closes a block.  When non-nil, c-indent-level is
  243. subtracted, and c++-block-close-brace-offset is added to the line's
  244. offset.")
  245. (defvar c++-continued-member-init-offset nil
  246.   "*Extra indent for continuation lines of member inits; NIL means to align
  247. with previous initializations rather than with the colon on the first line.")
  248. (defvar c++-member-init-indent 0
  249.   "*Indentation level of member initializations in function declarations.")
  250. (defvar c++-friend-offset -4
  251.   "*Offset of C++ friend class declarations relative to member declarations.")
  252. (defvar c++-access-specifier-offset c-label-offset
  253.   "*Extra indentation given to public, protected, and private labels.")
  254. (defvar c++-empty-arglist-indent nil
  255.   "*Indicates how far to indent an line following an empty argument
  256. list.  Nil indicates to just after the paren.")
  257. (defvar c++-comment-only-line-offset 0
  258.   "*Indentation offset for line which contains only C or C++ style comments.")
  259. (defvar c++-C-block-comments-indent-p nil
  260.   "*4 styles of C block comments are supported. If this variable is nil,
  261. then styles 1-3 are supported. If this variable is non-nil, style 4 is
  262. supported.
  263. style 1:       style 2:       style 3:       style 4:
  264. /*             /*             /*             /*
  265.    blah         * blah        ** blah        blah
  266.    blah         * blah        ** blah        blah
  267.    */           */            */             */
  268. ")
  269. (defvar c++-cleanup-list nil
  270.   "*List of various C++ constructs to \"clean up\".
  271. These cleanups only take place when auto-newline minor mode is on.
  272. Current legal values are:
  273.    brace-else-brace   -- clean up \"} else {\" constructs by placing entire
  274.                          construct on a single line.  This cleanup only
  275.                          takes place when there is nothing but white
  276.                          space between the braces and the else.  
  277.    empty-defun-braces -- cleans up empty C++ function braces by
  278.                          placing them on the same line.
  279.    defun-close-semi   -- cleans up the terminating semi-colon on class
  280.                          definitions and functions by placing the semi
  281.                          on the same line as the closing brace.")
  282. (defvar c++-hanging-braces t
  283.   "*Controls the insertion of newlines before open (left) braces.
  284. This variable only has effect when auto-newline is on.  If nil, open
  285. braces do not hang (i.e. a newline is inserted before all open
  286. braces).  If t, all open braces hang -- no newline is inserted before
  287. open braces.  If not nil or t, newlines are only inserted before
  288. top-level open braces; all other braces hang.")
  289. (defvar c++-hanging-member-init-colon 'before
  290.   "*Defines how colons which introduce member initializations are formatted.
  291. Legal values are:
  292.      t       -- no newlines inserted before or after colon
  293.      nil     -- newlines inserted before and after colon
  294.      'after  -- newlines inserted only after colon
  295.      'before -- newlines inserted only before colon")
  296. (defvar c++-auto-hungry-initial-state 'none
  297.   "*Initial state of auto/hungry mode when buffer is first visited.
  298. Legal values are:
  299.      'none         -- no auto-newline and no hungry-delete-key.
  300.      'auto-only    -- auto-newline, but no hungry-delete-key.
  301.      'hungry-only  -- no auto-newline, but hungry-delete-key.
  302.      'auto-hungry  -- both auto-newline and hungry-delete-key enabled.
  303. Nil is synonymous for 'none and t is synonymous for 'auto-hungry.")
  304.  
  305. (defvar c++-auto-hungry-toggle t
  306.   "*Enable/disable toggling of auto/hungry states.
  307. Legal values are:
  308.      'none         -- auto-newline and hungry-delete-key cannot be enabled.
  309.      'auto-only    -- only auto-newline state can be toggled.
  310.      'hungry-only  -- only hungry-delete-key state can be toggled.
  311.      'auto-hungry  -- both auto-newline and hungry-delete-key can be toggled.
  312. Nil is synonymous for 'none and t is synonymous for 'auto-hungry.")
  313.  
  314. (defvar c++-mailer 'mail
  315.   "*Mail package to use to generate bug report mail buffer.")
  316. (defconst c++-mode-help-address "c++-mode-help@anthem.nlm.nih.gov"
  317.   "Address accepting submission of bug reports.")
  318.  
  319. (defvar c++-relative-offset-p t
  320.   "*Control the calculation for indentation.
  321. When non-nil (the default), indentation is calculated relative to the
  322. first statement in the block.  When nil, the indentation is calculated
  323. without regard to how the first statement is indented.")
  324.  
  325. (defvar c++-untame-characters '(?\')
  326.   "*Utilize a backslashing workaround of an emacs syntax parsing bug.
  327. If non-nil, this variable should contain a list of characters which
  328. will be prepended by a backslash in comment regions.  By default, the
  329. list contains only the most troublesome character, the single quote.
  330. To be completely safe, set this variable to:
  331.  
  332.     '(?\( ?\) ?\' ?\{ ?\} ?\[ ?\])
  333.  
  334. This is the full list of characters which can potentially cause
  335. problems if they exist unbalanced within comments. Setting this
  336. variable to nil will defeat this feature, but be forewarned!  Such
  337. un-escaped characters in comment regions can potentially break many
  338. things such as some indenting and blinking of parenthesis.
  339.  
  340. Note further that only the default set of characters will be escaped
  341. automatically as they are typed. But, executing c++-tame-comments
  342. (\\[c++-tame-comments]) will escape all characters which are members
  343. of this set, and which are found in comments throughout the file.")
  344.  
  345. (defvar c++-default-macroize-column 78
  346.   "*Column to insert backslashes.")
  347. (defvar c++-special-indent-hook nil
  348.   "*Hook for user defined special indentation adjustments.
  349. This hook gets called after each line to allow the user to do whatever
  350. special indentation adjustments are desired.  If you have non-standard
  351. indentation, you will likely need to have c++-relative-offset-p set to
  352. nil.")
  353. (defvar c++-delete-function 'backward-delete-char-untabify
  354.   "*Function called by c++-electric-delete when deleting a single char.")
  355. (defvar c++-electric-pound-behavior nil
  356.   "*List of behaviors for electric pound insertion.
  357. Only currently supported behavior is '(alignleft).")
  358.  
  359. ;; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  360. ;; NO USER DEFINABLE VARIABLES BEYOND THIS POINT
  361. ;; 
  362. (defvar c++-hungry-delete-key nil
  363.   "Internal state of hungry delete key.")
  364. (defvar c++-auto-newline nil
  365.   "Internal state of auto newline feature.")
  366.  
  367. (make-variable-buffer-local 'c++-auto-newline)
  368. (make-variable-buffer-local 'c++-hungry-delete-key)
  369.  
  370. (defconst c++-class-key "\\<\\(class\\|struct\\|union\\)\\>"
  371.   "Keywords which introduce a struct declaration in C++.")
  372. (defconst c++-access-key "\\<\\(public\\|protected\\|private\\)\\>:"
  373.   "Keywords which modify access protection.")
  374.  
  375.  
  376. ;; ======================================================================
  377. ;; c++-mode main entry point
  378. ;; ======================================================================
  379. (defun c++-mode ()
  380.   "Major mode for editing C++ code.  Revision: 2.195
  381. To submit a bug report, enter \"\\[c++-submit-bug-report]\"
  382. from a c++-mode buffer.
  383.  
  384. 1. Very much like editing C code.
  385. 2. Expression and list commands understand all C++ brackets.
  386. 3. Tab at left margin indents for C++ code
  387. 4. Comments are delimited with /* ... */ {or with // ... <newline>}
  388. 5. Paragraphs are separated by blank lines only.
  389. 6. Delete converts tabs to spaces as it moves back.
  390.  
  391. IMPORTANT NOTE: You will notice that some characters (by default, only
  392. single quote) will get escaped with a backslash when typed in a
  393. comment region.  This is a necessary workaround of a bug present in
  394. GNU emacs 18 and derivatives.  Enter \"\\[describe-variable] c++-untame-characters RET\"
  395. for more information.
  396.  
  397. Key bindings:
  398. \\{c++-mode-map}
  399.  
  400. These variables control indentation style. Those with names like
  401. c-<thing> are inherited from c-mode.  Those with names like
  402. c++-<thing> are unique for this mode, or have extended functionality
  403. from their c-mode cousins.
  404.  
  405.  c-indent-level
  406.     Indentation of C statements within surrounding block.
  407.     The surrounding block's indentation is the indentation
  408.     of the line on which the open-brace appears.
  409.  c-continued-statement-offset
  410.     Extra indentation given to a substatement, such as the
  411.     then-clause of an if or body of a while.
  412.  c-continued-brace-offset
  413.     Extra indentation given to a brace that starts a substatement.
  414.     This is in addition to c-continued-statement-offset.
  415.  c-brace-offset
  416.     Extra indentation for line if it starts with an open brace.
  417.  c-brace-imaginary-offset
  418.     An open brace following other text is treated as if it were
  419.     this far to the right of the start of its line.
  420.  c-argdecl-indent
  421.     Indentation level of declarations of C function arguments.
  422.  c-label-offset
  423.     Extra indentation for line that is a label, or case or ``default:'', or
  424.     ``public:'' or ``private:'', or ``protected:''.
  425.  
  426.  c++-tab-always-indent
  427.     Controls the operation of the TAB key.  t means always just
  428.     reindent the current line.  nil means indent the current line only
  429.     if point is at the left margin or in the line's indentation;
  430.     otherwise insert a tab.  If not-nil-or-t, then the line is first
  431.     reindented, then if the indentation hasn't changed, a tab is
  432.     inserted. This last mode is useful if you like to add tabs after
  433.     the # of preprocessor commands. Default is value for
  434.     c-tab-always-indent.
  435.  c++-block-close-brace-offset
  436.     Extra indentation give to braces which close a block. This does
  437.     not affect braces which close top-level constructs (e.g. functions).
  438.  c++-continued-member-init-offset
  439.     Extra indentation for continuation lines of member initializations; nil
  440.     means to align with previous initializations rather than with the colon.
  441.  c++-member-init-indent
  442.     Indentation level of member initializations in function declarations,
  443.     if they are on a separate line beginning with a colon.
  444.  c++-friend-offset
  445.     Offset of C++ friend class declarations relative to member declarations.
  446.  c++-access-specifier-offset
  447.     Extra indentation given to public, protected, and private keyword lines.
  448.  c++-empty-arglist-indent
  449.     If non-nil, a function declaration or invocation which ends a line with a
  450.     left paren is indented this many extra spaces, instead of flush with the
  451.     left paren. If nil, it lines up with the left paren.
  452.  c++-always-arglist-indent-p
  453.     Control indentation of continued arglists. When non-nil, arglists
  454.     continued on subsequent lines will always indent
  455.     c++-empty-arglist-indent spaces, otherwise, they will indent to
  456.     just under previous line's argument indentation.
  457.  c++-comment-only-line-offset
  458.     Extra indentation for a line containing only a C or C++ style comment.
  459.  c++-cleanup-list
  460.     A list of construct \"clean ups\" which c++-mode will perform when
  461.     auto-newline mode is on.  Current legal values are:
  462.     brace-else-brace, empty-defun-braces, defun-close-semi.
  463.  c++-hanging-braces
  464.     Controls open brace hanging behavior when using auto-newline. Nil
  465.     says no braces hang, t says all open braces hang. Not nil or t
  466.     means top-level open braces don't hang, all others do.
  467.  c++-hanging-member-init-colon
  468.     Defines how colons which introduce member initialization lists are
  469.     formatted. t means no newlines are inserted either before or after
  470.     the colon. Nil means newlines are inserted both before and after
  471.     the colon.  'before inserts newlines only before the colon, and
  472.     'after inserts newlines only after colon.
  473.  c++-auto-hungry-initial-state
  474.     Initial state of auto/hungry mode when a C++ buffer is first visited.
  475.  c++-auto-hungry-toggle
  476.     Enable/disable toggling of auto/hungry states.
  477.  c++-mailer
  478.     Mailer to use when sending bug reports.
  479.  c++-mode-help-address
  480.     Address to send bug report via email.
  481.  c++-relative-offset-p
  482.     Control the calculation for indentation. When non-nil (the
  483.     default), indentation is calculated relative to the first
  484.     statement in the block.  When nil, the indentation is calculated
  485.     without regard to how the first statement is indented. 
  486.  c++-default-macroize-column
  487.     Column to insert backslashes when macroizing a region.
  488.  c++-untame-characters
  489.     When non-nil, inserts backslash escapes before certain untamed
  490.     characters in comment regions. It is recommended that you keep the
  491.     default setting to workaround a nasty emacs bug.  Otherwise, this
  492.     variable contains a list of characters to escape.
  493.  c++-delete-function
  494.     Function called by c++-electric-delete when deleting a single char.
  495.  c++-electric-pound-behavior
  496.     List of behaviors for electric pound insertion.
  497.  
  498. Auto-newlining is no longer an all or nothing proposition. To be
  499. specific I don't believe it is possible to implement a perfect
  500. auto-newline algorithm. Sometimes you want it and sometimes you don't.
  501. So now auto-newline (and its companion, hungry-delete) can be toggled
  502. on and off on the fly.  Hungry-delete is the optional behavior of the
  503. delete key. When hungry-delete is enabled, hitting the delete key
  504. once consumes all preceeding whitespace, unless point is within a
  505. literal (defined as a C or C++ comment, or string).  Inside literals,
  506. and with hungry-delete disabled, the delete key just calls
  507. backward-delete-char-untabify.
  508.  
  509. Behavior is controlled by c++-auto-hungry-initial-state and
  510. c++-auto-hungry-toggle.  Legal values for both variables are:
  511.  
  512.    'none (or nil)      -- no auto-newline or hungry-delete.
  513.    'auto-only          -- function affects only auto-newline state.
  514.    'hungry-only        -- function affects only hungry-delete state.
  515.    'auto-hungry (or t) -- function affects both states.
  516.  
  517. Thus if c++-auto-hungry-initial-state is 'hungry-only, then only
  518. hungry state is turned on when the buffer is first visited.  If
  519. c++-auto-hungry-toggle is 'auto-hungry, and both auto-newline and
  520. hungry-delete state are on, then hitting \"\\[c++-toggle-auto-hungry-state]\"
  521. will toggle both states.  Hitting \"\\[c++-toggle-hungry-state]\" will
  522. always toggle hungry-delete state and hitting \"\\[c++-toggle-auto-state]\"
  523. will always toggle auto-newline state, regardless of the value of
  524. c++-auto-hungry-toggle.   Hungry-delete state, when on, makes the
  525. delete key consume all preceding whitespace.
  526.  
  527. Settings for K&R, BSD, and Stroustrup indentation styles are
  528.   c-indent-level                5    8    4
  529.   c-continued-statement-offset  5    8    4
  530.   c-continued-brace-offset                0
  531.   c-brace-offset               -5   -8    0
  532.   c-brace-imaginary-offset                0
  533.   c-argdecl-indent              0    8    4
  534.   c-label-offset               -5   -8   -4
  535.   c++-access-specifier-offset  -5   -8   -4
  536.   c++-empty-arglist-indent                4
  537.   c++-friend-offset                       0
  538.  
  539. Turning on C++ mode calls the value of the variable c++-mode-hook with
  540. no args, if that value is non-nil.
  541.  
  542. Report bugs by entering \"\\[c++-submit-bug-report]\". This
  543. automatically sets up a mail buffer with version information already
  544. added. You just need to add a description of the problem and send the
  545. message."
  546.   (interactive)
  547.   (kill-all-local-variables)
  548.   (use-local-map c++-mode-map)
  549.   (set-syntax-table c++-mode-syntax-table)
  550.   (setq major-mode 'c++-mode
  551.     mode-name "C++"
  552.     local-abbrev-table c++-mode-abbrev-table)
  553.   (set (make-local-variable 'paragraph-start) (concat "^$\\|" page-delimiter))
  554.   (set (make-local-variable 'paragraph-separate) paragraph-start)
  555.   (set (make-local-variable 'paragraph-ignore-fill-prefix) t)
  556.   (set (make-local-variable 'require-final-newline) t)
  557.   (set (make-local-variable 'parse-sexp-ignore-comments) nil)
  558.   ;; 
  559.   (set (make-local-variable 'indent-line-function) 'c++-indent-line)
  560.   (set (make-local-variable 'comment-start) "// ")
  561.   (set (make-local-variable 'comment-end) "")
  562.   (set (make-local-variable 'comment-column) 32)
  563.   (set (make-local-variable 'comment-start-skip) "/\\*+ *\\|// *")
  564.   (set (make-local-variable 'comment-indent-hook) 'c++-comment-indent)
  565.   ;; hack auto-hungry designators into mode-line-format
  566.   (if (listp mode-line-format)
  567.       (setq mode-line-format
  568.         (let ((modeline nil))
  569.           (mapcar
  570.            (function
  571.         (lambda (element)
  572.           (setq modeline
  573.             (append modeline
  574.                 (if (eq element 'mode-name)
  575.                     '(mode-name (c++-hungry-delete-key
  576.                          (c++-auto-newline "/ah" "/h")
  577.                          (c++-auto-newline "/a")))
  578.                   (list element))))))
  579.            mode-line-format)
  580.           modeline)))
  581.   (run-hooks 'c++-mode-hook)
  582.   (c++-set-auto-hungry-state
  583.    (memq c++-auto-hungry-initial-state '(auto-only   auto-hungry t))
  584.    (memq c++-auto-hungry-initial-state '(hungry-only auto-hungry t))))
  585.  
  586. (defun c++-c-mode ()
  587.   "Major mode for editing C code based on c++-mode. Revision: 2.195
  588. Documentation for this mode is available by doing a
  589. \"\\[describe-function] c++-mode\"."
  590.   (interactive)
  591.   (c++-mode)
  592.   (setq major-mode 'c++-c-mode
  593.     mode-name "C")
  594.   (setq comment-start "/* "
  595.     comment-end   " */")
  596.   ;; some syntax differences are necessary for C vs. C++
  597.   (set-syntax-table c++-c-mode-syntax-table)
  598.   (run-hooks 'c++-c-mode-hook))
  599.  
  600. (defun c++-comment-indent ()
  601.   "Used by indent-for-comment to decide how much to indent a comment
  602. in C++ code based on its context."
  603.   (if (looking-at "^\\(/\\*\\|//\\)")
  604.       0                    ; Existing comment at bol stays there.
  605.     (save-excursion
  606.       (skip-chars-backward " \t")
  607.       (max
  608.        ;; leave at least one space on non-empty lines.
  609.        (if (zerop (current-column)) 0 (1+ (current-column)))
  610.        (let ((cur-pt (point)))
  611.      (beginning-of-line 0)
  612.      ;; If previous line had a comment, use it's indent
  613.      (if (re-search-forward comment-start-skip cur-pt t)
  614.          (progn
  615.            (goto-char (match-beginning 0))
  616.            (current-column))
  617.        comment-column))))))        ; otherwise indent at comment column.
  618.  
  619.  
  620. ;; ======================================================================
  621. ;; most command level (interactive) and related
  622. ;; ======================================================================
  623. (defun c++-set-auto-hungry-state (auto-p hungry-p)
  624.   "Set auto/hungry to state indicated by AUTO-P and HUNGRY-P.
  625. Update mode line to indicate state to user."
  626.   (setq c++-auto-newline auto-p
  627.     c++-hungry-delete-key hungry-p)
  628.   (set-buffer-modified-p (buffer-modified-p)))
  629.  
  630. (defun c++-toggle-auto-state (arg)
  631.   "Toggle auto-newline state.
  632. This function ignores c++-auto-hungry-toggle variable.  Optional
  633. numeric ARG, if supplied turns on auto-newline when positive, turns
  634. off auto-newline when negative and toggles when zero."
  635.   (interactive "P")
  636.   (let ((auto (cond ((not arg)
  637.              (not c++-auto-newline))
  638.             ((zerop (setq arg (prefix-numeric-value arg)))
  639.              (not c++-auto-newline))
  640.             ((< arg 0) nil)
  641.             (t t))))
  642.     (c++-set-auto-hungry-state auto c++-hungry-delete-key)))
  643.  
  644. (defun c++-toggle-hungry-state (arg)
  645.   "Toggle hungry-delete-key state.
  646. This function ignores c++-auto-hungry-toggle variable.  Optional
  647. numeric ARG, if supplied turns on hungry-delete-key when positive,
  648. turns off hungry-delete-key when negative and toggles when zero."
  649.   (interactive "P")
  650.   (let ((hungry (cond ((not arg)
  651.                (not c++-hungry-delete-key))
  652.               ((zerop (setq arg (prefix-numeric-value arg)))
  653.                (not c++-hungry-delete-key))
  654.               ((< arg 0) nil)
  655.               (t t))))
  656.     (c++-set-auto-hungry-state c++-auto-newline hungry)))
  657.  
  658. (defun c++-toggle-auto-hungry-state (arg)
  659.   "Toggle auto-newline and hungry-delete-key state.
  660. Actual toggling of these states is controlled by
  661. c++-auto-hungry-toggle variable.
  662.  
  663. Optional argument has the following meanings when supplied:
  664.      Universal argument \\[universal-argument]
  665.           resets state to c++-auto-hungry-initial-state.
  666.      negative number
  667.           turn off both auto-newline and hungry-delete-key.
  668.      positive number
  669.           turn on both auto-newline and hungry-delete-key.
  670.      zero
  671.           toggle both states regardless of c++-auto-hungry-toggle-p."
  672.   (interactive "P")
  673.   (let* ((numarg (prefix-numeric-value arg))
  674.      (apl (list 'auto-only   'auto-hungry t))
  675.      (hpl (list 'hungry-only 'auto-hungry t))
  676.      (auto (cond ((not arg)
  677.               (if (memq c++-auto-hungry-toggle apl)
  678.               (not c++-auto-newline)
  679.             c++-auto-newline))
  680.              ((listp arg)
  681.               (memq c++-auto-hungry-initial-state apl))
  682.              ((zerop numarg)
  683.               (not c++-auto-newline))
  684.              ((< arg 0) nil)
  685.              (t t)))
  686.      (hungry (cond ((not arg)
  687.             (if (memq c++-auto-hungry-toggle hpl)
  688.                 (not c++-hungry-delete-key)
  689.               c++-hungry-delete-key))
  690.                ((listp arg)
  691.             (memq c++-auto-hungry-initial-state hpl))
  692.                ((zerop numarg)
  693.             (not c++-hungry-delete-key))
  694.                ((< arg 0) nil)
  695.                (t t))))
  696.     (c++-set-auto-hungry-state auto hungry)))
  697.  
  698. (defun c++-tame-insert (arg)
  699.   "Safely inserts certain troublesome characters in comment regions.
  700. Because of a syntax bug in emacs' scan-lists function, characters with
  701. string or parenthesis syntax must be escaped with a backslash or lots
  702. of things get messed up. Unfortunately, setting
  703. parse-sexp-ignore-comments to non-nil does not fix the problem.
  704.  
  705. See also the variable c++-untame-characters."
  706.   (interactive "p")
  707.   (if (and (memq last-command-char c++-untame-characters)
  708.        (memq (c++-in-literal) '(c c++)))
  709.       (insert "\\"))
  710.   (self-insert-command arg))
  711.  
  712. (defun c++-electric-delete (arg)
  713.   "If c++-hungry-delete-key is non-nil, consumes all preceding
  714. whitespace unless ARG is supplied, or point is inside a C or C++ style
  715. comment or string.  If ARG is supplied, this just calls
  716. backward-delete-char-untabify passing along ARG.
  717.  
  718. If c++-hungry-delete-key is nil, just call
  719. backward-delete-char-untabify."
  720.   (interactive "P")
  721.   (cond ((or (not c++-hungry-delete-key) arg)
  722.      (funcall c++-delete-function (prefix-numeric-value arg)))
  723.     ((let ((bod (c++-point 'bod)))
  724.        (not (or (memq (c++-in-literal bod) '(c c++ string))
  725.             (save-excursion
  726.               (skip-chars-backward " \t")
  727.               (= (preceding-char) ?#)))))
  728.      (let ((here (point)))
  729.        (skip-chars-backward " \t\n")
  730.        (if (/= (point) here)
  731.            (delete-region (point) here)
  732.          (funcall c++-delete-function 1))))
  733.     (t (funcall c++-delete-function 1))))
  734.  
  735. (defun c++-electric-pound (arg)
  736.   (interactive "p")
  737.   (if (memq (c++-in-literal) '(c c++ string))
  738.       (self-insert-command arg)
  739.     (let ((here (point-marker))
  740.       (bobp (bobp))
  741.       (bolp (bolp)))
  742.       (if (memq 'alignleft c++-electric-pound-behavior)
  743.       (progn (beginning-of-line)
  744.          (delete-horizontal-space)))
  745.       (if bobp
  746.       (insert (make-string arg last-command-char))
  747.     (insert-before-markers (make-string arg last-command-char)))
  748.       (if (not bolp)
  749.       (goto-char here))
  750.       (set-marker here nil))))
  751.  
  752. (defun c++-electric-brace (arg)
  753.   "Insert character and correct line's indentation."
  754.   (interactive "P")
  755.   (let (insertpos
  756.     (last-command-char last-command-char)
  757.     (bod (c++-point 'bod)))
  758.     (if (and (not arg)
  759.          (eolp)
  760.          (or (save-excursion
  761.            (skip-chars-backward " \t")
  762.            (bolp))
  763.          (let ((c++-auto-newline c++-auto-newline)
  764.                (open-brace-p (= last-command-char ?{)))
  765.            (if (and open-brace-p
  766.                 (or (eq c++-hanging-braces t)
  767.                 (and c++-hanging-braces
  768.                      (not (c++-at-top-level-p t bod)))))
  769.                (setq c++-auto-newline nil))
  770.            (if (c++-auto-newline)
  771.                ;; this may have auto-filled so we need to
  772.                ;; indent the previous line. we also need to
  773.                ;; indent the currently line, or
  774.                ;; c++-beginning-of-defun will not be able to
  775.                ;; correctly find the bod when
  776.                ;; c++-match-headers-strongly is nil.
  777.                (progn (c++-indent-line)
  778.                   (save-excursion
  779.                 (forward-line -1)
  780.                 (c++-indent-line))))
  781.            t)))
  782.     (progn
  783.       (if (and (memq last-command-char c++-untame-characters)
  784.            (memq (c++-in-literal bod) '(c c++)))
  785.           (insert "\\"))
  786.       (insert last-command-char)
  787.       ;; try to clean up empty defun braces if conditions apply
  788.       (let ((here (point-marker)))
  789.         (and (memq 'empty-defun-braces c++-cleanup-list)
  790.          (c++-at-top-level-p t bod)
  791.          c++-auto-newline
  792.          (= last-command-char ?\})
  793.          (progn (forward-char -1)
  794.             (skip-chars-backward " \t\n")
  795.             (= (preceding-char) ?\{))
  796.          (not (memq (c++-in-literal) '(c c++ string)))
  797.          (delete-region (point) (1- here)))
  798.         (goto-char here)
  799.         (set-marker here nil))
  800.       (let ((here (point-marker))
  801.         mbeg mend)
  802.         (if (and (memq 'brace-else-brace c++-cleanup-list)
  803.              (= last-command-char ?\{)
  804.              (let ((status
  805.                 (re-search-backward "}[ \t\n]*else[ \t\n]*{"
  806.                         nil t)))
  807.                (setq mbeg (match-beginning 0)
  808.                  mend (match-end 0))
  809.                status)
  810.              (= mend here)
  811.              (not (memq (c++-in-literal bod) '(c c++ string))))
  812.         (progn
  813.           ;; we should clean up brace-else-brace syntax
  814.           (delete-region mbeg mend)
  815.           (insert-before-markers "} else {")
  816.           (goto-char here)
  817.           (set-marker here nil))
  818.           (goto-char here)
  819.           (set-marker here nil)))
  820.       (c++-indent-line)
  821.       (if (c++-auto-newline)
  822.           (progn
  823.         ;; c++-auto-newline may have done an auto-fill
  824.         (save-excursion
  825.           (let ((here (point-marker)))
  826.             (goto-char (- (point) 2))
  827.             (c++-indent-line)
  828.             (setq insertpos (- (goto-char here) 2))
  829.             (set-marker here nil)))
  830.         (c++-indent-line)))
  831.       (save-excursion
  832.         (if insertpos (goto-char (1+ insertpos)))
  833.         (delete-char -1))))
  834.     (if insertpos
  835.     (save-excursion
  836.       (goto-char insertpos)
  837.       (self-insert-command (prefix-numeric-value arg)))
  838.       (self-insert-command (prefix-numeric-value arg)))))
  839.  
  840. (defun c++-electric-slash (arg)
  841.   "Slash as first non-whitespace character on line indents as comment
  842. unless we're inside a C style comment, or a string, does not do
  843. indentation. if first non-whitespace character on line is not a slash,
  844. then we just insert the slash.  in this case use indent-for-comment if
  845. you want to add a comment to the end of a line."
  846.   (interactive "P")
  847.   (let ((c++-auto-newline c++-auto-newline))
  848.     (if (= (preceding-char) ?/)
  849.     (setq c++-auto-newline nil))
  850.     (if (memq (preceding-char) '(?/ ?*))
  851.     (c++-electric-terminator arg)
  852.       (self-insert-command (prefix-numeric-value arg)))))
  853.  
  854. (defun c++-electric-star (arg)
  855.   "Works with c++-electric-slash to auto indent C style comment lines."
  856.   (interactive "P")
  857.   (if (= (preceding-char) ?/)
  858.       (let ((c++-auto-newline nil))
  859.     (c++-electric-terminator arg))
  860.     (self-insert-command (prefix-numeric-value arg))
  861.     (if (and (memq (c++-in-literal) '(c))
  862.          (or (= (point) (c++-point 'boi))
  863.          (= (preceding-char) ?*)))
  864.     (c++-indent-line))))
  865.  
  866. (defun c++-electric-semi (arg)
  867.   "Insert character and correct line's indentation."
  868.   (interactive "P")
  869.   (if (c++-in-literal)
  870.       (self-insert-command (prefix-numeric-value arg))
  871.     (let ((here (point-marker)))
  872.       (if (and (memq 'defun-close-semi c++-cleanup-list)
  873.            c++-auto-newline
  874.            (progn
  875.          (skip-chars-backward " \t\n")
  876.          (= (preceding-char) ?})))
  877.       (delete-region here (point)))
  878.       (goto-char here)
  879.       (set-marker here nil))
  880.     (c++-electric-terminator arg)))
  881.  
  882. (defun c++-electric-colon (arg)
  883.   "Electrify colon.  De-auto-newline double colons. No auto-new-lines
  884. for member initialization list."
  885.   (interactive "P")
  886.   (if (c++-in-literal)
  887.       (self-insert-command (prefix-numeric-value arg))
  888.     (let ((c++-auto-newline c++-auto-newline)
  889.       (insertion-point (point))
  890.       (bod (c++-point 'bod)))
  891.       (save-excursion
  892.     (cond
  893.      ;; check for double-colon where the first colon is not in a
  894.      ;; comment or literal region
  895.      ((progn (skip-chars-backward " \t\n")
  896.          (and (= (preceding-char) ?:)
  897.               (not (memq (c++-in-literal bod) '(c c++ string)))))
  898.       (progn (delete-region insertion-point (point))
  899.          (setq c++-auto-newline nil
  900.                insertion-point (point))))
  901.      ;; check for ?: construct which may be at any level
  902.      ((progn (goto-char insertion-point)
  903.          (condition-case premature-end
  904.              (backward-sexp 1)
  905.            (error nil))
  906.          (c++-backward-over-syntactic-ws bod)
  907.          (= (preceding-char) ?\?))
  908.       (setq c++-auto-newline nil))
  909.      ;; check for being at top level or top with respect to the
  910.      ;; class. if not, process as normal
  911.      ((progn (goto-char insertion-point)
  912.          (not (c++-at-top-level-p t bod))))
  913.      ;; if at top level, check to see if we are introducing a member
  914.      ;; init list. if not, continue
  915.      ((progn (c++-backward-over-syntactic-ws bod)
  916.          (= (preceding-char) ?\)))
  917.       (goto-char insertion-point)
  918.       ;; at a member init list, figure out about auto newlining. if
  919.       ;; nil or before then put a newline before the colon and
  920.       ;; adjust the insertion point, but *only* if there is no
  921.       ;; newline already before the insertion point
  922.       (if (memq c++-hanging-member-init-colon '(nil before))
  923.           (if (not (save-excursion (skip-chars-backward " \t")
  924.                        (bolp)))
  925.           (let ((c++-auto-newline t))
  926.             (c++-auto-newline)
  927.             (setq insertion-point (point)))))
  928.       ;; if hanging colon is after or nil, then newline is inserted
  929.       ;; after colon. set up variable so c++-electric-terminator
  930.       ;; places the newline correctly
  931.       (setq c++-auto-newline
  932.         (memq c++-hanging-member-init-colon '(nil after))))
  933.      ;; last condition is always put newline after colon
  934.      (t (setq c++-auto-newline nil))
  935.      ))                ; end-cond, end-save-excursion
  936.       (goto-char insertion-point)
  937.       (c++-electric-terminator arg))))
  938.  
  939. (defun c++-electric-terminator (arg)
  940.   "Insert character and correct line's indentation."
  941.   (interactive "P")
  942.   (let (insertpos (end (point)))
  943.     (if (and (not arg) (eolp)
  944.          (not (save-excursion
  945.             (beginning-of-line)
  946.             (skip-chars-forward " \t")
  947.             (or (= (following-char) ?#)
  948.             ;; Colon is special only after a label, or
  949.             ;; case, or another colon.
  950.             ;; So quickly rule out most other uses of colon
  951.             ;; and do no indentation for them.
  952.             (and (eq last-command-char ?:)
  953.                  (not (looking-at "case[ \t]"))
  954.                  (save-excursion
  955.                    (forward-word 1)
  956.                    (skip-chars-forward " \t")
  957.                    (< (point) end))
  958.                  ;; Do re-indent double colons
  959.                  (save-excursion
  960.                    (end-of-line 1)
  961.                    (looking-at ":")))
  962.             (progn
  963.               (c++-beginning-of-defun)
  964.               (let ((pps (parse-partial-sexp (point) end)))
  965.                 (or (nth 3 pps) (nth 4 pps) (nth 5 pps))))))))
  966.     (progn
  967.       (insert last-command-char)
  968.       (c++-indent-line)
  969.       (and c++-auto-newline
  970.            (not (c++-in-parens-p))
  971.            (progn
  972.          ;; the new marker object, used to be just an integer
  973.          (setq insertpos (make-marker))
  974.          ;; changed setq to set-marker
  975.          (set-marker insertpos (1- (point)))
  976.          ;; do this before the newline, since in auto fill can break
  977.          (newline)
  978.          (c++-indent-line)))
  979.       (save-excursion
  980.         (if insertpos (goto-char (1+ insertpos)))
  981.         (delete-char -1))))
  982.     (if insertpos
  983.     (save-excursion
  984.       (goto-char insertpos)
  985.       (self-insert-command (prefix-numeric-value arg)))
  986.       (self-insert-command (prefix-numeric-value arg)))))
  987.  
  988. (defun c++-indent-command (&optional whole-exp)
  989.   "Indent current line as C++ code, or in some cases insert a tab character.
  990. If c++-tab-always-indent is t (the default), always just indent the
  991. current line.  If nil, indent the current line only if point is at the
  992. left margin or in the line's indentation; otherwise insert a tab.  If
  993. not-nil-or-t, then tab is inserted only within literals (comments and
  994. strings) and inside preprocessor directives, but line is always reindented.
  995.  
  996. A numeric argument, regardless of its value, means indent rigidly all
  997. the lines of the expression starting after point so that this line
  998. becomes properly indented.  The relative indentation among the lines
  999. of the expression are preserved."
  1000.   (interactive "P")
  1001.   (let ((bod (c++-point 'bod)))
  1002.     (if whole-exp
  1003.     ;; If arg, always indent this line as C
  1004.     ;; and shift remaining lines of expression the same amount.
  1005.     (let ((shift-amt (c++-indent-line bod))
  1006.           beg end)
  1007.       (save-excursion
  1008.         (if (eq c++-tab-always-indent t)
  1009.         (beginning-of-line))
  1010.         (setq beg (point))
  1011.         (forward-sexp 1)
  1012.         (setq end (point))
  1013.         (goto-char beg)
  1014.         (forward-line 1)
  1015.         (setq beg (point)))
  1016.       (if (> end beg)
  1017.           (indent-code-rigidly beg end shift-amt "#")))
  1018.       (cond
  1019.        ((eq c++-tab-always-indent nil)
  1020.     (if (and (save-excursion
  1021.            (skip-chars-backward " \t")
  1022.            (bolp))
  1023.          (or (looking-at "[ \t]*$")
  1024.              (/= (point) (c++-point 'boi))))
  1025.         (c++-indent-line bod)
  1026.       (insert-tab)))
  1027.        ((eq c++-tab-always-indent t)
  1028.     (c++-indent-line bod))
  1029.        ((or (memq (c++-in-literal bod) '(c c++ string))
  1030.         (save-excursion
  1031.           (skip-chars-backward " \t")
  1032.           (= (preceding-char) ?#)))
  1033.     (let ((here (point))
  1034.           (boi (save-excursion (back-to-indentation) (point)))
  1035.           (indent-p nil))
  1036.       (c++-indent-line bod)
  1037.       (save-excursion
  1038.         (back-to-indentation)
  1039.         (setq indent-p (and (> here boi) (= (point) boi))))
  1040.       (if indent-p (insert-tab))))
  1041.        (t (c++-indent-line bod))))))
  1042.  
  1043. (defun c++-indent-exp ()
  1044.   "Indent each line of the C++ grouping following point."
  1045.   (interactive)
  1046.   (let ((indent-stack (list nil))
  1047.     (contain-stack (list (point)))
  1048.     (case-fold-search nil)
  1049.     restart outer-loop-done inner-loop-done state ostate
  1050.     this-indent last-sexp last-depth
  1051.     at-else at-brace
  1052.     (opoint (point))
  1053.     (next-depth 0))
  1054.     (save-excursion
  1055.       (forward-sexp 1))
  1056.     (save-excursion
  1057.       (setq outer-loop-done nil)
  1058.       (while (and (not (eobp)) (not outer-loop-done))
  1059.     (setq last-depth next-depth)
  1060.     ;; Compute how depth changes over this line
  1061.     ;; plus enough other lines to get to one that
  1062.     ;; does not end inside a comment or string.
  1063.     ;; Meanwhile, do appropriate indentation on comment lines.
  1064.     (setq inner-loop-done nil)
  1065.     (while (and (not inner-loop-done)
  1066.             (not (and (eobp) (setq outer-loop-done t))))
  1067.       (setq ostate state)
  1068.       ;; fix by reed@adapt.net.com
  1069.       ;; must pass in the return past the end of line, so that
  1070.       ;; parse-partial-sexp finds it, and recognizes that a "//"
  1071.       ;; comment is over. otherwise, state is set that we're in a
  1072.       ;; comment, and never gets unset, causing outer-loop to only
  1073.       ;; terminate in (eobp). old:
  1074.       ;;(setq state (parse-partial-sexp (point)
  1075.       ;;(progn (end-of-line) (point))
  1076.       ;;nil nil state))
  1077.       (let ((start (point))
  1078.         (line-end (progn (end-of-line) (point)))
  1079.         (end (progn (forward-char) (point))))
  1080.         (setq state (parse-partial-sexp start end nil nil state))
  1081.         (goto-char line-end))
  1082.       (setq next-depth (car state))
  1083.       (if (and (car (cdr (cdr state)))
  1084.            (>= (car (cdr (cdr state))) 0))
  1085.           (setq last-sexp (car (cdr (cdr state)))))
  1086.       (if (or (nth 4 ostate))
  1087.           (c++-indent-line))
  1088.       (if (or (nth 3 state))
  1089.           (forward-line 1)
  1090.         (setq inner-loop-done t)))
  1091.     (if (<= next-depth 0)
  1092.         (setq outer-loop-done t))
  1093.     (if outer-loop-done
  1094.         nil
  1095.       ;; If this line had ..))) (((.. in it, pop out of the levels
  1096.       ;; that ended anywhere in this line, even if the final depth
  1097.       ;; doesn't indicate that they ended.
  1098.       (while (> last-depth (nth 6 state))
  1099.         (setq indent-stack (cdr indent-stack)
  1100.           contain-stack (cdr contain-stack)
  1101.           last-depth (1- last-depth)))
  1102.       (if (/= last-depth next-depth)
  1103.           (setq last-sexp nil))
  1104.       ;; Add levels for any parens that were started in this line.
  1105.       (while (< last-depth next-depth)
  1106.         (setq indent-stack (cons nil indent-stack)
  1107.           contain-stack (cons nil contain-stack)
  1108.           last-depth (1+ last-depth)))
  1109.       (if (null (car contain-stack))
  1110.           (setcar contain-stack (or (car (cdr state))
  1111.                     (save-excursion (forward-sexp -1)
  1112.                             (point)))))
  1113.       (forward-line 1)
  1114.       (skip-chars-forward " \t")
  1115.       (if (eolp)
  1116.           nil
  1117.         (if (and (car indent-stack)
  1118.              (>= (car indent-stack) 0))
  1119.         ;; Line is on an existing nesting level.
  1120.         ;; Lines inside parens are handled specially.
  1121.         (if (or (/= (char-after (car contain-stack)) ?{)
  1122.             (c++-at-top-level-p t))
  1123.             (setq this-indent (car indent-stack))
  1124.           ;; Line is at statement level.
  1125.           ;; Is it a new statement?  Is it an else?
  1126.           ;; Find last non-comment character before this line
  1127.           (save-excursion
  1128.             (setq at-else (looking-at "else\\W"))
  1129.             (setq at-brace (= (following-char) ?{))
  1130.             (c++-backward-over-syntactic-ws opoint)
  1131.             (if (not (memq (preceding-char) '(nil ?\, ?\; ?} ?: ?{)))
  1132.             ;; Preceding line did not end in comma or semi;
  1133.             ;; indent this line  c-continued-statement-offset
  1134.             ;; more than previous.
  1135.             (progn
  1136.               (c-backward-to-start-of-continued-exp
  1137.                (car contain-stack))
  1138.               (setq this-indent
  1139.                 (+ c-continued-statement-offset
  1140.                    (current-column)
  1141.                    (if at-brace c-continued-brace-offset 0))))
  1142.               ;; Preceding line ended in comma or semi;
  1143.               ;; use the standard indent for this level.
  1144.               (if at-else
  1145.               (progn (c-backward-to-start-of-if opoint)
  1146.                  (back-to-indentation)
  1147.                  (skip-chars-forward "{ \t")
  1148.                  (setq this-indent (current-column)))
  1149.             (setq this-indent (car indent-stack))))))
  1150.           ;; Just started a new nesting level.
  1151.           ;; Compute the standard indent for this level.
  1152.           (let ((val (c++-calculate-indent
  1153.               (if (car indent-stack)
  1154.                   (- (car indent-stack))))))
  1155.         (setcar indent-stack
  1156.             (setq this-indent val))))
  1157.         ;; Adjust line indentation according to its contents
  1158.          (if (looking-at c++-access-key)
  1159.          (setq this-indent (+ this-indent c++-access-specifier-offset))
  1160.           (if (or (looking-at "case[ \t]")
  1161.               (and (looking-at "[A-Za-z]")
  1162.                (save-excursion
  1163.                  (forward-sexp 1)
  1164.                  (looking-at ":[^:]"))))
  1165.           (setq this-indent (max 0 (+ this-indent c-label-offset)))))
  1166.         ;; looking at a comment only line?
  1167.         (if (looking-at "//\\|/\\*")
  1168.         (setq this-indent (+ this-indent
  1169.                      c++-comment-only-line-offset)))
  1170.         (if (looking-at "friend[ \t]")
  1171.         (setq this-indent (+ this-indent c++-friend-offset)))
  1172.         (if (= (following-char) ?})
  1173.         (setq this-indent (- this-indent c-indent-level)))
  1174.         (if (= (following-char) ?{)
  1175.         (setq this-indent (+ this-indent c-brace-offset)))
  1176.         ;; Put chosen indentation into effect.
  1177.         (or (= (current-column) this-indent)
  1178.         (= (following-char) ?\#)
  1179.         (progn
  1180.           (delete-region (point) (progn (beginning-of-line) (point)))
  1181.           (indent-to this-indent)))
  1182.         ;; Indent any comment following the text.
  1183.         (or (looking-at comment-start-skip)
  1184.         (if (re-search-forward
  1185.              comment-start-skip
  1186.              (save-excursion (end-of-line) (point)) t)
  1187.             (progn (indent-for-comment) (beginning-of-line))))))))))
  1188.  
  1189. (defun c++-fill-C-comment ()
  1190.   "Fill a C style comment."
  1191.   (interactive)
  1192.   (save-excursion
  1193.     (let ((fill-prefix fill-prefix))
  1194.       (beginning-of-line 1)
  1195.       (save-excursion
  1196.     (re-search-forward comment-start-skip
  1197.                (save-excursion (end-of-line) (point))
  1198.                t)
  1199.     (goto-char (match-end 0))
  1200.     (set-fill-prefix))
  1201.       (while (looking-at fill-prefix)
  1202.     (forward-line -1))
  1203.       (forward-line 1)
  1204.       (insert-string "\n")
  1205.       (fill-paragraph nil)
  1206.       (delete-char -1))))
  1207.  
  1208. (defun c++-insert-header ()
  1209.   "Insert header denoting C++ code at top of buffer."
  1210.   (interactive)
  1211.   (save-excursion
  1212.     (goto-char (point-min))
  1213.     (insert "// "
  1214.         "This may look like C code, but it is really "
  1215.         "-*- C++ -*-"
  1216.         "\n\n")))
  1217.  
  1218. (defun c++-tame-comments ()
  1219.   "Backslashifies all untamed in comment regions found in the buffer.
  1220. This is the best available workaround for an emacs syntax bug in
  1221. scan-lists which exists at least as recently as v18.58.  Untamed
  1222. characters to escape are defined in the variable c++-untame-characters."
  1223.   (interactive)
  1224.   ;; make the list into a valid charset, escaping where necessary
  1225.   (let ((charset (concat "^" (mapconcat
  1226.                   (function
  1227.                    (lambda (char)
  1228.                  (if (memq char '(?\\ ?^ ?-))
  1229.                      (concat "\\" (char-to-string char))
  1230.                    (char-to-string char))))
  1231.                   c++-untame-characters ""))))
  1232.     (save-excursion
  1233.       (beginning-of-buffer)
  1234.       (while (not (eobp))
  1235.     (skip-chars-forward charset)
  1236.     (if (and (not (zerop (following-char)))
  1237.          (memq (c++-in-literal) '(c c++))
  1238.          (/= (preceding-char) ?\\ ))
  1239.         (insert "\\"))
  1240.     (if (not (eobp))
  1241.         (forward-char 1))))))
  1242.  
  1243. ;; taken from match-paren.el. Author: unknown
  1244. (defun c++-match-paren ()
  1245.   "Jumps to the paren matching the one under point, if there is one."
  1246.   (interactive)
  1247.   (cond ((looking-at "[\(\[{]")
  1248.      (forward-sexp 1)
  1249.      (backward-char))
  1250.     ((looking-at "[])}]")
  1251.      (forward-char)
  1252.      (backward-sexp 1))
  1253.     (t (message "Could not find matching paren."))))
  1254.  
  1255.  
  1256. ;; ======================================================================
  1257. ;; defuns for parsing syntactic elements
  1258. ;; ======================================================================
  1259. (defun c++-parse-state (&optional limit)
  1260.   "Determinate the syntactic state of the code at point.
  1261. Iteratively uses parse-partial-sexp from point to LIMIT and returns
  1262. the result of parse-partial-sexp at point.  LIMIT is optional and
  1263. defaults to point-max."
  1264.   (setq limit (or limit (point-max)))
  1265.   (let (state (parse-sexp-ignore-comments t))
  1266.     (while (< (point) limit)
  1267.       (setq state (parse-partial-sexp (point) limit 0)))
  1268.     state))
  1269.  
  1270. (defun c++-at-top-level-p (wrt &optional bod)
  1271.   "Return t if point is not inside a containing C++ expression, nil
  1272. if it is embedded in an expression.  When WRT is non-nil, returns nil
  1273. if not at the top level with respect to an enclosing class, or the
  1274. depth of class nesting at point.  With WRT nil, returns nil if not at
  1275. the \"real\" top level.  Optional BOD is the beginning of defun."
  1276.   (save-excursion
  1277.     (let ((indent-point (point))
  1278.       (case-fold-search nil)
  1279.       state containing-sexp paren-depth
  1280.       (bod (or bod (c++-point 'bod)))
  1281.       foundp)
  1282.       (goto-char bod)
  1283.       (setq state (c++-parse-state indent-point)
  1284.         containing-sexp (nth 1 state)
  1285.         paren-depth (nth 0 state))
  1286.       (cond
  1287.        ((eq major-mode 'c++-c-mode)
  1288.     (and (null containing-sexp) 0))
  1289.        ((not wrt)
  1290.     (null containing-sexp))
  1291.        ((c++-in-parens-p) nil)
  1292.        ((null containing-sexp) 0)
  1293.        (t
  1294.     ;; calculate depth wrt containing (possibly nested) classes
  1295.     (goto-char containing-sexp)
  1296.     (while (and (setq foundp (re-search-backward
  1297.                   (concat "[;}]\\|" c++-class-key)
  1298.                   (point-min) t))
  1299.             (let ((bod (c++-point 'bod)))
  1300.               (or (c++-in-literal bod)
  1301.               (c++-in-parens-p bod)
  1302.               ;; see if class key is inside a template spec
  1303.               (and (looking-at c++-class-key)
  1304.                    (progn (skip-chars-backward " \t\n")
  1305.                       (memq (preceding-char) '(?, ?<))))))))
  1306.     (if (memq (following-char) '(?} ?\;))
  1307.         nil
  1308.       (setq state (c++-parse-state containing-sexp))
  1309.       (and foundp
  1310.            (not (nth 1 state))
  1311.            (nth 2 state)
  1312.            paren-depth))
  1313.     )))))
  1314.  
  1315. (defun c++-in-literal (&optional lim)
  1316.   "Determine if point is in a C++ `literal'.
  1317. Return 'c if in a C-style comment, 'c++ if in a C++ style comment,
  1318. 'string if in a string literal, 'pound if on a preprocessor line, or
  1319. nil if not in a comment at all.  Optional LIM is used as the backward
  1320. limit of the search.  If omitted, or nil, c++-beginning-of-defun is
  1321. used."
  1322.   (save-excursion
  1323.     (let* ((here (point))
  1324.        (state nil)
  1325.        (match nil)
  1326.        (backlim (or lim (c++-point 'bod))))
  1327.       (goto-char backlim)
  1328.       (while (< (point) here)
  1329.     (setq match
  1330.           (and (re-search-forward "\\(/[/*]\\)\\|[\"']\\|\\(^[ \t]*#\\)"
  1331.                       here 'move)
  1332.            (buffer-substring (match-beginning 0) (match-end 0))))
  1333.     (setq state
  1334.           (cond
  1335.            ;; no match
  1336.            ((null match) nil)
  1337.            ;; looking at the opening of a C++ style comment
  1338.            ((string= "//" match)
  1339.         (if (<= here (progn (end-of-line) (point))) 'c++))
  1340.            ;; looking at the opening of a C block comment
  1341.            ((string= "/*" match)
  1342.         (if (not (re-search-forward "*/" here 'move)) 'c))
  1343.            ;; looking at the opening of a double quote string
  1344.            ((string= "\"" match)
  1345.         (if (not (save-restriction
  1346.                ;; this seems to be necessary since the
  1347.                ;; re-search-forward will not work without it
  1348.                (narrow-to-region (point) here)
  1349.                (re-search-forward
  1350.                 ;; this regexp matches a double quote
  1351.                 ;; which is preceeded by an even number
  1352.                 ;; of backslashes, including zero
  1353.                 "\\([^\\]\\|^\\)\\(\\\\\\\\\\)*\"" here 'move)))
  1354.             'string))
  1355.            ;; looking at the opening of a single quote string
  1356.            ((string= "'" match)
  1357.         (if (not (save-restriction
  1358.                ;; see comments from above
  1359.                (narrow-to-region (point) here)
  1360.                (re-search-forward
  1361.                 ;; this matches a single quote which is
  1362.                 ;; preceeded by zero or two backslashes.
  1363.                 "\\([^\\]\\|^\\)\\(\\\\\\\\\\)?'"
  1364.                 here 'move)))
  1365.             'string))
  1366.            ((string-match "[ \t]*#" match)
  1367.         (if (<= here (progn (end-of-line) (point))) 'pound))
  1368.            (t nil)))
  1369.     ) ; end-while
  1370.       state)))
  1371.  
  1372. (defun c++-in-parens-p (&optional lim)
  1373.   "Return t if inside a paren expression.
  1374. Optional LIM is used as the backward limit of the search."
  1375.   (let ((lim (or lim (c++-point 'bod))))
  1376.     (condition-case ()
  1377.     (save-excursion
  1378.       (save-restriction
  1379.         (narrow-to-region (point) lim)
  1380.         (goto-char (point-max))
  1381.         (= (char-after (or (scan-lists (point) -1 1) (point-min))) ?\()))
  1382.       (error nil))))
  1383.  
  1384.  
  1385. ;; ======================================================================
  1386. ;; defuns for calculating indentation
  1387. ;; ======================================================================
  1388. (defun c++-indent-line (&optional bod)
  1389.   "Indent current line as C++ code.
  1390. Return the amount the indentation changed by.  Optional BOD is the
  1391. point of the beginning of the C++ definition."
  1392.   (let* ((bod (or bod (c++-point 'bod)))
  1393.      (indent (c++-calculate-indent nil bod))
  1394.      beg shift-amt
  1395.      (comcol nil)
  1396.      (case-fold-search nil)
  1397.      (pos (- (point-max) (point))))
  1398.     (beginning-of-line)
  1399.     (setq beg (point))
  1400.     (cond ((eq indent nil)
  1401.        (setq indent (current-indentation)))
  1402.       ((eq indent t)
  1403.        (setq indent (c++-calculate-c-indent-within-comment)))
  1404.       ((looking-at "[ \t]*#")
  1405.        (setq indent 0))
  1406.       ((save-excursion
  1407.          (and (not (back-to-indentation))
  1408.           (looking-at "//\\|/\\*")
  1409.           (/= (setq comcol (current-column)) 0)))
  1410.        ;; we've found a comment-only line. we now must try to
  1411.        ;; determine if the line is a continuation from a comment
  1412.        ;; on the previous line.  we check to see if the comment
  1413.        ;; starts in comment-column and if so, we don't change its
  1414.        ;; indentation.
  1415.        (if (= comcol comment-column)
  1416.            (setq indent comment-column)
  1417.          (setq indent (+ indent c++-comment-only-line-offset))))
  1418.       (t
  1419.        (skip-chars-forward " \t")
  1420.        (if (listp indent) (setq indent (car indent)))
  1421.        (cond ((looking-at c++-access-key)
  1422.           (setq indent (+ indent c++-access-specifier-offset)))
  1423.          ((looking-at "default:")
  1424.           (setq indent (+ indent c-label-offset)))
  1425.          ((or (looking-at "case\\b")
  1426.               (and (looking-at "[A-Za-z]")
  1427.                (save-excursion
  1428.                  (forward-sexp 1)
  1429.                  (looking-at ":[^:]"))))
  1430.           (setq indent (max 1 (+ indent c-label-offset))))
  1431.          ((and (looking-at "else\\b")
  1432.                (not (looking-at "else\\s_")))
  1433.           (setq indent (save-excursion
  1434.                  (c-backward-to-start-of-if)
  1435.                  (back-to-indentation)
  1436.                  (skip-chars-forward "{ \t")
  1437.                  (current-column))))
  1438.          ((looking-at "\\<friend\\>")
  1439.           (setq indent (+ indent c++-friend-offset)))
  1440.          ((and (= (following-char) ?\))
  1441.                c++-paren-as-block-close-p)
  1442.           (setq indent (+ (- indent c-indent-level)
  1443.                   (save-excursion
  1444.                     (forward-char 1)
  1445.                     (cond ((c++-at-top-level-p nil bod)
  1446.                        (- c++-block-close-brace-offset))
  1447.                       ((c++-at-top-level-p t bod)
  1448.                        c-indent-level)
  1449.                       (t c++-block-close-brace-offset))))))
  1450.          ((= (following-char) ?})
  1451.           (setq indent (+ (- indent c-indent-level)
  1452.                   (if (save-excursion
  1453.                     (forward-char 1)
  1454.                     (c++-at-top-level-p nil bod))
  1455.                       (- c++-block-close-brace-offset)
  1456.                     c++-block-close-brace-offset))))
  1457.          ((= (following-char) ?{)
  1458.           (setq indent (+ indent c-brace-offset))))))
  1459.     (skip-chars-forward " \t")
  1460.     (setq shift-amt (- indent (current-column)))
  1461.     (if (zerop shift-amt)
  1462.     (if (> (- (point-max) pos) (point))
  1463.         (goto-char (- (point-max) pos)))
  1464.       (delete-region beg (point))
  1465.       (indent-to indent)
  1466.       ;; If initial point was within line's indentation,
  1467.       ;; position after the indentation.  Else stay at same point in text.
  1468.       (if (> (- (point-max) pos) (point))
  1469.       (goto-char (- (point-max) pos))))
  1470.     ;; save-excursion is necessary because things break if the hook
  1471.     ;; changes point or mark
  1472.     (save-excursion
  1473.       (run-hooks 'c++-special-indent-hook))
  1474.     shift-amt))
  1475.  
  1476. (defun c++-calculate-indent (&optional parse-start bod)
  1477.   "Return appropriate indentation for current line as C++ code.
  1478. In usual case returns an integer: the column to indent to.
  1479. Returns nil if line starts inside a string, t if in a comment.
  1480. Optional PARSE-START is the location to start parsing, and optional
  1481. BOD is the beginning of the C++ definition."
  1482.   (save-excursion
  1483.     (beginning-of-line)
  1484.     (let ((indent-point (point))
  1485.       (case-fold-search nil)
  1486.       state do-indentation literal
  1487.       containing-sexp streamop-pos
  1488.       (inclass-shift 0) inclass-depth
  1489.       (bod (or bod (c++-point 'bod))))
  1490.       (if parse-start
  1491.       (goto-char parse-start)
  1492.     (goto-char bod))
  1493.       (setq parse-start (point)
  1494.         state (c++-parse-state indent-point)
  1495.         containing-sexp (nth 1 state))
  1496.       ;; it is possible that c++-defun-header-weak could not find the
  1497.       ;; beginning of the C++ definition. The following code attempts
  1498.       ;; to work around this.  It is probably better to just use
  1499.       ;; c++-match-header-strongly, but there are performance questions
  1500.       (if (null state)
  1501.       (let* ((c++-match-header-strongly t)
  1502.          (bod (c++-point 'bod)))
  1503.         (goto-char bod)
  1504.         (setq state (c++-parse-state indent-point)
  1505.           containing-sexp (nth 1 state)
  1506.           parse-start (point))))
  1507.       (setq literal (c++-in-literal bod))
  1508.       (cond ((memq literal '(string))
  1509.          ;; in a string.
  1510.          nil)
  1511.         ((memq literal '(c c++))
  1512.          ;; in a C or C++ style comment.
  1513.          t)
  1514.         ;; is this a comment-only line in the first column or
  1515.         ;; comment-column?  if so we don't change the indentation,
  1516.         ;; otherwise, we indent relative to surrounding code
  1517.         ;; (later on).
  1518.         ((progn (goto-char indent-point)
  1519.             (beginning-of-line)
  1520.             (skip-chars-forward " \t")
  1521.             (and (looking-at comment-start-skip)
  1522.              (or (zerop (current-column))
  1523.                  (= (current-column) comment-column))))
  1524.          (current-column))
  1525.         ((setq inclass-depth (c++-at-top-level-p t bod))
  1526.          ;; Line is at top level.  May be comment-only line, data
  1527.          ;; or function definition, or may be function argument
  1528.          ;; declaration or member initialization.  Indent like the
  1529.          ;; previous top level line unless:
  1530.          ;;
  1531.          ;; 1. the previous line ends in a closeparen without
  1532.          ;; semicolon, in which case this line is the first
  1533.          ;; argument declaration or member initialization, or
  1534.          ;;
  1535.          ;; 2. the previous line ends with a closeparen
  1536.          ;; (closebrace), optional spaces, and a semicolon, in
  1537.          ;; which case this line follows a multiline function
  1538.          ;; declaration (class definition), or
  1539.          ;;
  1540.          ;; 3. the previous line begins with a colon, in which
  1541.          ;; case this is the second line of member inits.  It is
  1542.          ;; assumed that arg decls and member inits are not mixed.
  1543.          ;;
  1544.          (+
  1545.           ;; add an offset if we are inside a class defun body,
  1546.           ;; i.e. we are at the top level, but only wrt a
  1547.           ;; containing class
  1548.           (setq inclass-shift (* c++-class-member-indent inclass-depth))
  1549.           (progn
  1550.         (goto-char indent-point)
  1551.         (skip-chars-forward " \t")
  1552.         (if (looking-at "/[/*]")
  1553.             ;; comment only line, but must not be in the first
  1554.             ;; column since cond case above would have caught it
  1555.             0
  1556.           (if (= (following-char) ?{)
  1557.               0
  1558.             (c++-backward-over-syntactic-ws parse-start)
  1559.             (if (or (= (preceding-char) ?\))
  1560.                 (and (= (preceding-char) ?t)
  1561.                  (save-excursion
  1562.                    (forward-word -1)
  1563.                    (looking-at "\\<const\\>"))))
  1564.             (progn        ; first arg decl or member init
  1565.               (goto-char indent-point)
  1566.               (skip-chars-forward " \t")
  1567.               (if (= (following-char) ?:)
  1568.                   c++-member-init-indent
  1569.                 c-argdecl-indent))
  1570.               (if (= (preceding-char) ?\;)
  1571.               (progn
  1572.                 (backward-char 1)
  1573.                 (skip-chars-backward " \t")))
  1574.               ;; may be first line after a hanging member init colon
  1575.               (if (or (= (preceding-char) ?:)
  1576.                   (save-excursion
  1577.                 (forward-line 1)
  1578.                 (skip-chars-forward " \t")
  1579.                 (= (following-char) ?:)))
  1580.               ;; check to see if we're looking at a member
  1581.               ;; init, or access specifier
  1582.               (if (progn
  1583.                 (beginning-of-line)
  1584.                 (skip-chars-forward " \t")
  1585.                 (looking-at c++-access-key))
  1586.                   ;; access specifier so add zero to inclass-shift
  1587.                   0
  1588.                 ;; member init, so add offset, but
  1589.                 ;; subtract inclass-shift
  1590.                 (- c++-member-init-indent c++-class-member-indent))
  1591.             (if (or (= (preceding-char) ?})
  1592.                 (= (preceding-char) ?\))
  1593.                 (save-excursion
  1594.                   (beginning-of-line)
  1595.                   (looking-at "[ \t]*\\<friend\\>")))
  1596.                 0
  1597.               (beginning-of-line) ; cont arg decls or member inits
  1598.               (skip-chars-forward " \t")
  1599.               (if (or (memq (c++-in-literal bod) '(c c++))
  1600.                   (looking-at "/[/*]"))
  1601.                   0
  1602.                 (if (= (following-char) ?:)
  1603.                 (if c++-continued-member-init-offset
  1604.                     (+ (current-indentation)
  1605.                        c++-continued-member-init-offset)
  1606.                   (progn
  1607.                     (forward-char 1)
  1608.                     (skip-chars-forward " \t")
  1609.                     (- (current-column)
  1610.                        inclass-shift)))
  1611.                   ;; else first check to see if its a
  1612.                   ;; multiple inheritance continuation line
  1613.                   (if (looking-at
  1614.                    (concat c++-class-key
  1615.                        "[ \t]+"
  1616.                        "\\(\\w+[ \t]*:[ \t]*\\)?"))
  1617.                   (if (progn (goto-char indent-point)
  1618.                          (c++-backward-over-syntactic-ws)
  1619.                          (= (preceding-char) ?,))
  1620.                       (progn (goto-char (match-end 0))
  1621.                          (current-column))
  1622.                     0)
  1623.                 ;; we might be looking at the opening
  1624.                 ;; brace of a class defun
  1625.                 (if (= (following-char) ?\{)
  1626.                     (- c-indent-level c++-class-member-indent)
  1627.                   (if (eolp)
  1628.                       ;; looking at a blank line, indent
  1629.                       ;; next line to zero
  1630.                       0
  1631.                     (if (save-excursion
  1632.                       (goto-char indent-point)
  1633.                       (beginning-of-line)
  1634.                       (bobp))
  1635.                     ;; at beginning of buffer, if
  1636.                     ;; nothing else, indent to zero 
  1637.                     0
  1638.                       (if (c++-in-parens-p)
  1639.                       ;; we are perhaps inside a
  1640.                       ;; member init call
  1641.                       (while (and (c++-in-parens-p)
  1642.                               (< bod (point)))
  1643.                         (forward-line -1)
  1644.                         (skip-chars-forward " \t")))
  1645.                       ;; subtract inclass-shift since
  1646.                       ;; its already incorporated by
  1647.                       ;; defaultin current-indentation
  1648.                       (- (current-indentation) inclass-shift)
  1649.                       ))))))))
  1650.               ))))))
  1651.         ((/= (char-after containing-sexp) ?{)
  1652.          ;; line is expression, not statement:
  1653.          ;; indent to just after the surrounding open -- unless
  1654.          ;; empty arg list, in which case we do what
  1655.          ;; c++-empty-arglist-indent says to do.
  1656.          (if (and c++-empty-arglist-indent
  1657.               (or c++-always-arglist-indent-p
  1658.               (null (nth 2 state))    ;; indicates empty arg
  1659.                         ;; list.
  1660.               ;; Use a heuristic: if the first
  1661.               ;; non-whitespace following left paren on
  1662.               ;; same line is not a comment,
  1663.               ;; is not an empty arglist.
  1664.               (save-excursion
  1665.                 (goto-char (1+ containing-sexp))
  1666.                 (not
  1667.                  (looking-at "\\( \\|\t\\)*[^/\n]")))))
  1668.          (progn
  1669.            (goto-char containing-sexp)
  1670.            (beginning-of-line)
  1671.            (skip-chars-forward " \t")
  1672.            (goto-char (min (+ (point) c++-empty-arglist-indent)
  1673.                    (1+ containing-sexp)))
  1674.            (current-column))
  1675.            ;; In C-mode, we would always indent to one after the
  1676.            ;; left paren.  Here, though, we may have an
  1677.            ;; empty-arglist, so we'll indent to the min of that
  1678.            ;; and the beginning of the first argument.
  1679.            (goto-char (1+ containing-sexp))
  1680.            ;; we want to skip any whitespace b/w open paren and
  1681.            ;; first argurment. this handles while (thing) style
  1682.            ;; and while( thing ) style
  1683.            (skip-chars-forward " \t")
  1684.            (current-column)))
  1685.         (t
  1686.          ;; Statement.  Find previous non-comment character.
  1687.          (goto-char indent-point)
  1688.          (c++-backward-over-syntactic-ws containing-sexp)
  1689.          (if (not (memq (preceding-char) '(nil ?\, ?\; ?} ?: ?\{)))
  1690.          ;; This line is continuation of preceding line's statement;
  1691.          ;; indent  c-continued-statement-offset  more than the
  1692.          ;; previous line of the statement.
  1693.          (progn
  1694.            (c-backward-to-start-of-continued-exp containing-sexp)
  1695.            ;; take care of << and >> while in streams
  1696.            (if (let ((here (point)))
  1697.              (save-excursion
  1698.                (and (progn
  1699.                   (goto-char indent-point)
  1700.                   (looking-at "[ \t]*\\(<<\\|>>\\)"))
  1701.                 (progn
  1702.                   (goto-char here)
  1703.                   (skip-chars-forward "^><\n")
  1704.                   (setq streamop-pos (current-column))
  1705.                   (looking-at "\\(<<\\|>>\\)")))))
  1706.                streamop-pos
  1707.              (+ (current-column)
  1708.             ;; j.peck hack to prevent repeated continued
  1709.             ;; indentation:
  1710.             (if (save-excursion
  1711.                   (beginning-of-line 1)
  1712.                   (c++-backward-over-syntactic-ws containing-sexp)
  1713.                   (memq (preceding-char)
  1714.                     '(nil ?\, ?\; ?} ?: ?\{)))
  1715.                 c-continued-statement-offset
  1716.               ;; the following statements *do* indent even
  1717.               ;; for single statements (are there others?)
  1718.               (if (looking-at
  1719.                    "\\(do\\|else\\|for\\|if\\|while\\)\\b")
  1720.                   c-continued-statement-offset
  1721.                 ;; else may be a continued statement inside
  1722.                 ;; a simple for/else/while/if/do loop
  1723.                 (beginning-of-line 1)
  1724.                 (forward-char -1)
  1725.                 (c-backward-to-start-of-continued-exp
  1726.                  containing-sexp)
  1727.                 (if (looking-at
  1728.                  "\\(do\\|else\\|for\\|if\\|while\\)\\b")
  1729.                 c-continued-statement-offset
  1730.                   0)))
  1731.             ;; j.peck  [8/13/91]
  1732.             ;; j.peck hack replaced this line:
  1733.             ;; \(+ c-continued-statement-offset (current-column)
  1734.             ;; Add continued-brace-offset? [weikart]
  1735.             (save-excursion
  1736.               (goto-char indent-point)
  1737.               (skip-chars-forward " \t")
  1738.               (cond ((= (following-char) ?\{)
  1739.                  c-continued-brace-offset)
  1740.                 ((and (= (following-char) ?\})
  1741.                       (progn (forward-char 1)
  1742.                          (c++-at-top-level-p nil bod)))
  1743.                  (- c-continued-statement-offset))
  1744.                 (t 0))))))
  1745.            ;; This line may start a new statement, or it could
  1746.            ;; represent the while closure of a do/while construct
  1747.            (if (save-excursion
  1748.              (and (progn (goto-char indent-point)
  1749.                  (skip-chars-forward " \t\n")
  1750.                  (looking-at "while\\b"))
  1751.               (progn
  1752.                 (c++-backward-to-start-of-do containing-sexp)
  1753.                 (looking-at "do\\b"))
  1754.               (setq do-indentation (current-column))))
  1755.            do-indentation
  1756.          ;; this could be a case statement. if so we want to
  1757.          ;; indent it like the first case statement after a switch
  1758.          (if (save-excursion
  1759.                (goto-char indent-point)
  1760.                (skip-chars-forward " \t\n")
  1761.                (looking-at "case\\b"))
  1762.              (progn
  1763.                (goto-char containing-sexp)
  1764.                (back-to-indentation)
  1765.                (+ (current-column) c-indent-level))
  1766.            ;; else, this is the start of a new statement
  1767.            ;; Position following last unclosed open.
  1768.            (goto-char containing-sexp)
  1769.            ;; Is line first statement after an open-brace?
  1770.            (or
  1771.             (and c++-relative-offset-p
  1772.              ;; If no, find that first statement and
  1773.              ;; indent like it.
  1774.              (save-excursion
  1775.                (forward-char 1)
  1776.                (while (progn (skip-chars-forward " \t\n")
  1777.                      (looking-at
  1778.                       (concat
  1779.                        "#\\|/\\*\\|//"
  1780.                        "\\|\\(case\\|default\\)[ \t]"
  1781.                        "\\|[a-zA-Z0-9_$]*:[^:]"
  1782.                        "\\|friend[ \t]"
  1783.                        c++-class-key
  1784.                        "[ \t]")))
  1785.                  ;; Skip over comments and labels
  1786.                  ;; following openbrace.
  1787.                  (cond
  1788.                   ((= (following-char) ?\#)
  1789.                    (forward-line 1))
  1790.                   ((looking-at "/\\*")
  1791.                    (search-forward "*/" nil 'move))
  1792.                   ((looking-at
  1793.                 (concat "//\\|friend[ \t]" c++-class-key
  1794.                     "[ \t]"))
  1795.                    (forward-line 1))
  1796.                   ((looking-at "\\(case\\|default\\)\\b")
  1797.                    (forward-line 1))
  1798.                   (t
  1799.                    (re-search-forward ":[^:]" nil 'move))))
  1800.                ;; The first following code counts
  1801.                ;; if it is before the line we want to indent.
  1802.                (and (< (point) indent-point)
  1803.                 (+ (current-column)
  1804.                    (if (save-excursion
  1805.                      (goto-char indent-point)
  1806.                      (c++-backward-over-syntactic-ws)
  1807.                      (= (preceding-char) ?,))
  1808.                        c-indent-level 0)))))
  1809.             ;; If no previous statement, indent it relative to
  1810.             ;; line brace is on.  For open brace in column
  1811.             ;; zero, don't let statement start there too.  If
  1812.             ;; c-indent-offset is zero, use c-brace-offset +
  1813.             ;; c-continued-statement-offset instead.  For
  1814.             ;; open-braces not the first thing in a line, add
  1815.             ;; in c-brace-imaginary-offset.
  1816.             (+ (if (and (bolp) (zerop c-indent-level))
  1817.                (+ c-brace-offset c-continued-statement-offset)
  1818.              c-indent-level)
  1819.                ;; Move back over whitespace before the openbrace.
  1820.                ;; If openbrace is not first nonwhite thing on the line,
  1821.                ;; add the c-brace-imaginary-offset.
  1822.                (progn (skip-chars-backward " \t")
  1823.                   (if (bolp) 0 c-brace-imaginary-offset))
  1824.                ;; If the openbrace is preceded by a parenthesized exp,
  1825.                ;; move to the beginning of that;
  1826.                ;; possibly a different line
  1827.                (progn
  1828.              (if (eq (preceding-char) ?\))
  1829.                  (forward-sexp -1))
  1830.              ;; Get initial indentation of the line we are on.
  1831.              (current-indentation))))))))))))
  1832.  
  1833. (defun c++-calculate-c-indent-within-comment ()
  1834.   "Return the indentation amount for line, assuming that
  1835. the current line is to be regarded as part of a block comment."
  1836.   (let (end stars indent)
  1837.     (save-excursion
  1838.       (beginning-of-line)
  1839.       (skip-chars-forward " \t")
  1840.       (setq stars (if (looking-at "\\*\\*?")
  1841.               (- (match-end 0) (match-beginning 0))
  1842.             0))
  1843.       (skip-chars-backward " \t\n")
  1844.       (setq end (point))
  1845.       (beginning-of-line)
  1846.       (skip-chars-forward " \t")
  1847.       (if (re-search-forward "/\\*[ \t]*" end t)
  1848.       (goto-char (+ (match-beginning 0)
  1849.             (cond (c++-C-block-comments-indent-p 0)
  1850.                   ((= stars 1) 1)
  1851.                   ((= stars 2) 0)
  1852.                   (t (- (match-end 0) (match-beginning 0)))))))
  1853.       (current-column))))
  1854.  
  1855.  
  1856. ;; ======================================================================
  1857. ;; defuns to look backwards for things
  1858. ;; ======================================================================
  1859. (defun c++-backward-over-syntactic-ws (&optional lim)
  1860.   "Skip backwards over syntactic whitespace.
  1861. Syntactic whitespace is defined as lexical whitespace, C and C++ style
  1862. comments, and preprocessor directives. Search no farther back than
  1863. optional LIM.  If LIM is ommitted, point-min is used."
  1864.   (let (literal stop)
  1865.     (setq lim (or lim (point-min)))
  1866.     (while (not stop)
  1867.       (skip-chars-backward " \t\n\r\f" lim)
  1868.       (setq literal (c++-in-literal))
  1869.       (cond ((eq literal 'c++)
  1870.          (let ((sblim (max (c++-point 'bol) lim))
  1871.            (here (point)))
  1872.            (goto-char sblim)
  1873.            (if (search-forward "//" here 'move)
  1874.            (goto-char (match-beginning 0))
  1875.          (goto-char sblim))))
  1876.         ((eq literal 'c)
  1877.          (if (search-backward "/*" lim 'move)
  1878.          (goto-char (match-beginning 0))
  1879.            (setq stop t)))
  1880.         ((and (= (preceding-char) ?/)
  1881.           (progn (forward-char -1)
  1882.              (= (preceding-char) ?*)))
  1883.          (forward-char -1))
  1884.         ((and (eq literal 'pound)
  1885.           (> (c++-point 'bol) lim))
  1886.          (beginning-of-line))
  1887.         (t (setq stop t))
  1888.         ))))
  1889.  
  1890. (defun c++-backward-to-start-of-do (&optional limit)
  1891.   "Move to the start of the last ``unbalanced'' do."
  1892.   (setq limit (or limit (c++-point 'bod)))
  1893.   (let ((do-level 1)
  1894.     (case-fold-search nil))
  1895.     (while (not (zerop do-level))
  1896.       ;; we protect this call because trying to execute this when the
  1897.       ;; while is not associated with a do will throw an error
  1898.       (condition-case err
  1899.       (progn
  1900.         (backward-sexp 1)
  1901.         (cond ((memq (c++-in-literal limit) '(c c++)))
  1902.           ((looking-at "while\\b")
  1903.            (setq do-level (1+ do-level)))
  1904.           ((looking-at "do\\b")
  1905.            (setq do-level (1- do-level)))
  1906.           ((< (point) limit)
  1907.            (setq do-level 0)
  1908.            (goto-char limit))))
  1909.     (error
  1910.      (goto-char limit)
  1911.      (setq do-level 0))))))
  1912.  
  1913. (defun c++-auto-newline ()
  1914.   "Insert a newline iff we're not in a literal.
  1915. Literals are defined as being inside a C or C++ style comment or open
  1916. string according to mode's syntax."
  1917.   (let ((bod (c++-point 'bod)))
  1918.     (and c++-auto-newline
  1919.      (not (c++-in-literal bod))
  1920.      (not (newline)))))
  1921.  
  1922. (defun c++-point (position)
  1923.   "Returns the value of point at certain commonly referenced POSITIONs.
  1924. POSITION can be one of the following symbols:
  1925.   bol -- beginning of line
  1926.   eol -- end of line
  1927.   bod -- beginning of defun
  1928.   boi -- back to indentation
  1929. This function does not modify point or mark."
  1930.   (let ((here (point)) bufpos)
  1931.     (cond ((eq position 'bol) (beginning-of-line))
  1932.       ((eq position 'eol) (end-of-line))
  1933.       ((eq position 'bod) (c++-beginning-of-defun))
  1934.       ((eq position 'boi) (back-to-indentation))
  1935.       )
  1936.     (setq bufpos (point))
  1937.     (goto-char here)
  1938.     bufpos))
  1939.  
  1940.  
  1941. ;; ======================================================================
  1942. ;; defuns for "macroizations" -- making C++ parameterized types via macros
  1943. ;; ======================================================================
  1944. (defun c++-macroize-region (from to arg)
  1945.   "Insert backslashes at end of every line in region.  Useful for defining cpp
  1946. macros.  If called with negative argument, will remove trailing backslashes,
  1947. so that indentation will work right."
  1948.   (interactive "r\np")
  1949.   (save-excursion
  1950.     (goto-char from)
  1951.     (beginning-of-line 1)
  1952.     (let ((line (count-lines (point-min) (point)))
  1953.       (to-line (save-excursion (goto-char to)
  1954.                    (count-lines (point-min) (point)))))
  1955.       (while (< line to-line)
  1956.     (c++-backslashify-current-line (> arg 0))
  1957.     (forward-line 1) (setq line (1+ line))))))
  1958.  
  1959. (defun c++-backslashify-current-line (doit)
  1960.   "Backslashifies current line."
  1961.   (end-of-line 1)
  1962.   (cond
  1963.    (doit
  1964.     ;; Note that "\\\\" is needed to get one backslash.
  1965.     (if (not (save-excursion (forward-char -1) (looking-at "\\\\")))
  1966.     (progn
  1967.       (if (>= (current-column) c++-default-macroize-column)
  1968.           (insert " \\")
  1969.         (while (<= (current-column) c++-default-macroize-column)
  1970.           (insert "\t") (end-of-line))
  1971.         (delete-char -1)
  1972.         (while (< (current-column) c++-default-macroize-column)
  1973.           (insert " ") (end-of-line))
  1974.         (insert "\\")))))
  1975.    (t
  1976.     (forward-char -1)
  1977.     (if (looking-at "\\\\")
  1978.     (progn (skip-chars-backward " \t")
  1979.            (kill-line))))))
  1980.  
  1981.  
  1982. ;; ======================================================================
  1983. ;; defuns for  commenting out multiple lines.
  1984. ;; ======================================================================
  1985. (defun c++-comment-region (beg end)
  1986.   "Comment out all lines in a region between mark and current point by
  1987. inserting comment-start in front of each line."
  1988.   (interactive "*r")
  1989.   (save-excursion
  1990.     (save-restriction
  1991.       (narrow-to-region
  1992.        (progn (goto-char beg) (beginning-of-line) (point))
  1993.        (progn (goto-char end) (or (bolp) (forward-line 1)) (point)))
  1994.       (goto-char (point-min))
  1995.       (while (not (eobp))
  1996.     (insert comment-start)
  1997.     (forward-line 1))
  1998.       (if (eq major-mode 'c++-c-mode)
  1999.       (insert comment-end)))))
  2000.  
  2001. (defun c++-uncomment-region (beg end)
  2002.   "Uncomment all lines in region between mark and current point by deleting
  2003. the leading \"// \" from each line, if any."
  2004.   (interactive "*r")
  2005.   (save-excursion
  2006.     (save-restriction
  2007.       (narrow-to-region
  2008.        (progn (goto-char beg) (beginning-of-line) (point))
  2009.        (progn (goto-char end) (forward-line 1) (point)))
  2010.       (goto-char (point-min))
  2011.       (let ((comment-regexp
  2012.          (if (eq major-mode 'c++-c-mode)
  2013.          (concat "\\s *\\(" (regexp-quote comment-start)
  2014.              "\\|"      (regexp-quote comment-end)
  2015.              "\\)")
  2016.            (concat "\\s *" (regexp-quote comment-start)))))
  2017.     (while (not (eobp))
  2018.       (if (looking-at comment-regexp)
  2019.           (delete-region (match-beginning 0) (match-end 0)))
  2020.       (forward-line 1))))))
  2021.  
  2022.  
  2023. ;; ======================================================================
  2024. ;; grammar parsing
  2025. ;; ======================================================================
  2026.  
  2027. ;;; Below are two regular expressions that attempt to match defuns
  2028. ;;; "strongly" and "weakly."  The strong one almost reconstructs the
  2029. ;;; grammar of C++; the weak one just figures anything id or curly on
  2030. ;;; the left begins a defun.  The constant "c++-match-header-strongly"
  2031. ;;; determines which to use; the default is the weak one.
  2032.  
  2033. (defvar c++-match-header-strongly nil
  2034.   "*If NIL, use c++-defun-header-weak to identify beginning of definitions,
  2035. if nonNIL, use c++-defun-header-strong")
  2036.  
  2037. (defvar c++-defun-header-strong-struct-equivs
  2038.   "\\(class\\|struct\\|union\\|enum\\)"
  2039.   "Regexp to match names of structure declaration blocks in C++")
  2040.  
  2041. (defconst c++-defun-header-strong
  2042.   (let*
  2043.       (; valid identifiers
  2044.        ;; There's a real wierdness here -- if I switch the below
  2045.        (id "\\(\\w\\|_\\)+")
  2046.        ;; to be
  2047.        ;; (id "\\(_\\|\\w\\)+")
  2048.        ;; things no longer work right.  Try it and see!
  2049.  
  2050.        ; overloadable operators
  2051.        (op-sym1
  2052.      "[---+*/%^&|~!=<>]\\|[---+*/%^&|<>=!]=\\|<<=?\\|>>=?")
  2053.        (op-sym2
  2054.      "&&\\|||\\|\\+\\+\\|--\\|()\\|\\[\\]")     
  2055.        (op-sym (concat "\\(" op-sym1 "\\|" op-sym2 "\\)"))
  2056.        ; whitespace
  2057.        (middle "[^\\*]*\\(\\*+[^/\\*][^\\*]*\\)*")
  2058.        (c-comment (concat "/\\*" middle "\\*+/"))
  2059.        (wh (concat "\\(\\s \\|\n\\|//.*$\\|" c-comment "\\)"))
  2060.        (wh-opt (concat wh "*"))
  2061.        (wh-nec (concat wh "+"))
  2062.        (oper (concat "\\(" "operator" "\\("
  2063.              wh-opt op-sym "\\|" wh-nec id "\\)" "\\)"))
  2064.        (dcl-list "([^():]*)")
  2065.        (func-name (concat "\\(" oper "\\|" id "::" id "\\|" id "\\)"))
  2066.        (inits
  2067.      (concat "\\(:"
  2068.          "\\(" wh-opt id "(.*\\()" wh-opt "," "\\)\\)*"
  2069.          wh-opt id "(.*)" wh-opt "{"
  2070.          "\\|" wh-opt "{\\)"))
  2071.        (type-name (concat
  2072.             "\\(" c++-defun-header-strong-struct-equivs wh-nec "\\)?"
  2073.             id))
  2074.        (type (concat "\\(const" wh-nec "\\)?"
  2075.              "\\(" type-name "\\|" type-name wh-opt "\\*+" "\\|"
  2076.              type-name wh-opt "&" "\\)"))
  2077.        (modifier "\\(inline\\|virtual\\|overload\\|auto\\|static\\)")
  2078.        (modifiers (concat "\\(" modifier wh-nec "\\)*"))
  2079.        (func-header
  2080.      ;;     type               arg-dcl
  2081.      (concat modifiers type wh-nec func-name wh-opt dcl-list wh-opt inits))
  2082.        (inherit (concat "\\(:" wh-opt "\\(public\\|protected\\|private\\)?"
  2083.             wh-nec id "\\)"))
  2084.        (cs-header (concat
  2085.             c++-defun-header-strong-struct-equivs
  2086.             wh-nec id wh-opt inherit "?" wh-opt "{")))
  2087.     (concat "^\\(" func-header "\\|" cs-header "\\)"))
  2088.   "Strongly-defined regexp to match beginning of structure or
  2089. function definition.")
  2090.  
  2091.  
  2092. ;; This part has to do with recognizing defuns.
  2093.  
  2094. ;; The weak convention we will use is that a defun begins any time
  2095. ;; there is a left curly brace, or some identifier on the left margin,
  2096. ;; followed by a left curly somewhere on the line.  (This will also
  2097. ;; incorrectly match some continued strings, but this is after all
  2098. ;; just a weak heuristic.)  Suggestions for improvement (short of the
  2099. ;; strong scheme shown above) are welcomed.
  2100.  
  2101. (defconst c++-defun-header-weak "^{\\|^[_a-zA-Z].*{"
  2102.   "Weakly-defined regexp to match beginning of structure or function definition.")
  2103.  
  2104.  
  2105. (defun c++-beginning-of-defun (&optional arg)
  2106.   (interactive "p")
  2107.   (if (not arg) (setq arg 1))
  2108.   (let ((c++-defun-header (if c++-match-header-strongly
  2109.                   c++-defun-header-strong
  2110.                 c++-defun-header-weak)))
  2111.     (cond ((or (= arg 0) (and (> arg 0) (bobp))) nil)
  2112.       ((and (not (looking-at c++-defun-header))
  2113.         (let ((curr-pos (point))
  2114.               (open-pos (if (search-forward "{" nil 'move)
  2115.                     (point)))
  2116.               (beg-pos
  2117.             (if (re-search-backward c++-defun-header nil 'move)
  2118.                 (match-beginning 0))))
  2119.           (if (and open-pos beg-pos
  2120.                (< beg-pos curr-pos)
  2121.                (> open-pos curr-pos))
  2122.               (progn
  2123.             (goto-char beg-pos)
  2124.             (if (= arg 1) t nil));; Are we done?
  2125.             (goto-char curr-pos)
  2126.             nil))))
  2127.       (t
  2128.         (if (and (looking-at c++-defun-header) (not (bobp)))
  2129.         (forward-char (if (< arg 0) 1 -1)))
  2130.         (and (re-search-backward c++-defun-header nil 'move (or arg 1))
  2131.          (goto-char (match-beginning 0)))))))
  2132.  
  2133.  
  2134. (defun c++-end-of-defun (arg)
  2135.   (interactive "p")
  2136.   (let ((c++-defun-header (if c++-match-header-strongly
  2137.                   c++-defun-header-strong
  2138.                 c++-defun-header-weak)))
  2139.     (if (and (eobp) (> arg 0))
  2140.     nil
  2141.       (if (and (> arg 0) (looking-at c++-defun-header)) (forward-char 1))
  2142.       (let ((pos (point)))
  2143.     (c++-beginning-of-defun 
  2144.       (if (< arg 0)
  2145.           (- (- arg (if (eobp) 0 1)))
  2146.         arg))
  2147.     (if (and (< arg 0) (bobp))
  2148.         t
  2149.       (if (re-search-forward c++-defun-header nil 'move)
  2150.           (progn (forward-char -1)
  2151.              (forward-sexp)
  2152.              (beginning-of-line 2)))
  2153.       (if (and (= pos (point)) 
  2154.            (re-search-forward c++-defun-header nil 'move))
  2155.           (c++-end-of-defun 1))))
  2156.       t)))
  2157.  
  2158. (defun c++-indent-defun ()
  2159.   "Indents the current function def, struct or class decl."
  2160.   (interactive)
  2161.   (let ((restore (point)))
  2162.     (c++-end-of-defun 1)
  2163.     (beginning-of-line 1)
  2164.     (let ((end (point-marker)))
  2165.       (c++-beginning-of-defun)
  2166.       (while (and (< (point) end))
  2167.     (c++-indent-line)
  2168.     (forward-line 1)
  2169.     (beginning-of-line 1))
  2170.       (set-marker end nil))
  2171.     (goto-char restore)))
  2172.  
  2173.  
  2174. ;; ======================================================================
  2175. ;; defuns for submitting bug reports
  2176. ;; ======================================================================
  2177. (defconst c++-version "Revision: 2.195"
  2178.   "c++-mode version number.")
  2179.  
  2180. (defun c++-version ()
  2181.   "Echo the current version of c++-mode."
  2182.   (interactive)
  2183.   (message "Using c++-mode.el %s" c++-version))
  2184.  
  2185. (defun c++-dump-state (mode)
  2186.   "Inserts into the c++-mode-state-buffer the current state of
  2187. c++-mode into the bug report mail buffer. MODE is either c++-mode or
  2188. c++-c-mode.
  2189.  
  2190. Use \\[c++-submit-bug-report] to submit a bug report."
  2191.   (let ((buffer (current-buffer))
  2192.     (varlist (list 'c++-continued-member-init-offset
  2193.                'c++-class-member-indent
  2194.                'c++-member-init-indent
  2195.                'c++-friend-offset
  2196.                'c++-access-specifier-offset
  2197.                'c++-empty-arglist-indent
  2198.                'c++-always-arglist-indent-p
  2199.                'c++-comment-only-line-offset
  2200.                'c++-C-block-comments-indent-p
  2201.                'c++-cleanup-list
  2202.                'c++-hanging-braces
  2203.                'c++-hanging-member-init-colon
  2204.                'c++-auto-hungry-initial-state
  2205.                'c++-auto-hungry-toggle
  2206.                'c++-hungry-delete-key
  2207.                'c++-auto-newline
  2208.                'c++-default-macroize-column
  2209.                'c++-match-header-strongly
  2210.                'c++-defun-header-strong-struct-equivs
  2211.                'c++-tab-always-indent
  2212.                'c++-untame-characters
  2213.                'c++-relative-offset-p
  2214.                'c++-electric-pound-behavior
  2215.                'c++-delete-function
  2216.                'c++-paren-as-block-close-p
  2217.                'c++-block-close-brace-offset
  2218.                'c-indent-level
  2219.                'c-continued-statement-offset
  2220.                'c-continued-brace-offset
  2221.                'c-brace-offset
  2222.                'c-brace-imaginary-offset
  2223.                'c-argdecl-indent
  2224.                'c-label-offset
  2225.                'tab-width
  2226.                )))
  2227.     (set-buffer buffer)
  2228.     (if c++-special-indent-hook
  2229.     (insert "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"
  2230.         "c++-special-indent-hook is set to '"
  2231.         (symbol-name c++-special-indent-hook)
  2232.         ".\nPerhaps this is your problem?\n"
  2233.         "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n\n"))
  2234.     (insert (emacs-version) "\n")
  2235.     (insert "c++-mode.el " c++-version " (editing "
  2236.         (if (eq mode 'c++-mode) "C++" "C")
  2237.         " code) \n\ncurrent state:\n==============\n(setq\n")
  2238.     (mapcar
  2239.      (function
  2240.       (lambda (varsym)
  2241.     (let ((val (eval varsym))
  2242.           (sym (symbol-name varsym)))
  2243.       (insert "     " sym " "
  2244.           (if (or (listp val) (symbolp val)) "'" "")
  2245.           (prin1-to-string val)
  2246.           "\n"))))
  2247.      varlist)
  2248.     (insert "     )\n")
  2249.     ))
  2250.  
  2251. (defun c++-submit-bug-report ()
  2252.   "Submit via mail a bug report using the mailer in c++-mailer."
  2253.   (interactive)
  2254.   (let ((curbuf (current-buffer))
  2255.     (mode   major-mode)
  2256.     (mailbuf (progn (funcall c++-mailer)
  2257.             (current-buffer))))
  2258.     (pop-to-buffer curbuf)
  2259.     (pop-to-buffer mailbuf)
  2260.     (insert c++-mode-help-address)
  2261.     (if (re-search-forward "^subject:[ \t]+" (point-max) 'move)
  2262.     (insert "Bug in c++-mode.el " c++-version))
  2263.     (if (not (re-search-forward mail-header-separator (point-max) 'move))
  2264.     (progn (goto-char (point-max))
  2265.            (insert "\n" mail-header-separator "\n")
  2266.            (goto-char (point-max)))
  2267.       (forward-line 1))
  2268.     (set-mark (point))            ;user should see mark change
  2269.     (insert "\n\n")
  2270.     (c++-dump-state mode)
  2271.     (exchange-point-and-mark)))
  2272.  
  2273.  
  2274. ;; this is sometimes useful
  2275. (provide 'c++-mode)
  2276.  
  2277. ;;; c++-mode.el ends here
  2278.