home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / languages / elisp / modes / c++-mode.el < prev    next >
Encoding:
Text File  |  1993-06-23  |  106.1 KB  |  2,864 lines

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