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

Import from CVS: tag r19-14
author cvs
date Mon, 13 Aug 2007 08:45:50 +0200
parents
children 0293115a14e9
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/modes/old-c++-mode.el	Mon Aug 13 08:45:50 2007 +0200
@@ -0,0 +1,2869 @@
+;;; c++-mode.el --- major mode for editing C++ (and C) code
+
+;; Author: 1992 Barry A. Warsaw, Century Computing Inc. <bwarsaw@cen.com>
+;;         1987 Dave Detlefs and Stewart Clamen
+;;         1985 Richard M. Stallman
+;; Maintainer: c++-mode-help@anthem.nlm.nih.gov
+;; Created: a long, long, time ago. adapted from the original c-mode.el
+;; Version:         2.353
+;; Last Modified:   1993/06/23 13:58:52
+;; Keywords: c
+
+;; Copyright (C) 1992, 1993 Free Software Foundation, Inc.
+
+;; This file is part of XEmacs.
+
+;; XEmacs is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; XEmacs is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;; General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with XEmacs; see the file COPYING.  If not, write to the Free
+;; Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+;; Introduction
+;; ============
+;; Do a "C-h m" in a c++-mode buffer for more information on
+;; customizing c++-mode.  To submit bug reports hit "C-c C-b" in a
+;; c++-mode buffer.  This runs the command c++-submit-bug-report and
+;; automatically sets up the mail buffer with all the necessary
+;; information.  If you have other questions contact me at the
+;; following address: c++-mode-help@anthem.nlm.nih.gov.  Please don't
+;; send bug reports to my personal account, I may not get it for a
+;; long time.
+
+;; Notes for Novice Users
+;; ======================
+;; c++-mode facilitates editing of C++ code by automatically handling
+;; the indentation of lines of code in a manner very similar to c-mode
+;; as distributed with GNU Emacs.  Refer to the GNU Emacs manual,
+;; chapter 21 for more information on "Editing Programs".  In fact,
+;; c++-mode (through its companion mode entry point c++-c-mode) can
+;; also be used to edit both K&R and ANSI C code!
+;;
+;; To use c++-mode, add the following to your .emacs file.  This
+;; assumes you will use .cc or .C extensions for your C++ source:
+;;
+;; (autoload 'c++-mode   "c++-mode" "C++ Editing Mode" t)
+;; (autoload 'c++-c-mode "c++-mode" "C Editing Mode" t)
+;; (setq auto-mode-alist
+;;   (append '(("\\.C$"  . c++-mode)
+;;             ("\\.cc$" . c++-mode)
+;;             ("\\.c$"  . c++-c-mode)   ; to edit C code
+;;             ("\\.h$"  . c++-c-mode)   ; to edit C code
+;;            ) auto-mode-alist))
+;;
+;; If you want to use the default c-mode for editing C code, then just
+;; omit the lines marked "to edit C code".
+;;
+;; Finally, you may want to customize certain c++-mode variables.  The
+;; best place to do this is in the mode hook variable called
+;; c++-mode-hook.  Again, see the Emacs manual, chapter 21 for more
+;; information.
+
+;; Important Note about Escapes in Comments, and Performance
+;; =========================================================
+;; You may notice that certain characters, when typed in comment
+;; regions, get escaped with a backslash.  This is a workaround for
+;; bugs in Emacs' syntax parsing algorithms.  In brief, syntax parsing
+;; in Emacs 18 and derivatives is broken because syntax tables are not
+;; rich enough to support more than 1 comment style per mode (as C++
+;; requires).  The result is that Emacs will sometimes choke on
+;; unbalanced parentheses and single quotes in comments.  Please do a
+;; "C-h v c++-untame-characters" for more information.
+;;
+;; This problem affect both the accuracy and performance of c++-mode
+;; because some parsing must be performed in Emacs lisp instead of
+;; relying on the C primitives.  In general, I've chosen accuracy over
+;; performance, but have worked hard to give moderately acceptable
+;; speed in all but the most uncommon situations.  You will most likely
+;; notice c++-mode slowing when you're editing a file of preprocessor
+;; commands, or inside long functions or class definitions.
+;; Optimization is an ongoing concern, but the real solution is to fix
+;; Emacs.
+;;
+;; As of release 19.4, Lucid Emacs is distributed with the fixes in
+;; place, and c++-mode will automatically take advantage of them so
+;; none of the above applies to you.  Similar patches will be part of
+;; FSF GNU Emacs 19.  Some patches for GNU Emacs 18 have been released
+;; on the beta site, but they are unsupported.  Email for more
+;; information.
+
+;; Beta Testers Mailing List
+;; =========================
+;; Want to be a c++-mode victim, er, beta-tester?  Send add/drop
+;; requests to c++-mode-victims-request@anthem.nlm.nih.gov.
+;; Discussions go to c++-mode-victims@anthem.nlm.nih.gov, but bug
+;; reports and such should still be sent to c++-mode-help only.
+;;
+;; Many, many thanks go out to all the folks on the beta test list.
+;; Without their patience, testing, insight, and code contribution,
+;; c++-mode.el would be a far inferior package.
+
+;; Getting c++-mode.el
+;; ===================
+;; The latest public release version of this file should always be
+;; available for anonymous ftp on the Emacs lisp archive machine.  The
+;; path to the file is:
+;;
+;; archive.cis.ohio-state.edu:pub/gnu/emacs/elisp-archive/modes/c++-mode.el.Z 
+;; 
+;; For those of you without anon-ftp access, you can use the DEC's
+;; ftpmail'er at the address ftpmail@decwrl.dec.com.  Send the
+;; following message in the body of your mail to that address to get
+;; c++-mode:
+;;
+;; reply <a valid net address back to you>
+;; connect archive.cis.ohio-state.edu
+;; binary
+;; uuencode
+;; chdir pub/gnu/emacs/elisp-archive/modes
+;; get c++-mode.el.Z
+;;
+;; or just send the message "help" for more information on ftpmail.
+;; Response times will vary with the number of requests in the queue.
+
+;; LCD Archive Entry:
+;; c++-mode|Barry A. Warsaw|c++-mode-help@anthem.nlm.nih.gov
+;; |Mode for editing C++, and ANSI/K&R C code (was Detlefs' c++-mode.el)
+;; |1993/06/23 13:58:52|2.353|
+
+;;; Code:
+
+;; some people may not have c-mode loaded in by default.  c++-mode.el
+;; unfortunately still depends on distrib c-mode.  c-mode doesn't
+;; provide itself so this hack is best known way to ensure its loaded
+(or (fboundp 'c-mode)
+    (load "c-mode" nil t))
+
+
+;; ======================================================================
+;; user definable variables
+;; vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
+
+(defconst c++-emacs-features
+  (let ((mse-spec 'no-dual-comments)
+	(scanner 'v18))
+    ;; vanilla GNU18/Epoch 4 uses default values
+    (if (= 8 (length (parse-partial-sexp (point) (point))))
+	;; we know we're using v19 style dual-comment specifications.
+	;; All Lemacsen use 8-bit modify-syntax-entry flags, as do all
+	;; patched FSF19, GNU18, Epoch4's.  Only vanilla FSF19 uses
+	;; 1-bit flag.  Lets be as smart as we can about figuring this
+	;; out.
+	(let ((table (copy-syntax-table)))
+	  (modify-syntax-entry ?a ". 12345678" table)
+	  (if (= (logand (lsh (aref table ?a) -16) 255) 255)
+	      (setq mse-spec '8-bit)
+	    (setq mse-spec '1-bit))
+	  ;; we also know we're using a quicker, built-in comment
+	  ;; scanner, but we don't know if its old-style or new.
+	  ;; Fortunately we can ask emacs directly
+	  (if (fboundp 'forward-comment)
+	      (setq scanner 'v19)
+	    (setq scanner 'old-v19))))
+    ;; now cobble up the necessary list
+    (list mse-spec scanner))
+  "A list of needed features extant in the Emacs you are using.
+There are many flavors of Emacs out on the net, each with different
+features supporting those needed by c++-mode.  Here's the current
+known list, along with the values for this variable:
+
+Vanilla GNU 18/Epoch 4:  (no-dual-comments v18)
+GNU 18/Epoch 4 (patch1): (8-bit old-v19)
+GNU 18/Epoch 4 (patch2): (8-bit v19)
+Lemacs 19.4 - 19.7:      (8-bit old-v19)
+Lemacs 19.8 and over:    (8-bit v19)
+FSF 19:                  (1-bit v19)
+FSF 19 (patched):        (8-bit v19)")
+
+(defvar c++-mode-abbrev-table nil
+  "Abbrev table in use in c++-mode buffers.")
+(define-abbrev-table 'c++-mode-abbrev-table ())
+
+(defvar c++-mode-map ()
+  "Keymap used in c++-mode.")
+(if c++-mode-map
+    ()
+  (setq c++-mode-map (make-sparse-keymap))
+  (define-key c++-mode-map "\C-j"      'reindent-then-newline-and-indent)
+  (define-key c++-mode-map "\C-m"      'newline-and-indent)
+  (define-key c++-mode-map "{"         'c++-electric-brace)
+  (define-key c++-mode-map "}"         'c++-electric-brace)
+  (define-key c++-mode-map ";"         'c++-electric-semi)
+  (define-key c++-mode-map "#"         'c++-electric-pound)
+  (define-key c++-mode-map "\e\C-h"    'mark-c-function)
+  (define-key c++-mode-map "\e\C-q"    'c++-indent-exp)
+  (define-key c++-mode-map "\t"        'c++-indent-command)
+  (define-key c++-mode-map "\C-c\C-i"  'c++-insert-header)
+  (define-key c++-mode-map "\C-c\C-\\" 'c++-macroize-region)
+  (define-key c++-mode-map "\C-c\C-c"  'c++-comment-region)
+  (define-key c++-mode-map "\C-c\C-u"  'c++-uncomment-region)
+  (define-key c++-mode-map "\C-c\C-x"  'c++-match-paren)
+  (define-key c++-mode-map "\e\C-a"    'c++-beginning-of-defun)
+  (define-key c++-mode-map "\e\C-e"    'c++-end-of-defun)
+  (define-key c++-mode-map "\e\C-x"    'c++-indent-defun)
+  (define-key c++-mode-map "/"         'c++-electric-slash)
+  (define-key c++-mode-map "*"         'c++-electric-star)
+  (define-key c++-mode-map ":"         'c++-electric-colon)
+  (define-key c++-mode-map "\177"      'c++-electric-delete)
+  (define-key c++-mode-map "\C-c\C-t"  'c++-toggle-auto-hungry-state)
+  (define-key c++-mode-map "\C-c\C-h"  'c++-toggle-hungry-state)
+  (define-key c++-mode-map "\C-c\C-a"  'c++-toggle-auto-state)
+  (if (memq 'v18 c++-emacs-features)
+      (progn
+	(define-key c++-mode-map "\C-c'"     'c++-tame-comments)
+	(define-key c++-mode-map "'"         'c++-tame-insert)
+	(define-key c++-mode-map "["         'c++-tame-insert)
+	(define-key c++-mode-map "]"         'c++-tame-insert)
+	(define-key c++-mode-map "("         'c++-tame-insert)
+	(define-key c++-mode-map ")"         'c++-tame-insert)))
+  (define-key c++-mode-map "\C-c\C-b"  'c++-submit-bug-report)
+  (define-key c++-mode-map "\C-c\C-v"  'c++-version)
+  ;; these are necessary because default forward-sexp and
+  ;; backward-sexp don't automatically let-bind
+  ;; parse-sexp-ignore-comments, which is needed for them to work
+  ;; properly in a C++ buffer.
+  (define-key c++-mode-map "\e\C-f"    'c++-forward-sexp)
+  (define-key c++-mode-map "\e\C-b"    'c++-backward-sexp)
+  )
+
+(defvar c++-mode-syntax-table nil
+  "Syntax table used in c++-mode buffers.")
+(defvar c++-c-mode-syntax-table nil
+  "Syntax table used in c++-c-mode buffers.")
+
+(if c++-mode-syntax-table
+    ()
+  (setq c++-mode-syntax-table (make-syntax-table))
+  (modify-syntax-entry ?\\ "\\"    c++-mode-syntax-table)
+  (modify-syntax-entry ?+  "."     c++-mode-syntax-table)
+  (modify-syntax-entry ?-  "."     c++-mode-syntax-table)
+  (modify-syntax-entry ?=  "."     c++-mode-syntax-table)
+  (modify-syntax-entry ?%  "."     c++-mode-syntax-table)
+  (modify-syntax-entry ?<  "."     c++-mode-syntax-table)
+  (modify-syntax-entry ?>  "."     c++-mode-syntax-table)
+  (modify-syntax-entry ?&  "."     c++-mode-syntax-table)
+  (modify-syntax-entry ?|  "."     c++-mode-syntax-table)
+  (modify-syntax-entry ?\' "\""    c++-mode-syntax-table)
+  ;; comment syntax
+  (cond
+   ((memq '8-bit c++-emacs-features)
+    ;; Lucid emacs has the best implementation
+    (modify-syntax-entry ?/  ". 1456" c++-mode-syntax-table)
+    (modify-syntax-entry ?*  ". 23"   c++-mode-syntax-table)
+    (modify-syntax-entry ?\n "> b"    c++-mode-syntax-table))
+   ((memq '1-bit c++-emacs-features)
+    ;; FSF19 has sub-optimal, but workable implementation
+    ;; Some strange behavior may be encountered.  LOBBY FSF!
+    (modify-syntax-entry ?/  ". 124" c++-mode-syntax-table)
+    (modify-syntax-entry ?*  ". 23b" c++-mode-syntax-table)
+    (modify-syntax-entry ?\n ">"     c++-mode-syntax-table))
+   (t
+    ;; Vanilla GNU18 is just plain busted.  We'll do the best we can,
+    ;; but some strange behavior may be encountered.  PATCH or UPGRADE!
+    (modify-syntax-entry ?/  ". 124" c++-mode-syntax-table)
+    (modify-syntax-entry ?*  ". 23"  c++-mode-syntax-table)
+    (modify-syntax-entry ?\n ">"     c++-mode-syntax-table))
+   ))
+
+(if c++-c-mode-syntax-table
+    ()
+  (setq c++-c-mode-syntax-table (make-syntax-table))
+  (modify-syntax-entry ?\\ "\\"    c++-c-mode-syntax-table)
+  (modify-syntax-entry ?+  "."     c++-c-mode-syntax-table)
+  (modify-syntax-entry ?-  "."     c++-c-mode-syntax-table)
+  (modify-syntax-entry ?=  "."     c++-c-mode-syntax-table)
+  (modify-syntax-entry ?%  "."     c++-c-mode-syntax-table)
+  (modify-syntax-entry ?<  "."     c++-c-mode-syntax-table)
+  (modify-syntax-entry ?>  "."     c++-c-mode-syntax-table)
+  (modify-syntax-entry ?&  "."     c++-c-mode-syntax-table)
+  (modify-syntax-entry ?|  "."     c++-c-mode-syntax-table)
+  (modify-syntax-entry ?\' "\""    c++-c-mode-syntax-table)
+  (modify-syntax-entry ?/  ". 14"  c++-c-mode-syntax-table)
+  (modify-syntax-entry ?*  ". 23"  c++-c-mode-syntax-table)
+  )
+
+(defvar c++-tab-always-indent
+  (if (boundp 'c-tab-always-indent) c-tab-always-indent t)
+  "*Controls the operation of the TAB key.
+If t (the default), always just indent the current line.  If nil,
+indent the current line only if point is at the left margin or in the
+line's indentation; otherwise insert a tab.  If not-nil-or-t, then tab
+is inserted only within literals (comments and strings) and inside
+preprocessor directives, but line is always reindented.")
+(defvar c++-always-arglist-indent-p nil
+  "*Control indentation of continued arglists.
+When non-nil, arglists continued on subsequent lines will always
+indent `c++-empty-arglist-indent' spaces, otherwise, they will indent to
+just under previous line's argument indentation.")
+(defvar c++-block-close-brace-offset 0
+  "*Extra indentation given to close braces which close a block.
+This variable can be either an integer or a list.  If an integer, it
+describes the extra offset given a block closing brace (and a closing
+paren if `c++-paren-as-block-close-p' is non-nil), treating all
+closing parens the same.  If a list of the form (OTHERS . TOPLEVEL),
+OTHERS is an integer describing the offset given to all but top-level
+(e.g. function) closing braces, while TOPLEVEL is an integer
+describing offset given only to braces which close top-level
+constructs.")
+(defvar c++-paren-as-block-close-p nil
+  "*Treat a parenthesis which is the first non-whitespace on a line as
+a paren which closes a block.  When non-nil, `c-indent-level' is
+subtracted, and `c++-block-close-brace-offset' is added to the line's
+offset.")
+(defvar c++-continued-member-init-offset nil
+  "*Extra indent for continuation lines of member inits; nil means to align
+with previous initializations rather than with the colon on the first line.")
+(defvar c++-member-init-indent 0
+  "*Indentation level of member initializations in function declarations.")
+(defvar c++-friend-offset -4
+  "*Offset of C++ friend class declarations relative to member declarations.")
+(defvar c++-access-specifier-offset c-label-offset
+  "*Extra indentation given to public, protected, and private labels.")
+(defvar c++-empty-arglist-indent nil
+  "*Indicates how far to indent a line following an empty argument list.
+Nil means indent to just after the paren.")
+(defvar c++-comment-only-line-offset 0
+  "*Indentation offset for line which contains only C or C++ style comments.
+This variable can take either a single integer or a list of integers.
+If a single integer this is the extra indentation offset to apply to
+all comment-only lines, except those which start in column zero.  If a
+list is used, the first integer is for all non-column-zero
+comment-only lines and the second integer is for all column-zero
+lines.  You can also use a list containing only 1 integer, in which
+case, this value is used for all comment-only lines.  For example:
+
+value     meaning
+=====     =======
+  0       comment-only lines do not indent
+  4       non-col0 lines indent 4 spaces, col0 lines don't indent
+'(4)      all comment-only lines indent 4 spaces
+'(4 1)    non-col0 lines indent 4 spaces, col0 lines indent 1 space")
+
+(defvar c++-C-block-comments-indent-p nil
+  "*4 styles of C block comments are supported.  If this variable is nil,
+then styles 1-3 are supported.  If this variable is non-nil, style 4 is
+supported.
+style 1:       style 2:       style 3:       style 4:
+/*             /*             /*             /*
+   blah         * blah        ** blah        blah
+   blah         * blah        ** blah        blah
+   */           */            */             */
+")
+(defvar c++-cleanup-list nil
+  "*List of various C++ constructs to ``clean up''.
+These cleanups only take place when the auto-newline feature is turned
+on, as evidenced by the `/a' or `/ah' appearing next to the mode name.
+
+Current legal values are:
+ `brace-else-brace'   -- clean up ``} else {'' constructs by placing entire
+                         construct on a single line.  This cleanup only
+                         takes place when there is nothing but white
+                         space between the braces and the else.  
+ `empty-defun-braces' -- cleans up empty C++ function braces by
+                         placing them on the same line.
+ `defun-close-semi'   -- cleans up the terminating semi-colon on class
+                         definitions and functions by placing the semi
+                         on the same line as the closing brace.")
+(defvar c++-hanging-braces t
+  "*Controls the insertion of newlines before open (left) braces.
+This variable only has effect when auto-newline is on, as evidenced by
+the `/a' or `/ah' appearing next to the mode name.  If nil, open
+braces do not hang (i.e. a newline is inserted before all open
+braces).  If t, all open braces hang -- no newline is inserted before
+open braces.  If not nil or t, newlines are only inserted before
+top-level open braces; all other braces hang.")
+(defvar c++-hanging-member-init-colon 'before
+  "*Defines how colons which introduce member initializations are formatted.
+Legal values are:
+  t        -- no newlines inserted before or after colon
+  nil      -- newlines inserted before and after colon
+  `after'  -- newlines inserted only after colon
+  `before` -- newlines inserted only before colon")
+(defvar c++-auto-hungry-initial-state 'none
+  "*Initial state of auto/hungry features when buffer is first visited.
+Legal values are:
+  `none'         -- no auto-newline and no hungry-delete-key.
+  `auto-only'    -- auto-newline, but no hungry-delete-key.
+  `hungry-only'  -- no auto-newline, but hungry-delete-key.
+  `auto-hungry'  -- both auto-newline and hungry-delete-key enabled.
+Nil is synonymous for `none' and t is synonymous for `auto-hungry'.")
+
+(defvar c++-auto-hungry-toggle t
+  "*Enable/disable toggling of auto/hungry features.
+Legal values are:
+  `none'         -- auto-newline and hungry-delete-key cannot be enabled.
+  `auto-only'    -- only auto-newline feature can be toggled.
+  `hungry-only'  -- only hungry-delete-key feature can be toggled.
+  `auto-hungry'  -- both auto-newline and hungry-delete-key can be toggled.
+Nil is synonymous for `none' and t is synonymous for `auto-hungry'.")
+
+(defvar c++-relative-offset-p t
+  "*Control the calculation for indentation.
+When non-nil (the default), indentation is calculated relative to the
+first statement in the block.  When nil, the indentation is calculated
+without regard to how the first statement is indented.")
+
+(defvar c++-untame-characters (and (memq 'v18 c++-emacs-features) '(?\'))
+  "*Utilize a backslashing workaround of an Emacs syntax parsing bug.
+If non-nil, this variable should contain a list of characters which
+will be prepended by a backslash in comment regions.  By default, the
+list contains only the most troublesome character, the single quote.
+To be completely safe, set this variable to:
+
+    '(?\( ?\) ?\' ?\{ ?\} ?\[ ?\])
+
+This is the full list of characters which can potentially cause
+problems if they exist unbalanced within comments.  Setting this
+variable to nil will defeat this feature, but be forewarned!  Such
+un-escaped characters in comment regions can potentially break many
+things such as some indenting and blinking of parenthesis.
+
+Note further that only the default set of characters will be escaped
+automatically as they are typed.  But, executing `c++-tame-comments'
+(\\[c++-tame-comments]) will escape all characters which are members
+of this set, and which are found in comments throughout the file.
+
+Finally, c++-mode can tell if you're running a patched Emacs.  If so,
+taming characters isn't necessary and this variable is automatically
+set to nil.")
+
+(defvar c++-default-macroize-column 78
+  "*Column to insert backslashes.")
+(defvar c++-special-indent-hook nil
+  "*Hook for user defined special indentation adjustments.
+This hook gets called after a line is indented by the mode.  By
+supplying a hook, you can make adjustments to the line's standard
+indentation.  If you do use this hook, you will likely need to also
+set `c++-relative-offset-p' to nil.  The call to this hook is wrapped in
+a `save-excursion' so you don't need to worry about restoring point and
+mark inside the hook function.")
+(defvar c++-delete-function 'backward-delete-char-untabify
+  "*Function called by `c++-electric-delete' when deleting a single char.")
+(defvar c++-electric-pound-behavior nil
+  "*List of behaviors for electric pound insertion.
+Only currently supported behavior is `alignleft'.")
+(defvar c++-backscan-limit 2000
+  "*Limit in characters for looking back while skipping syntactic ws.
+If you typically write really big methods, and start noticing
+incorrect indentations, try cranking this value up.  The larger this
+value is, though, the slower parts of c++-mode can become.  Setting
+this variable to nil defeats backscan limits.")
+
+;; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+;; NO USER DEFINABLE VARIABLES BEYOND THIS POINT
+;; 
+(defvar c++-hungry-delete-key nil
+  "Internal state of hungry delete key feature.")
+(defvar c++-auto-newline nil
+  "Internal state of auto newline feature.")
+
+(make-variable-buffer-local 'c++-auto-newline)
+(make-variable-buffer-local 'c++-hungry-delete-key)
+
+(defconst c++-access-key "\\<\\(public\\|protected\\|private\\)\\>:"
+  "Regexp which describes access specification keywords.")
+(defconst c++-class-key
+  (concat
+   "\\(\\(extern\\|typedef\\)\\s +\\)?"
+   "\\(template\\s *<[^>]*>\\s *\\)?"
+   "\\<\\(class\\|struct\\|union\\)\\>")
+  "Regexp which describes a class declaration, including templates.")
+(defconst c++-inher-key
+  (concat "\\(\\<static\\>\\s +\\)?"
+	  c++-class-key
+	  "[ \t]+\\(\\(\\w\\|_\\)+[ \t]*:[ \t]*\\)?")
+  "Regexp which describes a class inheritance declaration.")
+
+
+;; ======================================================================
+;; c++-mode main entry point
+;; ======================================================================
+;;##autoload ;; don't autoload an obsolete package
+(defun c++-mode ()
+  "Major mode for editing C++ code.  2.353
+To submit a problem report, enter `\\[c++-submit-bug-report]' from a
+c++-mode buffer.  This automatically sets up a mail buffer with
+version information already added.  You just need to add a description
+of the problem and send the message.
+
+1. Very much like editing C code,
+2. Expression and list commands understand all C++ brackets,
+3. Tab at left margin indents for C++ code,
+4. Both C++ and C style block comments are recognized,
+5. Paragraphs are separated by blank lines only,
+6. Hungry delete key and auto newline features are optional.
+
+IMPORTANT NOTE: You may notice that some characters (by default, only
+single quote) will get escaped with a backslash when typed in a
+comment region.  This is a necessary workaround of a bug present in
+GNU Emacs 18 and derivatives.  Enter `\\[describe-variable] c++-untame-characters RET'
+for more information.  If you are running a patched Emacs, no
+characters will be escaped in comment regions, and many functions will
+run much faster.
+
+Key bindings:
+\\{c++-mode-map}
+
+These variables control indentation style.  Those with names like
+c-<thing> are inherited from c-mode.  Those with names like
+c++-<thing> are unique for this mode, or have extended functionality
+from their c-mode cousins.
+
+ c-argdecl-indent
+    Indentation level of declarations of C function arguments.
+ c-brace-imaginary-offset
+    An open brace following other text is treated as if it were
+    this far to the right of the start of its line.
+ c-brace-offset
+    Extra indentation for line if it starts with an open brace.
+ c-continued-brace-offset
+    Extra indentation given to a brace that starts a substatement.
+    This is in addition to `c-continued-statement-offset'.
+ c-continued-statement-offset
+    Extra indentation given to a substatement, such as the
+    then-clause of an if or body of a while.
+ c-indent-level
+    Indentation of C statements within surrounding block.
+    The surrounding block's indentation is the indentation
+    of the line on which the open-brace appears.
+ c-label-offset
+    Extra indentation for line that is a label, or case or ``default:''
+
+ c++-C-block-comments-indent-p
+    Style of C block comments to support.
+ c++-access-specifier-offset
+    Extra indentation given to public, protected, and private keyword lines.
+ c++-always-arglist-indent-p
+    Control indentation of continued arglists.  When non-nil, arglists
+    continued on subsequent lines will always indent
+    `c++-empty-arglist-indent' spaces, otherwise, they will indent to
+    just under previous line's argument indentation.
+ c++-auto-hungry-initial-state
+    Initial state of auto/hungry feature when a C++ buffer is first visited.
+ c++-auto-hungry-toggle
+    Enable/disable toggling of auto/hungry features.
+ c++-backscan-limit
+    Limit in characters for looking back while skipping syntactic
+    whitespace.  This variable is only used in an un-patched Emacs to
+    help improve performance at the expense of some accuracy.  Patched
+    Emacses are both fast and accurate.
+ c++-block-close-brace-offset
+    Extra indentation give to braces which close a block.
+ c++-cleanup-list
+    A list of construct ``clean ups'' which c++-mode will perform when
+    auto-newline feature is on.  Current legal values are:
+    `brace-else-brace', `empty-defun-braces', `defun-close-semi'.
+ c++-comment-only-line-offset
+    Extra indentation for a line containing only a C or C++ style
+    comment.  Can be an integer or list, specifying the various styles
+    of comment-only line special indentations.
+ c++-continued-member-init-offset
+    Extra indentation for continuation lines of member initializations; nil
+    means to align with previous initializations rather than with the colon.
+ c++-default-macroize-column
+    Column to insert backslashes when macroizing a region.
+ c++-delete-function
+    Function called by `c++-electric-delete' when deleting a single char.
+ c++-electric-pound-behavior
+    List of behaviors for electric pound insertion.
+ c++-empty-arglist-indent
+    Extra indentation to apply to a line following an empty argument
+    list.  nil means to line it up with the left paren.
+ c++-friend-offset
+    Offset of C++ friend class declarations relative to member declarations.
+ c++-hanging-braces
+    Controls open brace hanging behavior when using auto-newline feature.
+    nil says no braces hang, t says all open braces hang.  non-nil-or-t
+    means top-level open braces don't hang, all others do.
+ c++-hanging-member-init-colon
+    Defines how colons which introduce member initialization lists are
+    formatted.  t means no newlines are inserted either before or after
+    the colon.  nil means newlines are inserted both before and after
+    the colon.  `before' inserts newlines only before the colon, and
+    `after' inserts newlines only after colon.
+ c++-member-init-indent
+    Indentation level of member initializations in function declarations,
+    if they are on a separate line beginning with a colon.
+ c++-paren-as-block-close-p
+    If non-nil, treat a parenthesis which is the first non-whitespace
+    on a line as a paren which closes a block (i.e. treat it similar
+    to right curly brace).
+ c++-relative-offset-p
+    Control the calculation for indentation.  When non-nil (the
+    default), indentation is calculated relative to the first
+    statement in the block.  When nil, the indentation is calculated
+    without regard to how the first statement is indented.  Useful when
+    using a `c++-special-indent-hook'.
+ c++-special-indent-hook
+    Hook for user defined special indentation adjustments.  You can use
+    this hook, which gets called after a line is indented by the mode,
+    to customize indentations of the line.
+ c++-tab-always-indent
+    Controls the operation of the TAB key.  t means always just indent
+    the current line.  nil means indent the current line only if point
+    is at the left margin or in the line's indentation; otherwise
+    insert a tab.  If not-nil-or-t, then tab is inserted only within
+    literals (comments and strings) and inside preprocessor
+    directives, but the line is always reindented.  Default is value
+    for `c-tab-always-indent'.
+ c++-untame-characters
+    When non-nil, inserts backslash escapes before certain untamed
+    characters in comment regions.  It is recommended that you keep the
+    default setting to workaround a nasty Emacs bug, unless you are
+    running a patched Emacs.
+
+Auto-newlining is no longer an all or nothing proposition.  In my
+opinion, I don't believe it is possible to implement a perfect
+auto-newline algorithm.  Sometimes you want it and sometimes you don't.
+So now auto-newline (and its companion feature, hungry-delete-key) can
+be toggled on and off on the fly.  Hungry-delete-key is the optional
+behavior of the delete key so that, when enabled, hitting the delete
+key once consumes all preceding whitespace, unless point is within a
+literal (defined as a C or C++ comment, or string).  Inside literals,
+and with hungry-delete-key disabled, the delete key just calls the
+function in variable `c++-delete-function'.
+
+Selection and toggling of these features is controlled by the
+variables `c++-auto-hungry-initial-state' and `c++-auto-hungry-toggle'.
+Legal values for both variables are:
+
+  `none' (or nil)      -- no auto-newline or hungry-delete-key.
+  `auto-only'          -- function affects only auto-newline feature.
+  `hungry-only'        -- function affects only hungry-delete-key feature.
+  `auto-hungry' (or t) -- function affects both features.
+
+Thus if `c++-auto-hungry-initial-state' is `hungry-only', then only
+hungry-delete-key feature is turned on when the buffer is first
+visited.  If `c++-auto-hungry-toggle' is `auto-hungry', and both
+auto-newline and hungry-delete-key features are on, then hitting
+`\\[c++-toggle-auto-hungry-state]' will toggle both features.  Hitting
+`\\[c++-toggle-hungry-state]' will always toggle hungry-delete-key
+feature and hitting `\\[c++-toggle-auto-state]' will always toggle
+auto-newline feature, regardless of the value of
+`c++-auto-hungry-toggle'.
+
+Settings for K&R, BSD, and Stroustrup indentation styles are
+  c-indent-level                5    8    4
+  c-continued-statement-offset  5    8    4
+  c-continued-brace-offset                0
+  c-brace-offset               -5   -8    0
+  c-brace-imaginary-offset                0
+  c-argdecl-indent              0    8    4
+  c-label-offset               -5   -8   -4
+  c++-access-specifier-offset  -5   -8   -4
+  c++-empty-arglist-indent                4
+  c++-friend-offset                       0
+
+Turning on C++ mode calls the value of the variable `c++-mode-hook' with
+no args, if that value is non-nil."
+  (interactive)
+  (kill-all-local-variables)
+  (use-local-map c++-mode-map)
+  (set-syntax-table c++-mode-syntax-table)
+  (setq major-mode 'c++-mode
+	mode-name "C++"
+	local-abbrev-table c++-mode-abbrev-table)
+  (set (make-local-variable 'paragraph-start) (concat "^$\\|" page-delimiter))
+  (set (make-local-variable 'paragraph-separate) paragraph-start)
+  (set (make-local-variable 'paragraph-ignore-fill-prefix) t)
+  (set (make-local-variable 'require-final-newline) t)
+  (set (make-local-variable 'parse-sexp-ignore-comments) nil)
+  ;; 
+  (set (make-local-variable 'indent-line-function) 'c++-indent-line)
+  (set (make-local-variable 'comment-start) "// ")
+  (set (make-local-variable 'comment-end) "")
+  (set (make-local-variable 'comment-column) 32)
+  (set (make-local-variable 'comment-start-skip) "/\\*+ *\\|// *")
+  (set (make-local-variable 'comment-indent-hook) 'c++-comment-indent)
+  ;; hack auto-hungry designators into modeline-format
+  (if (listp modeline-format)
+      (setq modeline-format
+	    (let ((modeline nil))
+	      (mapcar
+	       (function
+		(lambda (element)
+		  (setq modeline
+			(append modeline
+				(if (eq element 'mode-name)
+				    '(mode-name (c++-hungry-delete-key
+						 (c++-auto-newline "/ah" "/h")
+						 (c++-auto-newline "/a")))
+				  (list element))))))
+	       modeline-format)
+	      modeline)))
+  (run-hooks 'c++-mode-hook)
+  (c++-set-auto-hungry-state
+   (memq c++-auto-hungry-initial-state '(auto-only   auto-hungry t))
+   (memq c++-auto-hungry-initial-state '(hungry-only auto-hungry t))))
+
+;;##autoload ;; don't autoload an obsolete package
+(defun c++-c-mode ()
+  "Major mode for editing K&R and ANSI C code.  2.353
+This mode is based on c++-mode.  Documentation for this mode is
+available by doing a `\\[describe-function] c++-mode'."
+  (interactive)
+  (c++-mode)
+  (setq major-mode 'c++-c-mode
+	mode-name "C"
+	local-abbrev-table c-mode-abbrev-table)
+  (setq comment-start "/* "
+	comment-end   " */")
+  ;; some syntax differences are necessary for C vs. C++
+  (set-syntax-table c++-c-mode-syntax-table)
+  (run-hooks 'c++-c-mode-hook))
+
+(defun c++-comment-indent ()
+  "Used by `indent-for-comment' to decide how much to indent a comment
+in C++ code based on its context."
+  (if (looking-at "^\\(/\\*\\|//\\)")
+      0					; Existing comment at bol stays there.
+    (save-excursion
+      (skip-chars-backward " \t")
+      (max
+       ;; leave at least one space on non-empty lines.
+       (if (zerop (current-column))
+	   0
+	 (1+ (current-column)))
+       ;; use comment-column if previous line is comment only line
+       ;; indented to the left of comment-column
+       (save-excursion
+	 (beginning-of-line)
+	 (if (not (bobp)) (forward-line -1))
+	 (skip-chars-forward " \t")
+	 (if (looking-at "/\\*\\|//")
+	     (if (< (current-column) comment-column)
+		 comment-column
+	       (current-column))
+	   0))
+       (let ((cur-pt (point)))
+	 (beginning-of-line 0)
+	 ;; If previous line had a comment, use it's indent
+	 (if (re-search-forward comment-start-skip cur-pt t)
+	     (progn
+	       (goto-char (match-beginning 0))
+	       (current-column))
+	   comment-column))))))		; otherwise indent at comment column.
+
+
+;; ======================================================================
+;; most command level (interactive) and related
+;; ======================================================================
+(defun c++-set-auto-hungry-state (auto-p hungry-p)
+  "Set auto/hungry to state indicated by AUTO-P and HUNGRY-P.
+Update modeline to indicate state to user."
+  (setq c++-auto-newline auto-p
+	c++-hungry-delete-key hungry-p)
+  (set-buffer-modified-p (buffer-modified-p)))
+
+(defun c++-toggle-auto-state (arg)
+  "Toggle auto-newline feature.
+This function ignores `c++-auto-hungry-toggle' variable.  Optional
+numeric ARG, if supplied turns on auto-newline when positive, turns
+off auto-newline when negative and toggles when zero."
+  (interactive "P")
+  (let ((auto (cond
+	       ((not arg)
+		(not c++-auto-newline))
+	       ((zerop (setq arg (prefix-numeric-value arg)))
+		(not c++-auto-newline))
+	       ((< arg 0) nil)
+	       (t t))))
+    (c++-set-auto-hungry-state auto c++-hungry-delete-key)))
+
+(defun c++-toggle-hungry-state (arg)
+  "Toggle hungry-delete-key feature.
+This function ignores `c++-auto-hungry-toggle' variable.  Optional
+numeric ARG, if supplied turns on hungry-delete-key when positive,
+turns off hungry-delete-key when negative and toggles when zero."
+  (interactive "P")
+  (let ((hungry (cond
+		 ((not arg)
+		  (not c++-hungry-delete-key))
+		 ((zerop (setq arg (prefix-numeric-value arg)))
+		  (not c++-hungry-delete-key))
+		 ((< arg 0) nil)
+		 (t t))))
+    (c++-set-auto-hungry-state c++-auto-newline hungry)))
+
+(defun c++-toggle-auto-hungry-state (arg)
+  "Toggle auto-newline and hungry-delete-key features.
+Actual toggling of these features is controlled by
+`c++-auto-hungry-toggle' variable.
+
+Optional argument has the following meanings when supplied:
+  Universal argument \\[universal-argument]
+        resets features to c++-auto-hungry-initial-state.
+  negative number
+        turn off both auto-newline and hungry-delete-key features.
+  positive number
+        turn on both auto-newline and hungry-delete-key features.
+  zero
+        toggle both features regardless of `c++-auto-hungry-toggle-p'."
+  (interactive "P")
+  (let* ((numarg (prefix-numeric-value arg))
+	 (apl (list 'auto-only   'auto-hungry t))
+	 (hpl (list 'hungry-only 'auto-hungry t))
+	 (auto (cond
+		((not arg)
+		 (if (memq c++-auto-hungry-toggle apl)
+		     (not c++-auto-newline)
+		   c++-auto-newline))
+		((listp arg)
+		 (memq c++-auto-hungry-initial-state apl))
+		((zerop numarg)
+		 (not c++-auto-newline))
+		((< arg 0) nil)
+		(t t)))
+	 (hungry (cond
+		  ((not arg)
+		   (if (memq c++-auto-hungry-toggle hpl)
+		       (not c++-hungry-delete-key)
+		     c++-hungry-delete-key))
+		  ((listp arg)
+		   (memq c++-auto-hungry-initial-state hpl))
+		  ((zerop numarg)
+		   (not c++-hungry-delete-key))
+		  ((< arg 0) nil)
+		  (t t))))
+    (c++-set-auto-hungry-state auto hungry)))
+
+(defun c++-tame-insert (arg)
+  "Safely inserts certain troublesome characters in comment regions.
+Because of syntax bugs in Emacs, characters with string or parenthesis
+syntax must be escaped with a backslash or lots of things get messed
+up.  Unfortunately, setting `parse-sexp-ignore-comments' to non-nil does
+not fix the problem, but this function is unnecessary if you are
+running a patched Emacs.
+
+See also the variable `c++-untame-characters'."
+  (interactive "p")
+  (if (and (memq last-command-char c++-untame-characters)
+	   (memq (c++-in-literal) '(c c++)))
+      (insert "\\"))
+  (self-insert-command arg))
+
+(defun c++-electric-delete (arg)
+  "If `c++-hungry-delete-key' is non-nil, consumes all preceding
+whitespace unless ARG is supplied, or point is inside a C or C++ style
+comment or string.  If ARG is supplied, this just calls
+`backward-delete-char-untabify' passing along ARG.
+
+If `c++-hungry-delete-key' is nil, just call `backward-delete-char-untabify'."
+  (interactive "P")
+  (cond
+   ((or (not c++-hungry-delete-key) arg)
+    (funcall c++-delete-function (prefix-numeric-value arg)))
+   ((let ((bod (c++-point 'bod)))
+      (not (or (memq (c++-in-literal bod) '(c c++ string))
+	       (save-excursion
+		 (skip-chars-backward " \t")
+		 (= (preceding-char) ?#)))))
+    (let ((here (point)))
+      (skip-chars-backward " \t\n")
+      (if (/= (point) here)
+	  (delete-region (point) here)
+	(funcall c++-delete-function 1))))
+   (t (funcall c++-delete-function 1))))
+
+(defun c++-electric-pound (arg)
+  "Electric pound command."
+  (interactive "p")
+  (if (memq (c++-in-literal) '(c c++ string))
+      (self-insert-command arg)
+    (let ((here (point-marker))
+	  (bobp (bobp))
+	  (bolp (bolp)))
+      (if (memq 'alignleft c++-electric-pound-behavior)
+	  (progn (beginning-of-line)
+		 (delete-horizontal-space)))
+      (if bobp
+	  (insert (make-string arg last-command-char))
+	(insert-before-markers (make-string arg last-command-char)))
+      (if (not bolp)
+	  (goto-char here))
+      (set-marker here nil))))
+
+(defun c++-electric-brace (arg)
+  "Insert character and correct line's indentation."
+  (interactive "P")
+  (let (insertpos
+	(last-command-char last-command-char)
+	(bod (c++-point 'bod)))
+    (if (and (not arg)
+	     (save-excursion
+	       (skip-chars-forward " \t")
+	       (eolp))
+	     (or (save-excursion
+		   (skip-chars-backward " \t")
+		   (bolp))
+		 (let ((c++-auto-newline c++-auto-newline)
+		       (open-brace-p (= last-command-char ?{)))
+		   (if (and open-brace-p
+			    (or (eq c++-hanging-braces t)
+				(and c++-hanging-braces
+				     (not (c++-at-top-level-p t bod)))))
+		       (setq c++-auto-newline nil))
+		   (if (c++-auto-newline)
+		       ;; this may have auto-filled so we need to
+		       ;; indent the previous line. we also need to
+		       ;; indent the currently line, or
+		       ;; c++-beginning-of-defun will not be able to
+		       ;; correctly find the bod when
+		       ;; c++-match-headers-strongly is nil.
+		       (progn (c++-indent-line)
+			      (save-excursion
+				(forward-line -1)
+				(c++-indent-line))))
+		   t)))
+	(progn
+	  (if (and (memq last-command-char c++-untame-characters)
+		   (memq (c++-in-literal bod) '(c c++)))
+	      (insert "\\"))
+	  ;; we need to work around a bogus feature of Emacs where an
+	  ;; open brace at bolp means a beginning-of-defun.  but it
+	  ;; really might not.
+	  (and (= last-command-char ?{)
+	       (bolp)
+	       (c++-indent-line))
+	  (insert last-command-char)
+	  ;; try to clean up empty defun braces if conditions apply
+	  (let ((here (point-marker)))
+	    (and (memq 'empty-defun-braces c++-cleanup-list)
+		 (c++-at-top-level-p t bod)
+		 c++-auto-newline
+		 (= last-command-char ?\})
+		 (progn (forward-char -1)
+			(skip-chars-backward " \t\n")
+			(= (preceding-char) ?\{))
+		 (not (memq (c++-in-literal) '(c c++ string)))
+		 (delete-region (point) (1- here)))
+	    (goto-char here)
+	    (set-marker here nil))
+	  (let ((here (point-marker))
+		mbeg mend)
+	    (if (and (memq 'brace-else-brace c++-cleanup-list)
+		     (= last-command-char ?\{)
+		     (let ((status
+			    (re-search-backward "}[ \t\n]*else[ \t\n]*{"
+						nil t)))
+		       (setq mbeg (match-beginning 0)
+			     mend (match-end 0))
+		       status)
+		     (= mend here)
+		     (not (memq (c++-in-literal bod) '(c c++ string))))
+		(progn
+		  ;; we should clean up brace-else-brace syntax
+		  (delete-region mbeg mend)
+		  (insert-before-markers "} else {")
+		  (goto-char here)
+		  (set-marker here nil))
+	      (goto-char here)
+	      (set-marker here nil)))
+	  (c++-indent-line)
+	  (if (c++-auto-newline)
+	      (progn
+		;; c++-auto-newline may have done an auto-fill
+		(save-excursion
+		  (let ((here (point-marker)))
+		    (goto-char (- (point) 2))
+		    (c++-indent-line)
+		    (setq insertpos (- (goto-char here) 2))
+		    (set-marker here nil)))
+		(c++-indent-line)))
+	  (save-excursion
+	    (if insertpos (goto-char (1+ insertpos)))
+	    (delete-char -1))))
+    (if insertpos
+	(save-excursion
+	  (goto-char insertpos)
+	  (self-insert-command (prefix-numeric-value arg)))
+      (self-insert-command (prefix-numeric-value arg)))))
+
+(defun c++-electric-slash (arg)
+  "Insert slash, and if slash is second of a double-slash comment
+introducing construct, indent line as comment.  This only indents if
+we're on a comment-only line, otherwise use `indent-for-comment' (\\[indent-for-comment])."
+  (interactive "P")
+  (let ((here (point)) char)
+    (self-insert-command (prefix-numeric-value arg))
+    (and (setq char (char-after (1- here)))
+	 (= char ?/)
+	 (save-excursion
+	   (goto-char here)
+	   (c++-indent-line)))))
+
+(defun c++-electric-star (arg)
+  "Works with `c++-electric-slash' to auto indent C style comment lines."
+  (interactive "P")
+  (let ((here (point)) char)
+    (self-insert-command (prefix-numeric-value arg))
+    (if (and (setq char (char-after (1- here)))
+	     (memq (c++-in-literal) '(c))
+	     (memq char '(?/ ?* ?\t 32 ?\n))
+	     (save-excursion
+	       (skip-chars-backward "* \t")
+	       (if (= (preceding-char) ?/)
+		   (progn
+		     (forward-char -1)
+		     (skip-chars-backward " \t")))
+	       (bolp)))
+	(save-excursion
+	  (goto-char here)
+	  (c++-indent-line)))))
+
+(defun c++-electric-semi (arg)
+  "Insert character and correct line's indentation."
+  (interactive "P")
+  (if (c++-in-literal)
+      (self-insert-command (prefix-numeric-value arg))
+    (let ((here (point-marker)))
+      (if (and (memq 'defun-close-semi c++-cleanup-list)
+	       c++-auto-newline
+	       (progn
+		 (skip-chars-backward " \t\n")
+		 (= (preceding-char) ?})))
+	  (delete-region here (point)))
+      (goto-char here)
+      (set-marker here nil))
+    (c++-electric-terminator arg)))
+
+(defun c++-electric-colon (arg)
+  "Electrify colon.
+De-auto-newline double colons.  No auto-new-lines for member
+initialization list."
+  (interactive "P")
+  (if (c++-in-literal)
+      (self-insert-command (prefix-numeric-value arg))
+    (let ((c++-auto-newline c++-auto-newline)
+	  (insertion-point (point))
+	  (bod (c++-point 'bod)))
+      (save-excursion
+	(cond
+	 ;; check for double-colon where the first colon is not in a
+	 ;; comment or literal region
+	 ((progn (skip-chars-backward " \t\n")
+		 (and (= (preceding-char) ?:)
+		      (not (memq (c++-in-literal bod) '(c c++ string)))))
+	  (progn (delete-region insertion-point (point))
+		 (setq c++-auto-newline nil
+		       insertion-point (point))))
+	 ;; check for ?: construct which may be at any level
+	 ((progn (goto-char insertion-point)
+		 (condition-case premature-end
+		     (backward-sexp 1)
+		   (error nil))
+		 ;; is possible that the sexp we just skipped was a
+		 ;; negative number. in that case the minus won't be
+		 ;; gobbled
+		 (skip-chars-backward "-")
+		 (c++-backward-syntactic-ws bod)
+		 (= (preceding-char) ?\?))
+	  (setq c++-auto-newline nil))
+	 ;; check for being at top level or top with respect to the
+	 ;; class. if not, process as normal
+	 ((progn (goto-char insertion-point)
+		 (not (c++-at-top-level-p t bod))))
+	 ;; if at top level, check to see if we are introducing a member
+	 ;; init list. if not, continue
+	 ((progn (c++-backward-syntactic-ws bod)
+		 (= (preceding-char) ?\)))
+	  (goto-char insertion-point)
+	  ;; at a member init list, figure out about auto newlining. if
+	  ;; nil or before then put a newline before the colon and
+	  ;; adjust the insertion point, but *only* if there is no
+	  ;; newline already before the insertion point
+	  (if (and (memq c++-hanging-member-init-colon '(nil before))
+		   c++-auto-newline)
+	      (if (not (save-excursion (skip-chars-backward " \t")
+				       (bolp)))
+		  (let ((c++-auto-newline t))
+		    (c++-auto-newline)
+		    (setq insertion-point (point)))))
+	  ;; if hanging colon is after or nil, then newline is inserted
+	  ;; after colon. set up variable so c++-electric-terminator
+	  ;; places the newline correctly
+	  (setq c++-auto-newline
+		(and c++-auto-newline
+		     (memq c++-hanging-member-init-colon '(nil after)))))
+	 ;; last condition is always put newline after colon
+	 (t (setq c++-auto-newline nil))
+	 ))				; end-cond, end-save-excursion
+      (goto-char insertion-point)
+      (c++-electric-terminator arg))))
+
+(defun c++-electric-terminator (arg)
+  "Insert character and correct line's indentation."
+  (interactive "P")
+  (let (insertpos (end (point)))
+    (if (and (not arg)
+	     (save-excursion
+	       (skip-chars-forward " \t")
+	       (eolp))
+	     (not (save-excursion
+		    (beginning-of-line)
+		    (skip-chars-forward " \t")
+		    (or (= (following-char) ?#)
+			;; Colon is special only after a label, or
+			;; case, or another colon.
+			;; So quickly rule out most other uses of colon
+			;; and do no indentation for them.
+			(and (eq last-command-char ?:)
+			     (not (looking-at "case[ \t]"))
+			     (save-excursion
+			       (forward-word 1)
+			       (skip-chars-forward " \t")
+			       (< (point) end))
+			     ;; Do re-indent double colons
+			     (save-excursion
+			       (end-of-line 1)
+			       (looking-at ":")))
+			(progn
+			  (c++-beginning-of-defun)
+			  (let* ((parse-sexp-ignore-comments t)
+				 (pps (parse-partial-sexp (point) end)))
+			    (or (nth 3 pps) (nth 4 pps) (nth 5 pps))))))))
+	(progn
+	  (insert last-command-char)
+	  (c++-indent-line)
+	  (and c++-auto-newline
+	       (not (c++-in-parens-p))
+	       (progn
+		 ;; the new marker object, used to be just an integer
+		 (setq insertpos (make-marker))
+		 ;; changed setq to set-marker
+		 (set-marker insertpos (1- (point)))
+		 ;; do this before the newline, since in auto fill can break
+		 (newline)
+		 (c++-indent-line)))
+	  (save-excursion
+	    (if insertpos (goto-char (1+ insertpos)))
+	    (delete-char -1))))
+    (if insertpos
+	(save-excursion
+	  (goto-char insertpos)
+	  (self-insert-command (prefix-numeric-value arg)))
+      (self-insert-command (prefix-numeric-value arg)))))
+
+(defun c++-indent-command (&optional whole-exp)
+  "Indent current line as C++ code, or in some cases insert a tab character.
+
+If `c++-tab-always-indent' is t, always just indent the current line.
+If nil, indent the current line only if point is at the left margin or
+in the line's indentation; otherwise insert a tab.  If not-nil-or-t,
+then tab is inserted only within literals (comments and strings) and
+inside preprocessor directives, but line is always reindented.
+
+A numeric argument, regardless of its value, means indent rigidly all
+the lines of the expression starting after point so that this line
+becomes properly indented.  The relative indentation among the lines
+of the expression are preserved."
+  (interactive "P")
+  (let ((bod (c++-point 'bod)))
+    (if whole-exp
+	;; If arg, always indent this line as C
+	;; and shift remaining lines of expression the same amount.
+	(let ((shift-amt (c++-indent-line bod))
+	      beg end)
+	  (save-excursion
+	    (if (eq c++-tab-always-indent t)
+		(beginning-of-line))
+	    (setq beg (point))
+	    (forward-sexp 1)
+	    (setq end (point))
+	    (goto-char beg)
+	    (forward-line 1)
+	    (setq beg (point)))
+	  (if (> end beg)
+	      (indent-code-rigidly beg end shift-amt "#")))
+      (cond
+       ;; CASE 1: indent when at column zero or in lines indentation,
+       ;; otherwise insert a tab
+       ((not c++-tab-always-indent)
+	(if (and (save-excursion
+		   (skip-chars-backward " \t")
+		   (bolp))
+		 (or (looking-at "[ \t]*$")
+		     (/= (point) (c++-point 'boi))
+		     (bolp)))
+	    (c++-indent-line bod)
+	  (insert-tab)))
+       ;; CASE 2: just indent the line
+       ((eq c++-tab-always-indent t)
+	(c++-indent-line bod))
+       ;; CASE 3: if in a literal, insert a tab, but always indent the line
+       ((or (memq (c++-in-literal bod) '(c c++ string))
+	    (save-excursion
+	      (skip-chars-backward " \t")
+	      (= (preceding-char) ?#)))
+	(let ((here (point))
+	      (boi (save-excursion (back-to-indentation) (point)))
+	      (indent-p nil))
+	  (c++-indent-line bod)
+	  (save-excursion
+	    (back-to-indentation)
+	    (setq indent-p (and (> here boi) (= (point) boi))))
+	  (if indent-p (insert-tab))))
+       ;; CASE 4: bogus, just indent the line
+       (t (c++-indent-line bod))))))
+
+(defun c++-indent-exp ()
+  "Indent each line of the C++ grouping following point."
+  (interactive)
+  (let ((indent-stack (list nil))
+	(contain-stack (list (point)))
+	(case-fold-search nil)
+	restart outer-loop-done inner-loop-done state ostate
+	this-indent last-sexp last-depth
+	at-else at-brace
+	(parse-sexp-ignore-comments t)
+	(opoint (point))
+	(next-depth 0))
+    (save-excursion
+      (forward-sexp 1))
+    (save-excursion
+      (setq outer-loop-done nil)
+      (while (and (not (eobp)) (not outer-loop-done))
+	(setq last-depth next-depth)
+	;; Compute how depth changes over this line
+	;; plus enough other lines to get to one that
+	;; does not end inside a comment or string.
+	;; Meanwhile, do appropriate indentation on comment lines.
+	(setq inner-loop-done nil)
+	(while (and (not inner-loop-done)
+		    (not (and (eobp) (setq outer-loop-done t))))
+	  (setq ostate state)
+	  ;; fix by reed@adapt.net.com
+	  ;; must pass in the return past the end of line, so that
+	  ;; parse-partial-sexp finds it, and recognizes that a "//"
+	  ;; comment is over. otherwise, state is set that we're in a
+	  ;; comment, and never gets unset, causing outer-loop to only
+	  ;; terminate in (eobp). old:
+	  ;;(setq state (parse-partial-sexp (point)
+	  ;;(progn (end-of-line) (point))
+	  ;;nil nil state))
+	  (let ((start (point))
+		(line-end
+		 (progn (end-of-line)
+			(while (eq (c++-in-literal) 'c)
+			  (forward-line 1)
+			  (c++-indent-line)
+			  (end-of-line))
+			(skip-chars-backward " \t")
+			(end-of-line)
+			(point)))
+		(end (progn (if (not (eobp)) (forward-char)) (point))))
+	    (setq state (parse-partial-sexp start end nil nil state))
+	    (goto-char line-end))
+	  (setq next-depth (car state))
+	  (if (and (car (cdr (cdr state)))
+		   (>= (car (cdr (cdr state))) 0))
+	      (setq last-sexp (car (cdr (cdr state)))))
+	  (if (or (nth 4 ostate))
+	      (c++-indent-line))
+	  (if (or (nth 3 state))
+	      (forward-line 1)
+	    (setq inner-loop-done t)))
+	(if (<= next-depth 0)
+	    (setq outer-loop-done t))
+	(if outer-loop-done
+	    nil
+	  ;; If this line had ..))) (((.. in it, pop out of the levels
+	  ;; that ended anywhere in this line, even if the final depth
+	  ;; doesn't indicate that they ended.
+	  (while (> last-depth (nth 6 state))
+	    (setq indent-stack (cdr indent-stack)
+		  contain-stack (cdr contain-stack)
+		  last-depth (1- last-depth)))
+	  (if (/= last-depth next-depth)
+	      (setq last-sexp nil))
+	  ;; Add levels for any parens that were started in this line.
+	  (while (< last-depth next-depth)
+	    (setq indent-stack (cons nil indent-stack)
+		  contain-stack (cons nil contain-stack)
+		  last-depth (1+ last-depth)))
+	  (if (null (car contain-stack))
+	      (setcar contain-stack (or (car (cdr state))
+					(save-excursion (forward-sexp -1)
+							(point)))))
+	  (forward-line 1)
+	  (skip-chars-forward " \t")
+	  ;; check for C comment block
+	  (if (memq (c++-in-literal) '(c))
+	      (let ((eoc (save-excursion
+			   (re-search-forward "\\*/" (point-max) 'move)
+			   (point))))
+		(while (< (point) eoc)
+		  (c++-indent-line)
+		  (forward-line 1))))
+	  (if (eolp)
+	      nil
+	    (if (and (car indent-stack)
+		     (>= (car indent-stack) 0))
+		;; Line is on an existing nesting level.
+		;; Lines inside parens are handled specially.
+		(if (or (/= (char-after (car contain-stack)) ?{)
+			;;(c++-at-top-level-p t))
+			;; baw hack for continued statement offsets
+			;; repercussions???
+			t)
+		    (setq this-indent (car indent-stack))
+		  ;; Line is at statement level.
+		  ;; Is it a new statement?  Is it an else?
+		  ;; Find last non-comment character before this line
+		  (save-excursion
+		    (setq at-else (looking-at "else\\W"))
+		    (setq at-brace (= (following-char) ?{))
+		    (c++-backward-syntactic-ws opoint)
+		    (if (not (memq (preceding-char) '(nil ?\, ?\; ?} ?: ?{)))
+			;; Preceding line did not end in comma or semi;
+			;; indent this line  c-continued-statement-offset
+			;; more than previous.
+			(progn
+			  (c-backward-to-start-of-continued-exp
+			   (car contain-stack))
+			  (setq this-indent
+				(+ c-continued-statement-offset
+				   (current-column)
+				   (if at-brace c-continued-brace-offset 0))))
+		      ;; Preceding line ended in comma or semi;
+		      ;; use the standard indent for this level.
+		      (if at-else
+			  (progn (c++-backward-to-start-of-if opoint)
+				 (back-to-indentation)
+				 (skip-chars-forward "{ \t")
+				 (setq this-indent (current-column)))
+			(setq this-indent (car indent-stack))))))
+	      ;; Just started a new nesting level.
+	      ;; Compute the standard indent for this level.
+	      (let ((val (c++-calculate-indent
+			  (if (car indent-stack)
+			      (- (car indent-stack))))))
+		(setcar indent-stack
+			(setq this-indent val))))
+	    ;; Adjust line indentation according to its contents
+	    (cond
+	     ;; looking at public, protected, private line
+	     ((looking-at c++-access-key)
+	      (setq this-indent (+ this-indent c++-access-specifier-offset)))
+	     ;; looking at a case, default, or other label
+	     ((or (looking-at "\\(case[ \t]+.*\\|default[ \t]*\\):")
+		  (and (looking-at "[A-Za-z]")
+		       (save-excursion
+			 (forward-sexp 1)
+			 (looking-at ":[^:]"))))
+	      (setq this-indent (max 0 (+ this-indent c-label-offset))))
+	     ;; looking at a comment only line?
+	     ((looking-at comment-start-skip)
+	      ;; different indentation base on whether this is a col0
+	      ;; comment only line or not. also, if comment is in, or
+	      ;; to the right of comment-column, the comment doesn't
+	      ;; move
+	      (progn
+		(skip-chars-forward " \t")
+		(setq this-indent
+		      (if (>= (current-column) comment-column)
+			  (current-column)
+			(c++-comment-offset
+			 (bolp)
+			 (+ this-indent
+			    (if (save-excursion
+				  (c++-backward-syntactic-ws
+				   (car contain-stack))
+				  (memq (preceding-char)
+					'(nil ?\, ?\; ?} ?: ?{)))
+				0 c-continued-statement-offset))
+			 )))))
+	     ;; looking at a friend declaration
+	     ((looking-at "friend[ \t]")
+	      (setq this-indent (+ this-indent c++-friend-offset)))
+	     ;; looking at a close brace
+	     ((= (following-char) ?})
+	      (setq this-indent (- this-indent c-indent-level)))
+	     ;; looking at an open brace
+	     ((= (following-char) ?{)
+	      (setq this-indent
+		    (+ this-indent c-brace-offset
+		       (if (c++-at-top-level-p t (car contain-stack))
+			   0 c-indent-level))))
+	     ;; check for continued statements
+	     ((save-excursion
+		(c++-backward-syntactic-ws (car contain-stack))
+		(and (not (c++-in-parens-p))
+		     (not (memq (preceding-char) '(nil ?\000 ?\; ?\} ?\: ?\{)))
+		     (progn
+		       (beginning-of-line)
+		       (skip-chars-forward " \t")
+		       (not (looking-at c++-class-key)))))
+	      (setq this-indent
+		    (+ this-indent
+		       c-continued-statement-offset
+		       ;; are we in a member init list?
+		       (if (not (looking-at "[ \t]*:"))
+			   (save-excursion
+			     (let ((lim (car contain-stack)))
+			       (c++-backward-syntactic-ws lim)
+			       (while (and (< lim (point))
+					   (= (preceding-char) ?,))
+				 (beginning-of-line)
+				 (c++-backward-syntactic-ws))
+			       (forward-line 1)
+			       (beginning-of-line)
+			       (if (looking-at "[ \t]*:")
+				   (- (save-excursion
+					(skip-chars-forward " \t")
+					(point))
+				      (point))
+				 0)))
+			 0)
+		       )))
+	     ;; check for stream operator
+	     ((looking-at "\\(<<\\|>>\\)")
+	      (setq this-indent (c++-calculate-indent)))
+	     ) ;; end-cond
+	    ;; Put chosen indentation into effect.
+	    (or (= (current-column) this-indent)
+		(= (following-char) ?\#)
+		(progn
+		  (delete-region (point) (progn (beginning-of-line) (point)))
+		  (indent-to this-indent)))
+	    ;; Indent any comment following the text.
+	    (or (looking-at comment-start-skip)
+		(if (re-search-forward
+		     comment-start-skip
+		     (c++-point 'eol) t)
+		    (progn (indent-for-comment)
+			   (beginning-of-line))))
+	    ))))))
+
+(defun c++-insert-header ()
+  "Insert header denoting C++ code at top of buffer."
+  (interactive)
+  (save-excursion
+    (goto-char (point-min))
+    (insert "// "
+	    "This may look like C code, but it is really "
+	    "-*- C++ -*-"
+	    "\n\n")))
+
+(defun c++-tame-comments ()
+  "Backslashifies all untamed in comment regions found in the buffer.
+This is a workaround for Emacs syntax bugs.  This function is
+unnecessary (and un-used automatically) if you are running a patched
+Emacs.  Untamed characters to escape are defined in the variable
+`c++-untame-characters'."
+  (interactive)
+  ;; make the list into a valid charset, escaping where necessary
+  (let ((charset (concat "^" (mapconcat
+			      (function
+			       (lambda (char)
+				 (if (memq char '(?\\ ?^ ?-))
+				     (concat "\\" (char-to-string char))
+				   (char-to-string char))))
+			      c++-untame-characters ""))))
+    (save-excursion
+      (beginning-of-buffer)
+      (while (not (eobp))
+	(skip-chars-forward charset)
+	(if (and (not (zerop (following-char)))
+		 (memq (c++-in-literal) '(c c++))
+		 (/= (preceding-char) ?\\ ))
+	    (insert "\\"))
+	(if (not (eobp))
+	    (forward-char 1))))))
+
+;; taken from match-paren.el. Author: unknown
+(defun c++-match-paren ()
+  "Jumps to the paren matching the one under point, if there is one."
+  (interactive)
+  (let ((parse-sexp-ignore-comments (memq 'v19 c++-emacs-features)))
+    (cond
+     ((looking-at "[\(\[{]")
+      (forward-sexp 1)
+      (backward-char))
+     ((looking-at "[])}]")
+      (forward-char)
+      (backward-sexp 1))
+     (t (message "Could not find matching paren.")))))
+
+(defun c++-forward-sexp (&optional arg)
+  "Safe forward-sexp call."
+  (interactive "_p")
+  (let ((parse-sexp-ignore-comments (memq 'v19 c++-emacs-features)))
+    (forward-sexp arg)))
+
+(defun c++-backward-sexp (&optional arg)
+  "Safe backward-sexp call."
+  (interactive "_p")
+  (let ((parse-sexp-ignore-comments (memq 'v19 c++-emacs-features)))
+    (backward-sexp arg)))
+
+
+;; ======================================================================
+;; compatibility between emacsen
+;; ======================================================================
+
+;; This is the best we can do in vanilla GNU 18 emacsen. Note that the
+;; following problems exist:
+;; 1. We only look back to LIM, and that could place us inside a
+;;    literal if we are scanning backwards over lots of comments
+;; 2. This can potentially get slower the larger LIM is
+;; If anybody has a better solution, I'll all ears
+(defun c++-backward-syntactic-ws-v18 (&optional lim)
+  "Skip backwards over syntactic whitespace.
+Syntactic whitespace is defined as lexical whitespace, C and C++ style
+comments, and preprocessor directives.  Search no farther back than
+optional LIM.  If LIM is omitted, `beginning-of-defun' is used."
+  (let ((lim (or lim (c++-point 'bod)))
+	literal stop)
+    (if (and c++-backscan-limit
+	     (> (- (point) lim) c++-backscan-limit))
+	(setq lim (- (point) c++-backscan-limit)))
+    (while (not stop)
+      (skip-chars-backward " \t\n\r\f" lim)
+      ;; c++ comment
+      (if (eq (setq literal (c++-in-literal lim)) 'c++)
+	  (progn
+	    (skip-chars-backward "^/" lim)
+	    (skip-chars-backward "/" lim)
+	    (while (not (or (and (= (following-char) ?/)
+				 (= (char-after (1+ (point))) ?/))
+			    (<= (point) lim)))
+	      (skip-chars-backward "^/" lim)
+	      (skip-chars-backward "/" lim)))
+	;; c comment
+	(if (eq literal 'c)
+	    (progn
+	      (skip-chars-backward "^*" lim)
+	      (skip-chars-backward "*" lim)
+	      (while (not (or (and (= (following-char) ?*)
+				   (= (preceding-char) ?/))
+			      (<= (point) lim)))
+		(skip-chars-backward "^*" lim)
+		(skip-chars-backward "*" lim))
+	      (or (bobp) (forward-char -1)))
+	  ;; preprocessor directive
+	  (if (eq literal 'pound)
+	      (progn
+		(beginning-of-line)
+		(setq stop (<= (point) lim)))
+	    ;; just outside of c block
+	    (if (and (= (preceding-char) ?/)
+		     (= (char-after (- (point) 2)) ?*))
+		(progn
+		  (skip-chars-backward "^*" lim)
+		  (skip-chars-backward "*" lim)
+		  (while (not (or (and (= (following-char) ?*)
+				       (= (preceding-char) ?/))
+				  (<= (point) lim)))
+		    (skip-chars-backward "^*" lim)
+		    (skip-chars-backward "*" lim))
+		  (or (bobp) (forward-char -1)))
+	      ;; none of the above
+	      (setq stop t))))))))
+
+;; This defun works well for Lemacs 19.4-7, which implemented a first
+;; shot at doing this via a C built-in backward-syntactic-ws.  This
+;; has been obsoleted in future Lemacsen and in FSF19
+(defun c++-fast-backward-syntactic-ws-1 (&optional lim)
+  "Skip backwards over syntactic whitespace.
+Syntactic whitespace is defined as lexical whitespace, C and C++ style
+comments, and preprocessor directives.  Search no farther back than
+optional LIM.  If LIM is omitted, `beginning-of-defun' is used."
+  (save-restriction
+    (let ((parse-sexp-ignore-comments t)
+	  donep boi char
+	  (lim (or lim (c++-point 'bod))))
+      (if (< lim (point))
+	  (unwind-protect
+	      (progn
+		(narrow-to-region lim (point))
+		;; cpp statements are comments for our purposes here
+		(if (eq major-mode 'c++-mode)
+		    (modify-syntax-entry ?# "< b" c++-mode-syntax-table)
+		  (modify-syntax-entry ?\n "> b" c++-c-mode-syntax-table)
+		  (modify-syntax-entry ?#  "< b" c++-c-mode-syntax-table))
+		(while (not donep)
+		  ;; if you're not running a patched XEmacs, the new byte
+		  ;; compiler will complain about this function. ignore that
+		  (backward-syntactic-ws)
+		  (if (not (looking-at "#\\|/\\*\\|//\\|\n"))
+		      (forward-char 1))
+		  (setq boi (c++-point 'boi)
+			char (char-after boi))
+		  (if (and char (= char ?#))
+		      (progn (goto-char boi)
+			     (setq donep (<= (point) lim)))
+		    (setq donep t))
+		  ))
+	    ;; cpp statements are not comments anywhere else
+	    (if (eq major-mode 'c++-mode)
+		(modify-syntax-entry ?# "." c++-mode-syntax-table)
+	      (modify-syntax-entry ?\n " " c++-c-mode-syntax-table)
+	      (modify-syntax-entry ?#  "." c++-c-mode-syntax-table))))
+      )))
+
+;; This is the way it should be done for all post 19.7 Lemacsen and
+;; for all FSF19 implementations
+(defun c++-fast-backward-syntactic-ws-2 (&optional lim)
+  "Skip backwards over syntactic whitespace.
+Syntactic whitespace is defined as lexical whitespace, C and C++ style
+comments, and preprocessor directives.  Search no farther back than
+optional LIM.  If LIM is omitted, `beginning-of-defun' is used."
+  (save-restriction
+    (let* ((lim (or lim (c++-point 'bod)))
+	   (here lim))
+      (if (< lim (point))
+	  (unwind-protect
+	      (progn
+		(narrow-to-region lim (point))
+		;; cpp statements are comments for our purposes here
+		(if (eq major-mode 'c++-mode)
+		    (modify-syntax-entry ?# "< b" c++-mode-syntax-table)
+		  (modify-syntax-entry ?\n "> b" c++-c-mode-syntax-table)
+		  (modify-syntax-entry ?#  "< b" c++-c-mode-syntax-table))
+		(while (/= here (point))
+		  (setq here (point))
+		  (forward-comment -1)))
+	    ;; cpp statements are not comments everywhere else
+	    (if (eq major-mode 'c++-mode)
+		(modify-syntax-entry ?# "." c++-mode-syntax-table)
+	      (modify-syntax-entry ?\n " " c++-c-mode-syntax-table)
+	      (modify-syntax-entry ?#  "." c++-c-mode-syntax-table))))
+      )))
+
+;; This is the slow and ugly way, but its the best we can do in
+;; vanilla GNU18 emacsen
+(defun c++-in-literal-v18 (&optional lim)
+  "Determine if point is in a C++ ``literal''.
+Return `c' if in a C-style comment, `c++' if in a C++ style comment,
+`string' if in a string literal, `pound' if on a preprocessor line, or
+nil if not in a comment at all.  Optional LIM is used as the backward
+limit of the search.  If omitted, or nil, `c++-beginning-of-defun' is
+used."
+  (save-excursion
+    (let* ((here (point))
+	   (state nil)
+	   (match nil)
+	   (backlim (or lim (c++-point 'bod))))
+      (goto-char backlim)
+      (while (< (point) here)
+	(setq match
+	      (and (re-search-forward "\\(/[/*]\\)\\|[\"']\\|\\(^[ \t]*#\\)"
+				      here 'move)
+		   (buffer-substring (match-beginning 0) (match-end 0))))
+	(setq state
+	      (cond
+	       ;; no match
+	       ((null match) nil)
+	       ;; looking at the opening of a C++ style comment
+	       ((string= "//" match)
+		(if (<= here (progn (end-of-line) (point))) 'c++))
+	       ;; looking at the opening of a C block comment
+	       ((string= "/*" match)
+		(if (not (re-search-forward "*/" here 'move)) 'c))
+	       ;; looking at the opening of a double quote string
+	       ((string= "\"" match)
+		(if (not (save-restriction
+			   ;; this seems to be necessary since the
+			   ;; re-search-forward will not work without it
+			   (narrow-to-region (point) here)
+			   (re-search-forward
+			    ;; this regexp matches a double quote
+			    ;; which is preceded by an even number
+			    ;; of backslashes, including zero
+			    "\\([^\\]\\|^\\)\\(\\\\\\\\\\)*\"" here 'move)))
+		    'string))
+	       ;; looking at the opening of a single quote string
+	       ((string= "'" match)
+		(if (not (save-restriction
+			   ;; see comments from above
+			   (narrow-to-region (point) here)
+			   (re-search-forward
+			    ;; this matches a single quote which is
+			    ;; preceded by zero or two backslashes.
+			    "\\([^\\]\\|^\\)\\(\\\\\\\\\\)?'"
+			    here 'move)))
+		    'string))
+	       ((string-match "[ \t]*#" match)
+		(if (<= here (progn (end-of-line) (point))) 'pound))
+	       (t nil)))
+	) ; end-while
+      state)))
+
+;; This is for all 8-bit emacsen (Lucid 19, patched GNU18)
+(defun c++-in-literal-8-bit (&optional lim)
+  "Determine if point is in a C++ ``literal''.
+Return `c' if in a C-style comment, `c++' if in a C++ style comment,
+`string' if in a string literal, `pound' if on a preprocessor line, or
+nil if not in a comment at all.  Optional LIM is used as the backward
+limit of the search.  If omitted, or nil, `c++-beginning-of-defun' is
+used."
+  (save-excursion
+    (let* ((backlim (or lim (c++-point 'bod)))
+	   (here (point))
+	   (parse-sexp-ignore-comments t) ; may not be necessary
+	   (state (parse-partial-sexp backlim (point))))
+      (cond
+       ((nth 3 state) 'string)
+       ((nth 4 state) (if (nth 7 state) 'c++ 'c))
+       ((progn
+	  (goto-char here)
+	  (beginning-of-line)
+	  (looking-at "[ \t]*#"))
+	'pound)
+       (t nil)))))
+
+;; This is for all 1-bit emacsen (FSF19)
+(defun c++-in-literal-1-bit (&optional lim)
+  "Determine if point is in a C++ ``literal''.
+Return `c' if in a C-style comment, `c++' if in a C++ style comment,
+`string' if in a string literal, `pound' if on a preprocessor line, or
+nil if not in a comment at all.  Optional LIM is used as the backward
+limit of the search.  If omitted, or nil, `c++-beginning-of-defun' is
+used."
+  (save-excursion
+    (let* ((backlim (or lim (c++-point 'bod)))
+	   (here (point))
+	   (parse-sexp-ignore-comments t) ; may not be necessary
+	   (state (parse-partial-sexp backlim (point))))
+      (cond
+       ((nth 3 state) 'string)
+       ((nth 4 state) (if (nth 7 state) 'c 'c++))
+       ((progn
+	  (goto-char here)
+	  (beginning-of-line)
+	  (looking-at "[ \t]*#"))
+	'pound)
+       (t nil)))))
+
+(cond
+ ((memq 'old-v19 c++-emacs-features)
+  (fset 'c++-backward-syntactic-ws 'c++-fast-backward-syntactic-ws-1))
+ ((memq 'v19 c++-emacs-features)
+  (fset 'c++-backward-syntactic-ws 'c++-fast-backward-syntactic-ws-2))
+ (t
+  (fset 'c++-backward-syntactic-ws 'c++-backward-syntactic-ws-v18))
+ )
+(cond
+ ((memq '8-bit c++-emacs-features)
+  (fset 'c++-in-literal 'c++-in-literal-8-bit))
+ ((memq '1-bit c++-emacs-features)
+  (fset 'c++-in-literal 'c++-in-literal-1-bit))
+ (t
+  (fset 'c++-in-literal 'c++-in-literal-v18))
+ )
+
+
+;; ======================================================================
+;; defuns for parsing syntactic elements
+;; ======================================================================
+(defun c++-parse-state (&optional limit)
+  "Determinate the syntactic state of the code at point.
+Iteratively uses `parse-partial-sexp' from point to LIMIT and returns
+the result of `parse-partial-sexp' at point.  LIMIT is optional and
+defaults to `point-max'."
+  (let ((limit (or limit (point-max)))
+	(parse-sexp-ignore-comments t)
+	state)
+    (while (< (point) limit)
+      (setq state (parse-partial-sexp (point) limit 0)))
+    state))
+
+(defun c++-at-top-level-p (wrt &optional bod)
+  "Return t if point is not inside a containing C++ expression, nil
+if it is embedded in an expression.  When WRT is non-nil, returns nil
+if not at the top level with respect to an enclosing class, or the
+depth of class nesting at point.  With WRT nil, returns nil if not at
+the ``real'' top level.  Optional BOD is the beginning of defun."
+  (save-excursion
+    (let ((indent-point (point))
+	  (case-fold-search nil)
+	  state containing-sexp paren-depth
+	  (bod (or bod (c++-point 'bod)))
+	  foundp)
+      (goto-char bod)
+      (setq state (c++-parse-state indent-point)
+	    containing-sexp (nth 1 state)
+	    paren-depth (nth 0 state))
+      (cond
+       ((eq major-mode 'c++-c-mode)
+	(and (null containing-sexp) 0))
+       ((not wrt)
+	(null containing-sexp))
+       ((null containing-sexp) 0)
+       ((c++-in-parens-p) nil)
+       (t
+	;; calculate depth wrt containing (possibly nested) classes
+	(goto-char containing-sexp)
+	(while (and (setq foundp (re-search-backward
+				  (concat "[;}]\\|" c++-class-key)
+				  (point-min) t))
+		    (let ((bod (c++-point 'bod)))
+		      (or (c++-in-literal bod)
+			  (c++-in-parens-p bod)
+			  ;; see if class key is inside a template spec
+			  (and (looking-at c++-class-key)
+			       (progn (skip-chars-backward " \t\n")
+				      (memq (preceding-char) '(?, ?<))))))))
+	(if (memq (following-char) '(?} ?\;))
+	    nil
+	  (setq state (c++-parse-state containing-sexp))
+	  (and foundp
+	       (not (nth 1 state))
+	       (nth 2 state)
+	       paren-depth))
+	)))))
+
+(defun c++-in-parens-p (&optional lim)
+  "Return t if inside a paren expression.
+Optional LIM is used as the backward limit of the search."
+  (let ((lim (or lim (c++-point 'bod))))
+    (condition-case var
+	(save-excursion
+	  (save-restriction
+	    (narrow-to-region (point) lim)
+	    (goto-char (point-max))
+	    (= (char-after (or (scan-lists (point) -1 1)
+			       (point-min)))
+	       ?\()))
+      (error nil)
+      )))
+
+(defun c++-in-function-p (&optional containing)
+  "Return t if inside a C++ function definition.
+Optional CONTAINING is position of containing s-exp open brace.  If not
+supplied, point is used as search start."
+  (save-excursion
+    (let ((here (if (not containing)
+		    (point)
+		  (goto-char containing)
+		  (c++-backward-syntactic-ws)
+		  (point))))
+      (if (and (= (preceding-char) ?t)
+	       (forward-word -1)
+	       (looking-at "\\<const\\>"))
+	  (c++-backward-syntactic-ws)
+	(goto-char here))
+      (= (preceding-char) ?\)))))
+
+
+;; ======================================================================
+;; defuns for calculating indentation
+;; ======================================================================
+(defun c++-indent-line (&optional bod)
+  "Indent current line as C++ code.
+Return the amount the indentation changed by.  Optional BOD is the
+point of the beginning of the C++ definition."
+  (let* ((bod (or bod (c++-point 'bod)))
+	 (indent (c++-calculate-indent nil bod))
+	 beg shift-amt
+	 close-paren top-close-paren
+	 (case-fold-search nil)
+	 (pos (- (point-max) (point))))
+    ;; calculate block close paren offset
+    (if (listp c++-block-close-brace-offset)
+	(setq close-paren (car c++-block-close-brace-offset)
+	      top-close-paren (cdr c++-block-close-brace-offset))
+      (setq close-paren c++-block-close-brace-offset
+	    top-close-paren c++-block-close-brace-offset))
+    ;; now start cleanup
+    (beginning-of-line)
+    (setq beg (point))
+    (cond
+     ((eq indent nil)
+      (setq indent (current-indentation)))
+     ((eq indent t)
+      (setq indent (c++-calculate-c-indent-within-comment)))
+     ((looking-at "[ \t]*#")
+      (setq indent 0))
+     ((save-excursion
+	(back-to-indentation)
+	(looking-at "//\\|/\\*"))
+      ;; we've found a comment-only line. we now must try to determine
+      ;; if the line is a continuation from a comment on the previous
+      ;; line.  we check to see if the comment starts in or to the
+      ;; right of comment-column and if so, we don't change its
+      ;; indentation.
+      (skip-chars-forward " \t")
+      (if (>= (current-column) comment-column)
+	  (setq indent (current-column))
+	(setq indent (c++-comment-offset (bolp) indent))))
+     (t
+      (skip-chars-forward " \t")
+      (if (listp indent) (setq indent (car indent)))
+      (cond
+       ((looking-at c++-access-key)
+	(setq indent (+ indent c++-access-specifier-offset)))
+       ((looking-at "default[ \t]*:")
+	(setq indent (+ indent c-label-offset)))
+       ((or (looking-at "case[ \t]+.*:")
+	    (and (looking-at "[A-Za-z]")
+		 (save-excursion
+		   (forward-sexp 1)
+		   (looking-at ":[^:]"))))
+	(setq indent (max 1 (+ indent c-label-offset))))
+       ((and (looking-at "else\\b")
+	     (not (looking-at "else\\s_")))
+	(setq indent (save-excursion
+		       (c++-backward-to-start-of-if)
+		       (back-to-indentation)
+		       (skip-chars-forward "{ \t")
+		       (current-column))))
+       ((looking-at "\\<friend\\>")
+	(setq indent (+ indent c++-friend-offset)))
+       ((and (= (following-char) ?\))
+	     c++-paren-as-block-close-p)
+	(setq indent (+ (- indent c-indent-level)
+			(if (save-excursion
+			      (forward-char 1)
+			      (c++-at-top-level-p nil bod))
+			    top-close-paren
+			  close-paren))))
+       ((= (following-char) ?})
+	(setq indent (+ (- indent c-indent-level)
+			(if (save-excursion
+			      (forward-char 1)
+			      (c++-at-top-level-p nil bod))
+			    top-close-paren
+			  close-paren))))
+       ((= (following-char) ?{)
+	(setq indent (+ indent c-brace-offset))))))
+    (skip-chars-forward " \t")
+    (setq shift-amt (- indent (current-column)))
+    (if (zerop shift-amt)
+	(if (> (- (point-max) pos) (point))
+	    (goto-char (- (point-max) pos)))
+      (delete-region beg (point))
+      (indent-to indent)
+      ;; If initial point was within line's indentation,
+      ;; position after the indentation.  Else stay at same point in text.
+      (if (> (- (point-max) pos) (point))
+	  (goto-char (- (point-max) pos))))
+    ;; save-excursion is necessary because things break if the hook
+    ;; changes point or mark
+    (save-excursion
+      (run-hooks 'c++-special-indent-hook))
+    shift-amt))
+
+(defun c++-cont-indent (ipnt char lim)
+  "Calculate the indentation for a continued statement.
+IPNT is the indentation point; CHAR is the character before the
+indentation point, excluding any intervening whitespace; LIM is the
+minimum point to search backwards to."
+  (let ((charlist '(nil ?\000 ?\, ?\; ?\} ?\: ?\{))
+	streamop-pos here)
+    (goto-char ipnt)
+    (c++-backward-syntactic-ws lim)
+    (if (not (memq char charlist))
+	;; This line is continuation of preceding line's statement
+	(progn
+	  (c-backward-to-start-of-continued-exp lim)
+	  ;; take care of << and >> while in streams
+	  (setq here (point))
+	  (if (save-excursion
+		(and (progn (goto-char ipnt)
+			    (looking-at "[ \t]*\\(<<\\|>>\\)"))
+		     (progn (goto-char here)
+			    (skip-chars-forward "^><\n")
+			    (setq streamop-pos (current-column))
+			    (looking-at "\\(<<\\|>>\\)"))))
+	      streamop-pos
+	    (+ (current-column)
+	       ;; prevent repeated continued indentation
+	       (if (save-excursion
+		     (beginning-of-line 1)
+		     (c++-backward-syntactic-ws lim)
+		     (memq (preceding-char) charlist))
+		   c-continued-statement-offset
+		 ;; the following statements *do* indent even
+		 ;; for single statements (are there others?)
+		 (if (looking-at "\\(do\\|else\\|for\\|if\\|while\\)\\b")
+		     c-continued-statement-offset
+		   ;; else may be a continued statement inside
+		   ;; a simple for/else/while/if/do loop
+		   (beginning-of-line 1)
+		   (forward-char -1)
+		   (c++-backward-syntactic-ws lim)
+		   (c-backward-to-start-of-continued-exp lim)
+		   (if (looking-at "\\(do\\|else\\|for\\|if\\|while\\)\\b")
+		       c-continued-statement-offset
+		     0)))
+	       (save-excursion
+		 (goto-char ipnt)
+		 (skip-chars-forward " \t")
+		 (cond
+		  ((= (following-char) ?\{)
+		   c-continued-brace-offset)
+		  ((and (= (following-char) ?\})
+			(progn (forward-char 1)
+			       (c++-at-top-level-p nil lim)))
+		   (- c-continued-statement-offset))
+		  (t 0))))))
+      nil)))
+
+(defun c++-calculate-indent (&optional parse-start bod)
+  "Return appropriate indentation for current line as C++ code.
+In usual case returns an integer: the column to indent to.
+Returns nil if line starts inside a string, t if in a comment.
+Optional PARSE-START is the location to start parsing, and optional
+BOD is the beginning of the C++ definition."
+  (save-excursion
+    (beginning-of-line)
+    (let ((indent-point (point))
+	  (case-fold-search nil)
+	  state do-indentation literal in-meminit-p
+	  containing-sexp streamop-pos char-before-ip
+	  (inclass-shift 0) inclass-depth inclass-unshift
+	  (bod (or bod (c++-point 'bod))))
+      (if parse-start
+	  (goto-char parse-start)
+	(goto-char bod))
+      (setq parse-start (point)
+	    state (c++-parse-state indent-point)
+	    containing-sexp (nth 1 state))
+      ;; it is possible that c++-defun-header-weak could not find the
+      ;; beginning of the C++ definition. The following code attempts
+      ;; to work around this.  It is probably better to just use
+      ;; c++-match-header-strongly, but there are performance questions
+      (if (null state)
+	  (let* ((c++-match-header-strongly t)
+		 (bod (c++-point 'bod)))
+	    (goto-char bod)
+	    (setq state (c++-parse-state indent-point)
+		  containing-sexp (nth 1 state)
+		  parse-start (point))))
+      (setq literal (c++-in-literal bod))
+      ;; cache char before indent point
+      (save-excursion
+	(goto-char indent-point)
+	(c++-backward-syntactic-ws bod)
+	(setq char-before-ip (preceding-char)))
+      (cond
+       ;; CASE 1: in a string.
+       ((memq literal '(string)) nil)
+       ;; CASE 2: in a C or C++ style comment.
+       ((memq literal '(c c++)) t)
+       ;; CASE 3: Line is at top level.  May be comment-only line,
+       ;; data or function definition, or may be function argument
+       ;; declaration or member initialization.  Indent like the
+       ;; previous top level line unless:
+       ;;
+       ;; 1. the previous line ends in a closeparen without
+       ;; semicolon, in which case this line is the first
+       ;; argument declaration or member initialization, or
+       ;;
+       ;; 2. the previous line ends with a closeparen
+       ;; (closebrace), optional spaces, and a semicolon, in
+       ;; which case this line follows a multiline function
+       ;; declaration (class definition), or
+       ;;
+       ;; 3. the previous line begins with a colon, in which
+       ;; case this is the second line of member inits.  It is
+       ;; assumed that arg decls and member inits are not mixed.
+       ;;
+       ((setq inclass-depth (c++-at-top-level-p t bod))
+	(+
+	 ;; add an offset if we are inside a class defun body, i.e. we
+	 ;; are at the top level, but only wrt a containing class
+	 (let ((shift/level (+ c-indent-level c-brace-imaginary-offset)))
+	   (setq inclass-shift (* shift/level inclass-depth)
+		 inclass-unshift (* shift/level (max 0 (1- inclass-depth))))
+	   inclass-shift)
+	 (progn
+	   (goto-char indent-point)
+	   (skip-chars-forward " \t")
+	   (cond
+	    ;;
+	    ((or (= (following-char) ?{)
+		 (progn
+		   (c++-backward-syntactic-ws parse-start)
+		   (bobp)))
+	     0)
+	    ;; first arg decl or member init
+	    ((c++-in-function-p)
+	     (goto-char indent-point)
+	     (skip-chars-forward " \t")
+	     (if (= (following-char) ?:)
+		 c++-member-init-indent
+	       c-argdecl-indent))
+	    ;;
+	    ((progn
+	       (if (= (preceding-char) ?\;)
+		   (progn
+		     (backward-char 1)
+		     (skip-chars-backward " \t")))
+	       ;; may be first line after a hanging member init colon.
+	       ;; check to be sure its not a scope operator meaning we
+	       ;; are inside a member def
+	       (or (= (preceding-char) ?:)
+		   (save-excursion
+		     (forward-line 1)
+		     (skip-chars-forward " \t")
+		     (or (eobp) (forward-char 1))
+		     (and (= (preceding-char) ?:)
+			  (/= (following-char) ?:)))
+		   (save-excursion
+		     (and (= (preceding-char) ?,)
+			  (let ((bol (c++-point 'bol)))
+			    (skip-chars-backward "^:" bol)
+			    (= (preceding-char) ?:))
+			  (not (c++-in-parens-p))
+			  (progn
+			    (forward-char -1)
+			    (skip-chars-backward " \t")
+			    (not (bolp)))
+			  ;; make sure its not a multiple inheritance
+			  ;; continuation line
+			  (progn
+			    (beginning-of-line)
+			    (not (looking-at c++-inher-key)))
+			  ))))
+	     ;; check to see if we're looking at a member init, or
+	     ;; access specifier
+	     (if (progn
+		   (beginning-of-line)
+		   (skip-chars-forward " \t")
+		   (looking-at c++-access-key))
+		 ;; access specifier. class defun opening brace may
+		 ;; not be in col zero, and derived classes could be
+		 ;; on a separate line than class intro
+		 (progn
+		   (goto-char (or containing-sexp bod))
+		   (beginning-of-line)
+		   (skip-chars-forward " \t")
+		   (if (looking-at
+			":[ \t]*\\<\\(public\\|protected\\|private\\)\\>")
+		       (forward-line -1))
+		   (- (current-indentation)
+		      ;; remove some nested inclass indentation
+		      inclass-unshift))
+	       ;; member init, so add offset. add additional offset if
+	       ;; looking at line with just a member init colon
+	       (+ c++-member-init-indent
+		  (if (looking-at ":[ \t]*$")
+		      (or c++-continued-member-init-offset 0) 0))))
+	    ((or (= (preceding-char) ?})
+		 (= (preceding-char) ?\))
+		 (save-excursion
+		   (beginning-of-line)
+		   (looking-at "[ \t]*\\<friend\\>")))
+	     ;; indentation of class defun opening brace may not be
+	     ;; zero
+	     (goto-char (or containing-sexp bod))
+	     (- (current-indentation)
+		;; remove some nested inclass indentation
+		inclass-unshift))
+	    ;; cont arg decls or member inits.  we might be inside a
+	    ;; K&R C arg decl
+	    ((save-excursion
+	       (while (and (< bod (point))
+			   (memq (preceding-char) '(?\, ?\;)))
+		 (beginning-of-line)
+		 (c++-backward-syntactic-ws bod))
+	       (and (eq major-mode 'c++-c-mode)
+		    (= (preceding-char) ?\))))
+	     (+ c-argdecl-indent
+		(progn
+		  (goto-char indent-point)
+		  (c++-backward-syntactic-ws bod)
+		  (if (= (preceding-char) ?,)
+		      c-continued-statement-offset
+		    0))))
+	    ((progn
+	       (beginning-of-line)
+	       (skip-chars-forward " \t")
+	       (or (memq (c++-in-literal bod) '(c c++))
+		   (looking-at "/[/*]")))
+	     0)
+	    ;; are we looking at the first member init?
+	    ((and (= (following-char) ?:)
+		  (save-excursion
+		    (c++-backward-syntactic-ws bod)
+		    (= (preceding-char) ?\))))
+	     (if c++-continued-member-init-offset
+		 (+ (current-indentation)
+		    c++-continued-member-init-offset)
+	       (progn
+		 (forward-char 1)
+		 (skip-chars-forward " \t")
+		 (- (current-column)
+		    inclass-shift))))
+	    ;; else first check to see if its a multiple inheritance
+	    ;; continuation line, but not a K&R C arg decl
+	    ((and (not (eq major-mode 'c++-c-mode))
+		  (looking-at c++-inher-key))
+	     (if (= char-before-ip ?,)
+		 (progn (goto-char (match-end 0))
+			(current-column))
+	       ;; nope, its probably a nested class
+	       0))
+	    ;; we might be looking at the opening brace of a class
+	    ;; defun
+	    ((= (following-char) ?\{)
+	     ;; indentation of opening brace may not be zero
+	     (- (current-indentation)
+		;; remove some nested inclass indentation
+		inclass-unshift))
+	    ((eolp)
+	     ;; looking at a blank line, indent next line to zero
+	     0)
+	    ;; at beginning of buffer, if nothing else, indent to zero
+	    ((save-excursion
+	       (goto-char indent-point)
+	       (beginning-of-line)
+	       (bobp))
+	     0)
+	    ;; this could be a compound statement, but make sure its
+	    ;; not a member init list
+	    ((save-excursion
+	       (goto-char indent-point)
+	       (c++-backward-syntactic-ws bod)
+	       (and (= (preceding-char) ?,)
+		    (save-excursion
+		      (while (and (< bod (point))
+				  (= (preceding-char) ?,))
+			(beginning-of-line)
+			(c++-backward-syntactic-ws bod))
+		      (forward-line 1)
+		      (not (setq in-meminit-p (looking-at "[ \t]*:"))))))
+	     c-continued-statement-offset)
+	    (t
+	     (if (c++-in-parens-p)
+		 ;; we are perhaps inside a member init call
+		 (while (and (c++-in-parens-p)
+			     (< bod (point)))
+		   (forward-line -1)
+		   (skip-chars-forward " \t")))
+	     ;; check to be sure that we're not on the first line of
+	     ;; the member init list
+	     (if (and (= (following-char) ?:)
+		      (save-excursion
+			(c++-backward-syntactic-ws bod)
+			(= (preceding-char) ?\))))
+		 (progn
+		   (forward-char 1)
+		   (skip-chars-forward " \t")))
+	     ;; skip to start of compound statement, but only if we're
+	     ;; not in a member initialization list
+	     (if (not in-meminit-p)
+		 (let ((ipnt (point)))
+		   (c++-backward-syntactic-ws bod)
+		   (while (and (= (preceding-char) ?,)
+			       (< bod (point)))
+		     (beginning-of-line)
+		     (skip-chars-forward " \t")
+		     (setq ipnt (point))
+		     (c++-backward-syntactic-ws bod))
+		   (goto-char ipnt)))
+	     ;; subtract inclass-shift since its already incorporated
+	     ;; by default in current-column
+	     (- (current-column) inclass-shift)
+	     )))))
+       ;; CASE 4: line is expression, not statement. indent to just
+       ;; after the surrounding open -- unless empty arg list, in
+       ;; which case we do what c++-empty-arglist-indent says to do.
+       ((/= (char-after containing-sexp) ?{)
+	(if (and c++-empty-arglist-indent
+		 (or c++-always-arglist-indent-p
+		     (null (nth 2 state))
+		     ;; indicates empty arg list.  Use a heuristic: if
+		     ;; the first non-whitespace following left paren
+		     ;; on same line is not a comment, is not an empty
+		     ;; arglist.
+		     (save-excursion
+		       (goto-char (1+ containing-sexp))
+		       (looking-at "[ \t]*[/\n]"))))
+	    (progn
+	      (goto-char containing-sexp)
+	      (beginning-of-line)
+	      (skip-chars-forward " \t")
+	      (goto-char (min (+ (point) c++-empty-arglist-indent)
+			      (1+ containing-sexp)))
+	      (current-column))
+	  ;; In C-mode, we would always indent to one after the
+	  ;; left paren.  Here, though, we may have an
+	  ;; empty-arglist, so we'll indent to the min of that
+	  ;; and the beginning of the first argument.
+	  (goto-char (1+ containing-sexp))
+	  ;; we want to skip any whitespace b/w open paren and
+	  ;; first argument. this handles while (thing) style
+	  ;; and while( thing ) style
+	  (skip-chars-forward " \t")
+	  (current-column)))
+       ;; CASE 5: Statement.  Find previous non-comment character.
+       (t
+	(or (c++-cont-indent indent-point char-before-ip containing-sexp)
+	  ;; This line may start a new statement, or it could
+	  ;; represent the while closure of a do/while construct
+	  (if (save-excursion
+		(and (progn (goto-char indent-point)
+			    (skip-chars-forward " \t\n")
+			    (looking-at "while\\b"))
+		     (progn
+		       (c++-backward-to-start-of-do containing-sexp)
+		       (looking-at "do\\b"))
+		     (setq do-indentation (current-column))))
+	      do-indentation
+	    ;; this could be a case statement. if so we want to
+	    ;; indent it like the first case statement after a switch
+	    (if (save-excursion
+		  (goto-char indent-point)
+		  (skip-chars-forward " \t\n")
+		  (looking-at "\\(case[ \t]+.*\\|default[ \t]*\\):"))
+		(progn
+		  (goto-char containing-sexp)
+		  (back-to-indentation)
+		  (+ (current-column) c-indent-level))
+	      ;; else, this is the start of a new statement
+	      ;; Position following last unclosed open.
+	      (goto-char containing-sexp)
+	      ;; Is line first statement after an open-brace?
+	      (or
+	       (and c++-relative-offset-p
+		    ;; If no, find that first statement and
+		    ;; indent like it.
+		    (save-excursion
+		      (forward-char 1)
+		      (while
+			  (progn
+			    (skip-chars-forward " \t\n")
+			    (looking-at
+			     (concat
+			      "#\\|/\\*\\|//"
+			      "\\|\\(case[ \t]+.*\\|default[ \t]*\\):"
+			      "\\|[a-zA-Z0-9_$]*:[^:]"
+			      "\\|friend[ \t]"
+			      c++-class-key
+			      "[ \t]")))
+			;; Skip over comments and labels
+			;; following openbrace.
+			(cond
+			 ((= (following-char) ?\#)
+			  (forward-line 1))
+			 ((looking-at "/\\*")
+			  (search-forward "*/" nil 'move))
+			 ((looking-at
+			   (concat "//\\|friend[ \t]" c++-class-key
+				   "[ \t]"))
+			  (forward-line 1))
+			 ((looking-at "\\(case[ \t]+.*\\|default[ \t]*\\):")
+			  (forward-line 1))
+			 (t
+			  (re-search-forward ":[^:]" nil 'move))))
+		      ;; The first following code counts
+		      ;; if it is before the line we want to indent.
+		      (and (< (point) indent-point)
+			   (+ (current-column)
+			      (c++-compound-offset
+			       char-before-ip containing-sexp bod)))))
+	       ;; If no previous statement, indent it relative to
+	       ;; line brace is on.  For open brace in column
+	       ;; zero, don't let statement start there too.  If
+	       ;; c-indent-offset is zero, use c-brace-offset +
+	       ;; c-continued-statement-offset instead.  For
+	       ;; open-braces not the first thing in a line, add
+	       ;; in c-brace-imaginary-offset.
+	       (+ (if (and (bolp) (zerop c-indent-level))
+		      (+ c-brace-offset c-continued-statement-offset)
+		    c-indent-level)
+		  ;; Move back over whitespace before the openbrace.
+		  ;; If openbrace is not first nonwhite thing on the line,
+		  ;; add the c-brace-imaginary-offset.
+		  (progn (skip-chars-backward " \t")
+			 (if (bolp) 0 c-brace-imaginary-offset))
+		  ;; If the openbrace is preceded by a parenthesized exp,
+		  ;; move to the beginning of that;
+		  ;; possibly a different line
+		  (progn
+		    (if (eq (preceding-char) ?\))
+			(forward-sexp -1))
+		    ;; Get initial indentation of the line we are on.
+		    (current-indentation)))))))) ; end t outer cond
+       ))))
+
+(defun c++-calculate-c-indent-within-comment ()
+  "Return the indentation amount for line, assuming that
+the current line is to be regarded as part of a block comment."
+  (let (end stars indent)
+    (save-excursion
+      (beginning-of-line)
+      (skip-chars-forward " \t")
+      (setq stars (if (looking-at "\\*\\*?")
+		      (- (match-end 0) (match-beginning 0))
+		    0))
+      (skip-chars-backward " \t\n")
+      (setq end (point))
+      (beginning-of-line)
+      (skip-chars-forward " \t")
+      (if (re-search-forward "/\\*[ \t]*" end t)
+	  (goto-char (+ (match-beginning 0)
+			(cond
+			 (c++-C-block-comments-indent-p 0)
+			 ((= stars 1) 1)
+			 ((= stars 2) 0)
+			 (t (- (match-end 0) (match-beginning 0)))))))
+      (current-column))))
+
+(defun c++-comment-offset (col0-line-p indent)
+  "Calculates and returns the comment-only line offset.
+Offset is based on the value of `c++-comment-only-line-offset', the
+argument COL0-LINE-P, and the current indentation INDENT."
+  (let ((offset 0))
+    (if col0-line-p
+	;; col0 means we need to look at the second member of the var's
+	;; list value. if value is not a list, then zero is used
+	(if (listp c++-comment-only-line-offset)
+	    ;; it is a list, so second element must be nil or a number
+	    (setq offset
+		  (+ indent
+		     (or (car (cdr c++-comment-only-line-offset))
+			 (car c++-comment-only-line-offset)))))
+      ;; not in column zero so indentation is car or value of variable
+      (setq offset
+	    (+ indent
+	       (if (listp c++-comment-only-line-offset)
+		   (car c++-comment-only-line-offset)
+		 c++-comment-only-line-offset))))
+    offset))
+
+(defun c++-compound-offset (char-before-ip containing-sexp bod)
+  "Calculates any addition offset due a comma separated compound statement.
+CHAR-BEFORE-IP is the character before the indentation point and
+CONTAINING-SEXP is the buffer position of the open brace or paren.
+BOD is the `beginning-of-defun' point."
+  (cond
+   ;; not a compound statement
+   ((/= char-before-ip ?,) 0)
+   ;; open brace could be at column zero == bod
+   ((and (= containing-sexp bod)
+	 (or (let ((lim (progn
+			  (goto-char containing-sexp)
+			  (forward-line -1)
+			  (point))))
+	       (end-of-line)
+	       (c++-backward-syntactic-ws lim)
+	       (= (preceding-char) ?=))
+	     (progn
+	       (beginning-of-line)
+	       (looking-at "\\(^\\|[ \t]*\\)enum[ \t]"))
+	     ))
+    0)
+   ;; check for inside an enum
+   ((let ((parse-sexp-ignore-comments t)
+	  in-enum-p)
+      (goto-char containing-sexp)
+      (while (< bod (point))
+	(c++-backward-syntactic-ws)
+	(if (memq (preceding-char) '(?\) ?\" ?\; ?\}))
+	    (goto-char bod)
+	  (forward-sexp -1)
+	  (if (looking-at "\\(enum[ \t\n]\\|\\[.*\\]\\)")
+	      (progn (goto-char bod)
+		     (setq in-enum-p t)))))
+      in-enum-p)
+    0)
+   ;; assume we're not in a list of enums or static array elems
+   (t c-continued-statement-offset)
+   ))
+   
+
+
+;; ======================================================================
+;; defuns to look backwards for things
+;; ======================================================================
+
+(defun c++-backward-to-start-of-do (&optional limit)
+  "Move to the start of the last ``unbalanced'' do."
+  (let ((do-level 1)
+	(case-fold-search nil)
+	(limit (or limit (c++-point 'bod))))
+    (while (not (zerop do-level))
+      ;; we protect this call because trying to execute this when the
+      ;; while is not associated with a do will throw an error
+      (condition-case err
+	  (progn
+	    (backward-sexp 1)
+	    (cond
+	     ((memq (c++-in-literal limit) '(c c++)))
+	     ((looking-at "while\\b")
+	      (setq do-level (1+ do-level)))
+	     ((looking-at "do\\b")
+	      (setq do-level (1- do-level)))
+	     ((< (point) limit)
+	      (setq do-level 0)
+	      (goto-char limit))))
+	(error
+	 (goto-char limit)
+	 (setq do-level 0))))))
+
+(defun c++-backward-to-start-of-if (&optional limit)
+  "Move to the start of the last ``unbalanced'' if."
+  (let ((if-level 1)
+	(case-fold-search nil)
+	(limit (or limit (c++-point 'bod))))
+    (while (and (not (bobp))
+		(not (zerop if-level)))
+      (c++-backward-syntactic-ws)
+      (c++-backward-sexp 1)
+      (cond ((looking-at "else\\b")
+	     (setq if-level (1+ if-level)))
+	    ((looking-at "if\\b")
+	     (setq if-level (1- if-level)))
+	    ((< (point) limit)
+	     (setq if-level 0)
+	     (goto-char limit))))))
+
+(defun c++-auto-newline ()
+  "Insert a newline iff we're not in a literal.
+Literals are defined as being inside a C or C++ style comment or open
+string according to mode's syntax."
+  (let ((bod (c++-point 'bod)))
+    (and c++-auto-newline
+	 (not (c++-in-literal bod))
+	 (not (newline)))))
+
+(defun c++-point (position)
+  "Returns the value of point at certain commonly referenced POSITIONs.
+POSITION can be one of the following symbols:
+  `bol' -- beginning of line
+  `eol' -- end of line
+  `bod' -- beginning of defun
+  `boi' -- back to indentation
+This function does not modify point or mark."
+  (let ((here (point)) bufpos)
+    (cond
+     ((eq position 'bol) (beginning-of-line))
+     ((eq position 'eol) (end-of-line))
+     ((eq position 'bod) (c++-beginning-of-defun))
+     ((eq position 'boi) (back-to-indentation))
+     )
+    (setq bufpos (point))
+    (goto-char here)
+    bufpos))
+
+
+;; ======================================================================
+;; defuns for "macroizations" -- making C++ parameterized types via macros
+;; ======================================================================
+(defun c++-macroize-region (from to arg)
+  "Insert backslashes at end of every line in region.
+Useful for defining cpp macros.  If called with a prefix argument,
+it will remove trailing backslashes."
+  (interactive "r\nP")
+  (save-excursion
+    (goto-char from)
+    (beginning-of-line 1)
+    (let ((line (count-lines (point-min) (point)))
+	  (to-line (save-excursion (goto-char to)
+				   (count-lines (point-min) (point)))))
+      (while (< line to-line)
+	(c++-backslashify-current-line (null arg))
+	(forward-line 1) (setq line (1+ line))))))
+
+(defun c++-backslashify-current-line (doit)
+  "Backslashifies current line."
+  (end-of-line 1)
+  (cond
+   (doit
+    ;; Note that "\\\\" is needed to get one backslash.
+    (if (not (save-excursion (forward-char -1) (looking-at "\\\\")))
+	(progn
+	  (if (>= (current-column) c++-default-macroize-column)
+	      (insert " \\")
+	    (while (<= (current-column) c++-default-macroize-column)
+	      (insert "\t") (end-of-line))
+	    (delete-char -1)
+	    (while (< (current-column) c++-default-macroize-column)
+	      (insert " ") (end-of-line))
+	    (insert "\\")))))
+   (t
+    (forward-char -1)
+    (if (looking-at "\\\\")
+	(progn (skip-chars-backward " \t")
+	       (kill-line))))))
+
+
+;; ======================================================================
+;; defuns for  commenting out multiple lines.
+;; ======================================================================
+(defun c++-comment-region (beg end)
+  "Comment out all lines in a region between mark and current point by
+inserting `comment-start' in front of each line."
+  (interactive "*r")
+  (save-excursion
+    (save-restriction
+      (narrow-to-region
+       (progn (goto-char beg) (beginning-of-line) (point))
+       (progn (goto-char end) (or (bolp) (forward-line 1)) (point)))
+      (goto-char (point-min))
+      (while (not (eobp))
+	(insert comment-start)
+	(forward-line 1))
+      (if (eq major-mode 'c++-c-mode)
+	  (insert comment-end)))))
+
+(defun c++-uncomment-region (beg end)
+  "Uncomment all lines in region between mark and current point by deleting
+the leading ``// '' from each line, if any."
+  (interactive "*r")
+  (save-excursion
+    (save-restriction
+      (narrow-to-region
+       (progn (goto-char beg) (beginning-of-line) (point))
+       (progn (goto-char end) (forward-line 1) (point)))
+      (goto-char (point-min))
+      (let ((comment-regexp
+	     (if (eq major-mode 'c++-c-mode)
+		 (concat "\\s *\\(" (regexp-quote comment-start)
+			 "\\|"      (regexp-quote comment-end)
+			 "\\)")
+	       (concat "\\s *" (regexp-quote comment-start)))))
+	(while (not (eobp))
+	  (if (looking-at comment-regexp)
+	      (delete-region (match-beginning 0) (match-end 0)))
+	  (forward-line 1))))))
+
+
+;; ======================================================================
+;; grammar parsing
+;; ======================================================================
+
+;;; Below are two regular expressions that attempt to match defuns
+;;; "strongly" and "weakly."  The strong one almost reconstructs the
+;;; grammar of C++; the weak one just figures anything id or curly on
+;;; the left begins a defun.  The constant "c++-match-header-strongly"
+;;; determines which to use; the default is the weak one.
+
+(defvar c++-match-header-strongly nil
+  "*If nil, use `c++-defun-header-weak' to identify beginning of definitions,
+if non-nil, use `c++-defun-header-strong'.")
+
+(defvar c++-defun-header-strong-struct-equivs
+  "\\(class\\|struct\\|union\\|enum\\)"
+  "Regexp to match names of structure declaration blocks in C++")
+
+(defconst c++-defun-header-strong
+  (let*
+      (; valid identifiers
+       ;; There's a real weirdness here -- if I switch the below
+       (id "\\(\\w\\|_\\)+")
+       ;; to be
+       ;; (id "\\(_\\|\\w\\)+")
+       ;; things no longer work right.  Try it and see!
+
+       ; overloadable operators
+       (op-sym1
+	 "[---+*/%^&|~!=<>]\\|[---+*/%^&|<>=!]=\\|<<=?\\|>>=?")
+       (op-sym2
+	 "&&\\|||\\|\\+\\+\\|--\\|()\\|\\[\\]")	 
+       (op-sym (concat "\\(" op-sym1 "\\|" op-sym2 "\\)"))
+       ; whitespace
+       (middle "[^\\*]*\\(\\*+[^/\\*][^\\*]*\\)*")
+       (c-comment (concat "/\\*" middle "\\*+/"))
+       (wh (concat "\\(\\s \\|\n\\|//.*$\\|" c-comment "\\)"))
+       (wh-opt (concat wh "*"))
+       (wh-nec (concat wh "+"))
+       (oper (concat "\\(" "operator" "\\("
+		     wh-opt op-sym "\\|" wh-nec id "\\)" "\\)"))
+       (dcl-list "([^():]*)")
+       (func-name (concat "\\(" oper "\\|" id "::" id "\\|" id "\\)"))
+       (inits
+	 (concat "\\(:"
+		 "\\(" wh-opt id "(.*\\()" wh-opt "," "\\)\\)*"
+		 wh-opt id "(.*)" wh-opt "{"
+		 "\\|" wh-opt "{\\)"))
+       (type-name (concat
+		    "\\(" c++-defun-header-strong-struct-equivs wh-nec "\\)?"
+		    id))
+       (type (concat "\\(const" wh-nec "\\)?"
+		     "\\(" type-name "\\|" type-name wh-opt "\\*+" "\\|"
+		     type-name wh-opt "&" "\\)"))
+       (modifier "\\(inline\\|virtual\\|overload\\|auto\\|static\\)")
+       (modifiers (concat "\\(" modifier wh-nec "\\)*"))
+       (func-header
+	 ;;     type               arg-dcl
+	 (concat modifiers type wh-nec func-name wh-opt dcl-list wh-opt inits))
+       (inherit (concat "\\(:" wh-opt "\\(public\\|protected\\|private\\)?"
+			wh-nec id "\\)"))
+       (cs-header (concat
+		    c++-defun-header-strong-struct-equivs
+		    wh-nec id wh-opt inherit "?" wh-opt "{")))
+    (concat "^\\(" func-header "\\|" cs-header "\\)"))
+  "Strongly-defined regexp to match beginning of structure or
+function definition.")
+
+
+;; This part has to do with recognizing defuns.
+
+;; The weak convention we will use is that a defun begins any time
+;; there is a left curly brace, or some identifier on the left margin,
+;; followed by a left curly somewhere on the line.  (This will also
+;; incorrectly match some continued strings, but this is after all
+;; just a weak heuristic.)  Suggestions for improvement (short of the
+;; strong scheme shown above) are welcomed.
+
+(defconst c++-defun-header-weak "^{\\|^[_a-zA-Z].*{"
+  "Weakly-defined regexp to match beginning of structure or function
+definition.")
+
+
+(defun c++-beginning-of-defun (&optional arg)
+  "Find the beginning of the C++ function or class."
+  (interactive "_p")
+  (if (not arg) (setq arg 1))
+  (let ((c++-defun-header (if c++-match-header-strongly
+			      c++-defun-header-strong
+			    c++-defun-header-weak)))
+    (cond
+     ((or (= arg 0) (and (> arg 0) (bobp))) nil)
+     ((and (not (looking-at c++-defun-header))
+	   (let ((curr-pos (point))
+		 (open-pos (if (search-forward "{" nil 'move)
+			       (point)))
+		 (beg-pos
+		  (if (re-search-backward c++-defun-header nil 'move)
+		      (match-beginning 0))))
+	     (if (and open-pos beg-pos
+		      (< beg-pos curr-pos)
+		      (> open-pos curr-pos))
+		 (progn
+		   (goto-char beg-pos)
+		   (if (= arg 1) t nil));; Are we done?
+	       (goto-char curr-pos)
+	       nil))))
+     (t
+      (if (and (looking-at c++-defun-header) (not (bobp)))
+	  (forward-char (if (< arg 0) 1 -1)))
+      (and (re-search-backward c++-defun-header nil 'move (or arg 1))
+	   (goto-char (match-beginning 0)))))))
+
+
+(defun c++-end-of-defun (arg)
+  "Find the end of the C++ function or class."
+  (interactive "_p")
+  (let ((c++-defun-header (if c++-match-header-strongly
+			      c++-defun-header-strong
+			    c++-defun-header-weak))
+	(parse-sexp-ignore-comments t))
+    (if (and (eobp) (> arg 0))
+	nil
+      (if (and (> arg 0) (looking-at c++-defun-header)) (forward-char 1))
+      (let ((pos (point)))
+	(c++-beginning-of-defun 
+	  (if (< arg 0)
+	      (- (- arg (if (eobp) 0 1)))
+	    arg))
+	(if (and (< arg 0) (bobp))
+	    t
+	  (if (re-search-forward c++-defun-header nil 'move)
+	      (progn (forward-char -1)
+		     (forward-sexp)
+		     (beginning-of-line 2)))
+	  (if (and (= pos (point)) 
+		   (re-search-forward c++-defun-header nil 'move))
+	      (c++-end-of-defun 1))))
+      t)))
+
+(defun c++-indent-defun ()
+  "Indents the current function def, struct or class declaration."
+  (interactive)
+  (let ((restore (point)))
+    (c++-end-of-defun 1)
+    (beginning-of-line 1)
+    (let ((end (point-marker)))
+      (c++-beginning-of-defun)
+      (while (and (< (point) end))
+	(c++-indent-line)
+	(forward-line 1)
+	(beginning-of-line 1))
+      (set-marker end nil))
+    (goto-char restore)))
+
+
+;; ======================================================================
+;; defuns for submitting bug reports
+;; ======================================================================
+(defconst c++-version "2.353"
+  "c++-mode version number.")
+(defconst c++-mode-help-address "c++-mode-help@anthem.nlm.nih.gov"
+  "Address accepting submission of bug reports.")
+
+(defun c++-version ()
+  "Echo the current version of c++-mode."
+  (interactive)
+  (message "Using c++-mode.el %s" c++-version))
+
+(defun c++-submit-bug-report ()
+  "Submit via mail a bug report on c++-mode."
+  (interactive)
+  (require 'reporter)
+  (and
+   (y-or-n-p "Do you want to submit a report on c++-mode? ")
+   (reporter-submit-bug-report
+    c++-mode-help-address
+    (concat "c++-mode.el " c++-version " (editing "
+	    (if (eq major-mode 'c++-mode) "C++" "C")
+	    " code)")
+    (list
+     'c++-emacs-features
+     'c++-C-block-comments-indent-p
+     'c++-access-specifier-offset
+     'c++-always-arglist-indent-p
+     'c++-auto-hungry-initial-state
+     'c++-auto-hungry-toggle
+     'c++-auto-newline
+     'c++-backscan-limit
+     'c++-block-close-brace-offset
+     'c++-cleanup-list
+     'c++-comment-only-line-offset
+     'c++-continued-member-init-offset
+     'c++-default-macroize-column
+     'c++-defun-header-strong-struct-equivs
+     'c++-delete-function
+     'c++-electric-pound-behavior
+     'c++-empty-arglist-indent
+     'c++-friend-offset
+     'c++-hanging-braces
+     'c++-hanging-member-init-colon
+     'c++-hungry-delete-key
+     'c++-match-header-strongly
+     'c++-member-init-indent
+     'c++-paren-as-block-close-p
+     'c++-relative-offset-p
+     'c++-tab-always-indent
+     'c++-untame-characters
+     'c-argdecl-indent
+     'c-brace-imaginary-offset
+     'c-brace-offset
+     'c-continued-brace-offset
+     'c-continued-statement-offset
+     'c-indent-level
+     'c-label-offset
+     'tab-width
+     )
+    (function
+     (lambda ()
+       (insert
+	(if c++-special-indent-hook
+	    (concat "\n@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"
+		    "c++-special-indent-hook is set to '"
+		    (format "%s" c++-special-indent-hook)
+		    ".\nPerhaps this is your problem?\n"
+		    "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n\n")
+	  "\n")
+	)))
+    )))
+
+
+;; this is sometimes useful
+(provide 'c++-mode)
+
+;;; c++-mode.el ends here