Commits

mast  committed 34e59dd

Updated to CC Mode 5.30.9.

  • Participants
  • Parent commits bfcc9c3

Comments (0)

Files changed (11)

+2004-08-11  Martin Stjernholm  <bug-cc-mode@gnu.org>
+
+	* Patch release 5.30.9.
+
+2004-08-11  Martin Stjernholm  <bug-cc-mode@gnu.org>
+
+	* cc-defs.el, cc-vars.el (c-emacs-features): Moved from cc-vars to
+	cc-defs for dependency reasons.  Fixed the POSIX char class test
+	to check that it works in `skip-chars-(forward|backward)' too.
+
+	* cc-align.el (c-lineup-arglist): Fixed bug when the first
+	argument starts with a special brace list.
+
+2004-08-11  Martin Stjernholm  <bug-cc-mode@gnu.org>
+
+	* cc-engine.el (c-forward-type): Fixed promotion bug when
+	`c-opt-type-concat-key' is used (i.e. in Pike).
+
+	* cc-engine.el (c-looking-at-special-brace-list): Fixed bug when
+	the inner char pair doesn't have paren syntax, i.e. "(< >)".
+
+2004-08-11  Alan Mackenzie  <bug-cc-mode@gnu.org>
+
+	* cc-cmds.el, cc-vars.el: Amend doc(-strings) to say that <TAB>
+	doesn't insert WS into a CPP line.
+	(c-indent-command, c-tab-always-indent): Amend doc strings.
+
+2004-08-11  Martin Stjernholm  <bug-cc-mode@gnu.org>
+
+	* cc-align.el (c-lineup-multi-inher): Made it syntactic whitespace
+	safe.
+
+2004-08-11  Martin Stjernholm  <bug-cc-mode@gnu.org>
+
+	* cc-engine.el (c-guess-basic-syntax): Fixed similar situations
+	for `arglist-cont-nonempty' and `arglist-close'.
+
+2004-08-11  Martin Stjernholm  <bug-cc-mode@gnu.org>
+
+	* cc-engine.el (c-guess-basic-syntax): Fixed anchor position for
+	`arglist-intro' when there are two arglist open parens on the same
+	line and there's nothing in front of the first.
+
+	* cc-fonts.el (c-basic-matchers-before): Fixed font locking of
+	qualified names in Java, which previously could fontify common
+	indexing expressions in many cases.  The standard Java naming
+	conventions are used to tell them apart.
+
+2004-08-11  Martin Stjernholm  <bug-cc-mode@gnu.org>
+
+	* cc-align.el (c-lineup-whitesmith-in-block): Fixed inconsistency
+	wrt opening parens on the first line inside a paren block.
+
+	* cc-defs.el (c-langs-are-parametric): Must be known at compile
+	time for the sake of `c-major-mode-is'.
+
+	(c-mode-is-new-awk-p): Made it a macro to delay expansion of
+	`c-major-mode-is' in the event that this is used inside a
+	`c-lang-defconst'.
+
+2004-08-11  Alan Mackenzie  <bug-cc-mode@gnu.org>
+
+	* cc-styles.el, cc-engine.el: Add in two checks for user errors,
+	thus eliminating cryptic and unhelpful Emacs error messages.  (1)
+	Check the arg to `c-set-style' is a string.  (2) Check that
+	settings to `c-offsets-alist' are not spuriously quoted.
+
+2004-08-11  Martin Stjernholm  <bug-cc-mode@gnu.org>
+
+	* cc-defs.el (c-major-mode-is): Fixed expansion inside
+	`c-lang-defconst' so that it works better with fallback languages.
+
+	* cc-defs.el (c-add-language): Fixed a typo that caused it to fail
+	to record the base mode.
+
+2004-08-11  Martin Stjernholm  <bug-cc-mode@gnu.org>
+
+	* cc-engine.el (c-syntactic-re-search-forward): Fixed bug so that
+	it doesn't go past the closing paren when PAREN-LEVEL is used.
+	Reordered the syntax checks to get more efficient skipping in some
+	situations.
+
+2004-08-11  Martin Stjernholm  <bug-cc-mode@gnu.org>
+
+	* cc-cmds.el (c-electric-brace): Don't trip up on a line
+	continuation which might precede the newly inserted '{'.
+
+2004-08-11  Martin Stjernholm  <bug-cc-mode@gnu.org>
+
+	* cc-engine.el (c-syntactic-re-search-forward): Fixed cases where
+	it could loop indefinitely.
+
+2004-08-11  Alan Mackenzie  <bug-cc-mode@gnu.org>
+
+	* cc-cmds.el: (c-electric-brace): don't delete a comment which
+	precedes the newly inserted `{'.
+
+2004-08-11  Martin Stjernholm  <bug-cc-mode@gnu.org>
+
+	* cc-fonts.el (c-font-lock-declarators): Handle array size specs
+	correctly.  Only fontify identifiers in front of '(' with as
+	functions - don't accept any paren char.  Tightened up initializer
+	skipping to stop before function and class blocks.
+
+2004-08-11  Martin Stjernholm  <bug-cc-mode@gnu.org>
+
+	* cc-engine.el (c-beginning-of-decl-1): Fixed bug where the point
+	could be left directly after an open paren when finding the
+	beginning of the first decl in the block.
+
+	* cc-engine.el (c-parse-state): Don't use the syntax table when
+	filtering out legitimate open parens to be recorded.  This could
+	cause cache inconsistencies when e.g. `c++-template-syntax-table'
+	was temporarily in use.
+
+2004-08-11  Martin Stjernholm  <bug-cc-mode@gnu.org>
+
+	* cc-engine.el (c-on-identifier, c-simple-skip-symbol-backward):
+	Small fix for handling "-" correctly in `skip-chars-backward'.
+	Affected the operator lfun syntax in Pike.
+
+2004-08-11  Martin Stjernholm  <bug-cc-mode@gnu.org>
+
+	* cc-engine.el (c-invalidate-sws-region-after): Fixed bug that
+	could cause an error from `after-change-functions' when the
+	changed region is at bob.
+
 2003-11-18  Norbert Koch  <viteno@xemacs.org>
 
 	* Makefile (VERSION): XEmacs package 1.42 released.
 # Boston, MA 02111-1307, USA.
 
 VERSION = 1.42
-AUTHOR_VERSION = 5.30.8
+AUTHOR_VERSION = 5.30.9
 MAINTAINER = Martin Stjernholm <bug-cc-mode@gnu.org>
 PACKAGE = cc-mode
 PKG_TYPE = regular
     ;; like "({".
     (when c-special-brace-lists
       (let ((special-list (c-looking-at-special-brace-list)))
-	(when special-list
+	(when (and special-list (< (car (car special-list)) (point)))
 	  (goto-char (+ (car (car special-list)) 2)))))
 
     (let ((savepos (point))
     (back-to-indentation)
     (let* ((eol (c-point 'eol))
 	   (here (point))
-	   (char-after-ip (progn
-			    (skip-chars-forward " \t")
-			    (char-after))))
+	   (char-after-ip (char-after)))
       (if (cdr langelem) (goto-char (cdr langelem)))
 
       ;; This kludge is necessary to support both inher-cont and
 	(backward-char)
 	(c-backward-syntactic-ws))
 
-      (skip-chars-forward "^:" eol)
-      (if (eq char-after-ip ?,)
-	  (skip-chars-forward " \t" eol)
-	(skip-chars-forward " \t:" eol))
-      (if (or (eolp)
-	      (looking-at c-comment-start-regexp))
-	  (c-forward-syntactic-ws here))
+      (c-syntactic-re-search-forward ":" eol 'move)
+      (if (looking-at c-syntactic-eol)
+	  (c-forward-syntactic-ws here)
+	(if (eq char-after-ip ?,)
+	    (backward-char)
+	  (skip-chars-forward " \t" eol)))
       (if (< (point) here)
 	  (vector (current-column)))
       )))
 brace-list-close, brace-list-intro, statement-block-intro and all in*
 symbols, e.g. inclass and inextern-lang."
   (save-excursion
-    (goto-char (cdr langelem))
-    (back-to-indentation)
-    (if (eq (char-syntax (char-after)) ?\()
-	0
-      c-basic-offset)))
+    (+ (progn
+	 (back-to-indentation)
+	 (if (eq (char-syntax (char-after)) ?\()
+	     c-basic-offset
+	   0))
+       (progn
+	 (goto-char (cdr langelem))
+	 (back-to-indentation)
+	 (if (eq (char-syntax (char-after)) ?\()
+	     0
+	   c-basic-offset)))))
 
 (defun c-lineup-cpp-define (langelem)
   "Line up macro continuation lines according to the indentation of
 	  ;; end up before it.
 	  (setq delete-temp-newline
 		(cons (save-excursion
-			(c-backward-syntactic-ws)
+			(end-of-line 0)
+			(if (eq (char-before) ?\\)
+			    ;; Ignore a line continuation.
+			    (backward-char))
+			(skip-chars-backward " \t")
 			(copy-marker (point) t))
 		      (point-marker))))
 	(unwind-protect
 If nil, indent the current line only if point is at the left margin or
 in the line's indentation; otherwise insert some whitespace[*].  If
 other than nil or t, then some whitespace[*] is inserted only within
-literals (comments and strings) and inside preprocessor directives,
-but the line is always reindented.
+literals (comments and strings), but the line is always reindented.
 
 If `c-syntactic-indentation' is t, indentation is done according to
 the syntactic context.  A numeric argument, regardless of its value,
 
 ;; Silence the compiler.
 (cc-bytecomp-defvar c-enable-xemacs-performance-kludge-p) ; In cc-vars.el
-(cc-bytecomp-defvar c-emacs-features)	; In cc-vars.el
 (cc-bytecomp-defun buffer-syntactic-context-depth) ; XEmacs
 (cc-bytecomp-defun region-active-p)	; XEmacs
 (cc-bytecomp-defvar zmacs-region-stays)	; XEmacs
 
 ;;; Variables also used at compile time.
 
-(defconst c-version "5.30.8"
+(defconst c-version "5.30.9"
   "CC Mode version number.")
 
 (defconst c-version-sym (intern c-version))
 		   (eq (char-before) ?\\)))
        (backward-char))))
 
+(eval-and-compile
+  (defvar c-langs-are-parametric nil))
+
 (defmacro c-major-mode-is (mode)
   "Return non-nil if the current CC Mode major mode is MODE.
 MODE is either a mode symbol or a list of mode symbols.
 
 This function does not do any hidden buffer changes."
-  (if (eq (car-safe mode) 'quote)
-      (let ((mode (eval mode)))
-	(if (listp mode)
-	    `(memq c-buffer-is-cc-mode ',mode)
-	  `(eq c-buffer-is-cc-mode ',mode)))
-    `(let ((mode ,mode))
-       (if (listp mode)
-	   (memq c-buffer-is-cc-mode mode)
-	 (eq c-buffer-is-cc-mode mode)))))
+
+  (if c-langs-are-parametric
+      ;; Inside a `c-lang-defconst'.
+      `(c-lang-major-mode-is ,mode)
+
+    (if (eq (car-safe mode) 'quote)
+	(let ((mode (eval mode)))
+	  (if (listp mode)
+	      `(memq c-buffer-is-cc-mode ',mode)
+	    `(eq c-buffer-is-cc-mode ',mode)))
+
+      `(let ((mode ,mode))
+	 (if (listp mode)
+	     (memq c-buffer-is-cc-mode mode)
+	   (eq c-buffer-is-cc-mode mode))))))
+
+(defmacro c-mode-is-new-awk-p ()
+  ;; Is the current mode the "new" awk mode?  It is important for
+  ;; (e.g.) the cc-engine functions do distinguish between the old and
+  ;; new awk-modes.
+  '(and (c-major-mode-is 'awk-mode)
+	(memq 'syntax-properties c-emacs-features)))
 
 (defmacro c-parse-sexp-lookup-properties ()
   ;; Return the value of the variable that says whether the
 This function does not do any hidden buffer changes."
   (symbol-value (c-mode-symbol suffix)))
 
-(defsubst c-mode-is-new-awk-p ()
-  ;; Is the current mode the "new" awk mode?  It is important for
-  ;; (e.g.) the cc-engine functions do distinguish between the old and
-  ;; new awk-modes.
-  (and (c-major-mode-is 'awk-mode)
-       (memq 'syntax-properties c-emacs-features)))
-
 (defsubst c-got-face-at (pos faces)
   "Return non-nil if position POS in the current buffer has any of the
 faces in the list FACES.
 (put 'c-make-keywords-re 'lisp-indent-function 1)
 
 
+;; Figure out what features this Emacs has
+
+(cc-bytecomp-defvar open-paren-in-column-0-is-defun-start)
+
+(defconst c-emacs-features
+  (let (list)
+
+    (if (boundp 'infodock-version)
+	;; I've no idea what this actually is, but it's legacy. /mast
+	(setq list (cons 'infodock list)))
+
+    ;; XEmacs 19 and beyond use 8-bit modify-syntax-entry flags.
+    ;; Emacs 19 uses a 1-bit flag.  We will have to set up our
+    ;; syntax tables differently to handle this.
+    (let ((table (copy-syntax-table))
+	  entry)
+      (modify-syntax-entry ?a ". 12345678" table)
+      (cond
+       ;; XEmacs 19, and beyond Emacs 19.34
+       ((arrayp table)
+	(setq entry (aref table ?a))
+	;; In Emacs, table entries are cons cells
+	(if (consp entry) (setq entry (car entry))))
+       ;; XEmacs 20
+       ((fboundp 'get-char-table) (setq entry (get-char-table ?a table)))
+       ;; before and including Emacs 19.34
+       ((and (fboundp 'char-table-p)
+	     (char-table-p table))
+	(setq entry (car (char-table-range table [?a]))))
+       ;; incompatible
+       (t (error "CC Mode is incompatible with this version of Emacs")))
+      (setq list (cons (if (= (logand (lsh entry -16) 255) 255)
+			   '8-bit
+			 '1-bit)
+		       list)))
+
+    (let ((buf (generate-new-buffer " test"))
+	  parse-sexp-lookup-properties
+	  parse-sexp-ignore-comments
+	  lookup-syntax-properties)
+      (save-excursion
+	(set-buffer buf)
+	(set-syntax-table (make-syntax-table))
+
+	;; For some reason we have to set some of these after the
+	;; buffer has been made current.  (Specifically,
+	;; `parse-sexp-ignore-comments' in Emacs 21.)
+	(setq parse-sexp-lookup-properties t
+	      parse-sexp-ignore-comments t
+	      lookup-syntax-properties t)
+
+	;; Find out if the `syntax-table' text property works.
+	(modify-syntax-entry ?< ".")
+	(modify-syntax-entry ?> ".")
+	(insert "<()>")
+	(c-mark-<-as-paren 1)
+	(c-mark->-as-paren 4)
+	(goto-char 1)
+	(c-forward-sexp)
+	(if (= (point) 5)
+	    (setq list (cons 'syntax-properties list)))
+
+	;; Find out if generic comment delimiters work.
+	(c-safe
+	  (modify-syntax-entry ?x "!")
+	  (if (string-match "\\s!" "x")
+	      (setq list (cons 'gen-comment-delim list))))
+
+	;; Find out if generic string delimiters work.
+	(c-safe
+	  (modify-syntax-entry ?x "|")
+	  (if (string-match "\\s|" "x")
+	      (setq list (cons 'gen-string-delim list))))
+
+	;; See if POSIX char classes work.
+	(when (and (string-match "[[:alpha:]]" "a")
+		   ;; All versions of Emacs 21 so far haven't fixed
+		   ;; char classes in `skip-chars-forward' and
+		   ;; `skip-chars-backward'.
+		   (progn
+		     (delete-region (point-min) (point-max))
+		     (insert "foo123")
+		     (skip-chars-backward "[:alnum:]")
+		     (bobp))
+		   (= (skip-chars-forward "[:alpha:]") 3))
+	  (setq list (cons 'posix-char-classes list)))
+
+	;; See if `open-paren-in-column-0-is-defun-start' exists and
+	;; isn't buggy.
+	(when (boundp 'open-paren-in-column-0-is-defun-start)
+	  (let ((open-paren-in-column-0-is-defun-start nil)
+		(parse-sexp-ignore-comments t))
+	    (delete-region (point-min) (point-max))
+	    (set-syntax-table (make-syntax-table))
+	    (modify-syntax-entry ?\' "\"")
+	    (cond
+	     ;; XEmacs.  Afaik this is currently an Emacs-only
+	     ;; feature, but it's good to be prepared.
+	     ((memq '8-bit list)
+	      (modify-syntax-entry ?/ ". 1456")
+	      (modify-syntax-entry ?* ". 23"))
+	     ;; Emacs
+	     ((memq '1-bit list)
+	      (modify-syntax-entry ?/ ". 124b")
+	      (modify-syntax-entry ?* ". 23")))
+	    (modify-syntax-entry ?\n "> b")
+	    (insert "/* '\n   () */")
+	    (backward-sexp)
+	    (if (bobp)
+		(setq list (cons 'col-0-paren list)))))
+
+	(set-buffer-modified-p nil))
+      (kill-buffer buf))
+
+    ;; See if `parse-partial-sexp' returns the eighth element.
+    (when (c-safe (>= (length (save-excursion (parse-partial-sexp 1 1))) 10))
+      (setq list (cons 'pps-extended-state list)))
+
+    ;;(message "c-emacs-features: %S" list)
+    list)
+  "A list of certain features in the (X)Emacs you are using.
+There are many flavors of Emacs out there, each with different
+features supporting those needed by CC Mode.  The following values
+might be present:
+
+'8-bit              8 bit syntax entry flags (XEmacs style).
+'1-bit              1 bit syntax entry flags (Emacs style).
+'syntax-properties  It works to override the syntax for specific characters
+		    in the buffer with the 'syntax-table property.
+'gen-comment-delim  Generic comment delimiters work
+		    (i.e. the syntax class `!').
+'gen-string-delim   Generic string delimiters work
+		    (i.e. the syntax class `|').
+'pps-extended-state `parse-partial-sexp' returns a list with at least 10
+		    elements, i.e. it contains the position of the
+		    start of the last comment or string.
+'posix-char-classes The regexp engine understands POSIX character classes.
+'col-0-paren        It's possible to turn off the ad-hoc rule that a paren
+		    in column zero is the start of a defun.
+'infodock           This is Infodock (based on XEmacs).
+
+'8-bit and '1-bit are mutually exclusive.")
+
+
 ;;; Some helper constants.
 
-;; If the regexp engine supports POSIX char classes (e.g. Emacs 21)
-;; then we can use them to handle extended charsets correctly.
-(if (string-match "[[:alpha:]]" "a")	; Can't use c-emacs-features here.
+;; If the regexp engine supports POSIX char classes then we can use
+;; them to handle extended charsets correctly.
+(if (memq 'posix-char-classes c-emacs-features)
     (progn
       (defconst c-alpha "[:alpha:]")
       (defconst c-alnum "[:alnum:]")
     (error "The mode name symbol `%s' must end with \"-mode\"" mode))
   (put mode 'c-mode-prefix (match-string 1 (symbol-name mode)))
   (unless (get base-mode 'c-mode-prefix)
-    (error "Unknown base mode `%s'" base-mode)
-    (put mode 'c-fallback-mode base-mode)))
+    (error "Unknown base mode `%s'" base-mode))
+  (put mode 'c-fallback-mode base-mode))
 
 (defvar c-lang-constants (make-vector 151 0))
 ;; This obarray is a cache to keep track of the language constants
 ;; various other symbols, but those don't have any variable bindings.
 
 (defvar c-lang-const-expansion nil)
-(defvar c-langs-are-parametric nil)
 
 (defsubst c-get-current-file ()
   ;; Return the base name of the current file.
 
       c-lang-constants)))
 
+(defun c-lang-major-mode-is (mode)
+  ;; `c-major-mode-is' expands to a call to this function inside
+  ;; `c-lang-defconst'.  Here we also match the mode(s) against any
+  ;; fallback modes for the one in `c-buffer-is-cc-mode', so that
+  ;; e.g. (c-major-mode-is 'c++-mode) is true in a derived language
+  ;; that has c++-mode as base mode.
+  (unless (listp mode)
+    (setq mode (list mode)))
+  (let (match (buf-mode c-buffer-is-cc-mode))
+    (while (if (memq buf-mode mode)
+	       (progn
+		 (setq match t)
+		 nil)
+	     (setq buf-mode (get buf-mode 'c-fallback-mode))))
+    match))
+
 
 (cc-provide 'cc-defs)
 

File cc-engine.el

 
   (when (and (= beg end)
 	     (get-text-property beg 'c-in-sws)
-	     (not (bobp))
+	     (> beg (point-min))
 	     (get-text-property (1- beg) 'c-in-sws))
     ;; Ensure that an `c-in-sws' range gets broken.  Note that it isn't
     ;; safe to keep a range that was continuous before the change.  E.g:
 	(if last-pos
 	    ;; Prepare to loop, but record the open paren only if it's
 	    ;; outside a macro or within the same macro as point, and
-	    ;; if it is a "real" open paren and not some character
+	    ;; if it is a legitimate open paren and not some character
 	    ;; that got an open paren syntax-table property.
 	    (progn
 	      (setq pos last-pos)
 			   (save-excursion
 			     (goto-char last-pos)
 			     (not (c-beginning-of-macro))))
-		       (= (char-syntax (char-before last-pos)) ?\())
+		       ;; Check for known types of parens that we want
+		       ;; to record.  The syntax table is not to be
+		       ;; trusted here since the caller might be using
+		       ;; e.g. `c++-template-syntax-table'.
+		       (memq (char-before last-pos) '(?{ ?\( ?\[)))
 		  (setq c-state-cache (cons (1- last-pos) c-state-cache))))
 
 	  (if (setq last-pos (c-up-list-forward pos))
 	(when (c-major-mode-is 'pike-mode)
 	  ;; Handle the `<operator> syntax in Pike.
 	  (let ((pos (point)))
-	    (skip-chars-backward "!%&*+\\-/<=>^|~[]()")
+	    (skip-chars-backward "-!%&*+/<=>^|~[]()")
 	    (and (if (< (skip-chars-backward "`") 0)
 		     t
 		   (goto-char pos)
       (and (c-major-mode-is 'pike-mode)
 	   ;; Handle the `<operator> syntax in Pike.
 	   (let ((pos (point)))
-	     (if (and (< (skip-chars-backward "!%&*+\\-/<=>^|~[]()") 0)
+	     (if (and (< (skip-chars-backward "-!%&*+/<=>^|~[]()") 0)
 		      (< (skip-chars-backward "`") 0)
 		      (looking-at c-symbol-key)
 		      (>= (match-end 0) pos))
 that region is taken as syntactically significant text.
 
 If PAREN-LEVEL is non-nil, an additional restriction is added to
-ignore matches in nested paren sexps, and the search will also not go
-outside the current paren sexp.
+ignore matches in nested paren sexps.  The search will also not go
+outside the current list sexp, which has the effect that if the point
+should be moved to BOUND when no match is found \(i.e. NOERROR is
+neither nil nor t), then it will be at the closing paren if the end of
+the current list sexp is encountered first.
 
 If NOT-INSIDE-TOKEN is non-nil, matches in the middle of tokens are
 ignored.  Things like multicharacter operators and special symbols
 might be a good idea to include \\=\\= as a match alternative in it.
 
 Optimization note: Matches might be missed if the \"look behind\"
-subexpression should match the end of nonwhite syntactic whitespace,
+subexpression can match the end of nonwhite syntactic whitespace,
 i.e. the end of comments or cpp directives.  This since the function
-skips over such things before resuming the search.  It's also not safe
-to assume that the \"look behind\" subexpression never can match
-syntactic whitespace."
+skips over such things before resuming the search.  It's on the other
+hand not safe to assume that the \"look behind\" subexpression never
+matches syntactic whitespace.
+
+Bug: Unbalanced parens inside cpp directives are currently not handled
+correctly \(i.e. they don't get ignored as they should) when
+PAREN-LEVEL is set."
 
   (or bound (setq bound (point-max)))
   (if paren-level (setq paren-level -1))
   ;;(message "c-syntactic-re-search-forward %s %s %S" (point) bound regexp)
 
   (let ((start (point))
-	(pos (point))
+	tmp
+	;; Start position for the last search.
+	search-pos
+	;; The `parse-partial-sexp' state between the start position
+	;; and the point.
+	state
+	;; The current position after the last state update.  The next
+	;; `parse-partial-sexp' continues from here.
+	(state-pos (point))
+	;; The position at which to check the state and the state
+	;; there.  This is separate from `state-pos' since we might
+	;; need to back up before doing the next search round.
+	check-pos check-state
+	;; Last position known to end a token.
 	(last-token-end-pos (point-min))
-	match-pos found state check-pos check-state tmp)
+	;; Set when a valid match is found.
+	found)
 
     (condition-case err
 	(while
 	    (and
-	     (re-search-forward regexp bound noerror)
-
 	     (progn
-	       (setq match-pos (point)
-		     state (parse-partial-sexp
-			    pos (match-beginning 0) paren-level nil state)
-		     pos (point))
+	       (setq search-pos (point))
+	       (re-search-forward regexp bound noerror))
+
+	     (progn
+	       (setq state (parse-partial-sexp
+			    state-pos (match-beginning 0) paren-level nil state)
+		     state-pos (point))
 	       (if (setq check-pos (and lookbehind-submatch
+					(or (not paren-level)
+					    (>= (car state) 0))
 					(match-end lookbehind-submatch)))
 		   (setq check-state (parse-partial-sexp
-				      pos check-pos paren-level nil state))
-		 (setq check-pos pos
+				      state-pos check-pos paren-level nil state))
+		 (setq check-pos state-pos
 		       check-state state))
 
-	       ;; If we got a look behind subexpression and get an
-	       ;; insignificant match in something that isn't
+	       ;; NOTE: If we got a look behind subexpression and get
+	       ;; an insignificant match in something that isn't
 	       ;; syntactic whitespace (i.e. strings or in nested
 	       ;; parentheses), then we can never skip more than a
-	       ;; single character from the match position before
-	       ;; continuing the search.  That since the look behind
-	       ;; subexpression might match the end of the
-	       ;; insignificant region.
+	       ;; single character from the match start position
+	       ;; (i.e. `state-pos' here) before continuing the
+	       ;; search.  That since the look behind subexpression
+	       ;; might match the end of the insignificant region in
+	       ;; the next search.
 
 	       (cond
-		((setq tmp (elt check-state 3))
-		 ;; Match inside a string.
-		 (if (or lookbehind-submatch
-			 (not (integerp tmp)))
-		     (goto-char (min (1+ pos) bound))
-		   ;; Skip to the end of the string before continuing.
-		   (let ((ender (make-string 1 tmp)) (continue t))
-		     (while (if (search-forward ender bound noerror)
-				(progn
-				  (setq state (parse-partial-sexp
-					       pos (point) nil nil state)
-					pos (point))
-				  (elt state 3))
-			      (setq continue nil)))
-		     continue)))
-
 		((elt check-state 7)
 		 ;; Match inside a line comment.  Skip to eol.  Use
 		 ;; `re-search-forward' instead of `skip-chars-forward' to get
 
 		((and (not (elt check-state 5))
 		      (eq (char-before check-pos) ?/)
+		      (not (c-get-char-property (1- check-pos) 'syntax-table))
 		      (memq (char-after check-pos) '(?/ ?*)))
 		 ;; Match in the middle of the opener of a block or line
 		 ;; comment.
 		     (re-search-forward "[\n\r]" bound noerror)
 		   (search-forward "*/" bound noerror)))
 
+		;; The last `parse-partial-sexp' above might have
+		;; stopped short of the real check position if the end
+		;; of the current sexp was encountered in paren-level
+		;; mode.  The checks above are always false in that
+		;; case, and since they can do better skipping in
+		;; lookbehind-submatch mode, we do them before
+		;; checking the paren level.
+
+		((and paren-level
+		      (/= (setq tmp (car check-state)) 0))
+		 ;; Check the paren level first since we're short of the
+		 ;; syntactic checking position if the end of the
+		 ;; current sexp was encountered by `parse-partial-sexp'.
+		 (if (> tmp 0)
+
+		     ;; Inside a nested paren sexp.
+		     (if lookbehind-submatch
+			 ;; See the NOTE above.
+			 (progn (goto-char state-pos) t)
+		       ;; Skip out of the paren quickly.
+		       (setq state (parse-partial-sexp state-pos bound 0 nil state)
+			     state-pos (point)))
+
+		   ;; Have exited the current paren sexp.
+		   (if noerror
+		       (progn
+			 ;; The last `parse-partial-sexp' call above
+			 ;; has left us just after the closing paren
+			 ;; in this case, so we can modify the bound
+			 ;; to leave the point at the right position
+			 ;; upon return.
+			 (setq bound (1- (point)))
+			 nil)
+		     (signal 'search-failed (list regexp)))))
+
+		((setq tmp (elt check-state 3))
+		 ;; Match inside a string.
+		 (if (or lookbehind-submatch
+			 (not (integerp tmp)))
+		     ;; See the NOTE above.
+		     (progn (goto-char state-pos) t)
+		   ;; Skip to the end of the string before continuing.
+		   (let ((ender (make-string 1 tmp)) (continue t))
+		     (while (if (search-forward ender bound noerror)
+				(progn
+				  (setq state (parse-partial-sexp
+					       state-pos (point) nil nil state)
+					state-pos (point))
+				  (elt state 3))
+			      (setq continue nil)))
+		     continue)))
+
+		((save-excursion
+		   (save-match-data
+		     (c-beginning-of-macro start)))
+		 ;; Match inside a macro.  Skip to the end of it.
+		 (c-end-of-macro)
+		 (cond ((<= (point) bound) t)
+		       (noerror nil)
+		       (t (signal 'search-failed (list regexp)))))
+
 		((and not-inside-token
 		      (or (< check-pos last-token-end-pos)
 			  (< check-pos
 			       (save-match-data
 				 (c-end-of-current-token last-token-end-pos))
 			       (setq last-token-end-pos (point))))))
-		 ;; Match inside a token.
-		 (cond ((<= (point) bound)
-			(goto-char (min (1+ pos) bound))
-			t)
-		       (noerror nil)
-		       (t (signal 'search-failed "end of token"))))
-
-		((save-excursion
-		   (save-match-data
-		     (c-beginning-of-macro start)))
-		 ;; Match inside a macro.  Skip to the end of it.
-		 (c-end-of-macro)
-		 (cond ((<= (point) bound) t)
-		       (noerror nil)
-		       (t (signal 'search-failed "end of macro"))))
-
-		((and paren-level
-		      (/= (setq tmp (car check-state)) 0))
-		 (if (> tmp 0)
-		     ;; Match inside a nested paren sexp.
-		     (if lookbehind-submatch
-			 (goto-char (min (1+ pos) bound))
-		       ;; Skip out of the paren quickly.
-		       (setq state (parse-partial-sexp pos bound 0 nil state)
-			     pos (point)))
-		   ;; Have exited the current paren sexp.  The
-		   ;; `parse-partial-sexp' above has left us just after the
-		   ;; closing paren in this case.  Just make
-		   ;; `re-search-forward' above fail in the appropriate way;
-		   ;; we'll adjust the leave off point below if necessary.
-		   (setq bound (point))))
+		 ;; Inside a token.
+		 (if lookbehind-submatch
+		     ;; See the NOTE above.
+		     (goto-char state-pos)
+		   (goto-char (min last-token-end-pos bound))))
 
 		(t
 		 ;; A real match.
 		 (setq found t)
-		 nil)))))
+		 nil)))
+
+	     ;; Should loop to search again, but take care to avoid
+	     ;; looping on the same spot.
+	     (or (/= search-pos (point))
+		 (if (= (point) bound)
+		     (if noerror
+			 nil
+		       (signal 'search-failed (list regexp)))
+		   (forward-char)
+		   t))))
 
       (error
        (goto-char start)
        (signal (car err) (cdr err))))
 
-    ;;(message "c-syntactic-re-search-forward done %s" (or match-pos (point)))
+    ;;(message "c-syntactic-re-search-forward done %s" (or (match-end 0) (point)))
 
     (if found
 	(progn
-	  (goto-char match-pos)
-	  match-pos)
+	  (goto-char (match-end 0))
+	  (match-end 0))
 
       ;; Search failed.  Set point as appropriate.
-      (cond ((eq noerror t)
-	     (goto-char start))
-	    (paren-level
-	     (if (eq (car (parse-partial-sexp pos bound -1 nil state)) -1)
-		 (backward-char)))
-	    (t
-	     (goto-char bound)))
+      (if (eq noerror t)
+	  (goto-char start)
+	(goto-char bound))
       nil)))
 
 (defun c-syntactic-skip-backward (skip-chars &optional limit)
 (defun c-forward-type ()
   ;; Move forward over a type spec if at the beginning of one,
   ;; stopping at the next following token.  Return t if it's a known
-  ;; type that can't be a name, 'known if it's an otherwise known type
-  ;; (according to `*-font-lock-extra-types'), 'prefix if it's a known
-  ;; prefix of a type, 'found if it's a type that matches one in
-  ;; `c-found-types', 'maybe if it's an identfier that might be a
-  ;; type, or nil if it can't be a type (the point isn't moved then).
-  ;; The point is assumed to be at the beginning of a token.
+  ;; type that can't be a name or other expression, 'known if it's an
+  ;; otherwise known type (according to `*-font-lock-extra-types'),
+  ;; 'prefix if it's a known prefix of a type, 'found if it's a type
+  ;; that matches one in `c-found-types', 'maybe if it's an identfier
+  ;; that might be a type, or nil if it can't be a type (the point
+  ;; isn't moved then).  The point is assumed to be at the beginning
+  ;; of a token.
   ;;
   ;; Note that this function doesn't skip past the brace definition
   ;; that might be considered part of the type, e.g.
 		;; don't let the existence of the operator itself promote two
 		;; uncertain types to a certain one.
 		(cond ((eq res t))
-		      ((or (eq res 'known) (memq res2 '(t known)))
+		      ((eq res2 t)
 		       (c-add-type id-start id-end)
 		       (when c-record-type-identifiers
 			 (c-record-type-id id-range))
 		       (setq res t))
+		      ((eq res 'known))
+		      ((eq res2 'known)
+		       (setq res 'known))
 		      ((eq res 'found))
 		      ((eq res2 'found)
 		       (setq res 'found))
 
       ;; `c-beginning-of-statement-1' stops at a block start, but we
       ;; want to continue if the block doesn't begin a top level
-      ;; construct, i.e. if it isn't preceded by ';', '}', ':', or bob.
+      ;; construct, i.e. if it isn't preceded by ';', '}', ':', bob,
+      ;; or an open paren.
       (let ((beg (point)) tentative-move)
 	(while (and
 		;; Must check with c-opt-method-key in ObjC mode.
 		(progn
 		  (c-backward-syntactic-ws lim)
 		  (not (memq (char-before) '(?\; ?} ?: nil))))
+		(save-excursion
+		  (backward-char)
+		  (not (looking-at "\\s(")))
 		;; Check that we don't move from the first thing in a
 		;; macro to its header.
 		(not (eq (setq tentative-move
       (condition-case ()
 	  (save-excursion
 	    (let ((beg (point))
-		  end type)
+		  inner-beg end type)
 	      (c-forward-syntactic-ws)
 	      (if (eq (char-after) ?\()
 		  (progn
 		    (forward-char 1)
 		    (c-forward-syntactic-ws)
+		    (setq inner-beg (point))
 		    (setq type (assq (char-after) c-special-brace-lists)))
 		(if (setq type (assq (char-after) c-special-brace-lists))
 		    (progn
+		      (setq inner-beg (point))
 		      (c-backward-syntactic-ws)
 		      (forward-char -1)
 		      (setq beg (if (eq (char-after) ?\()
 				    (point)
 				  nil)))))
 	      (if (and beg type)
-		  (if (and (c-safe (goto-char beg)
+		  (if (and (c-safe
+			     (goto-char beg)
+			     (c-forward-sexp 1)
+			     (setq end (point))
+			     (= (char-before) ?\)))
+			   (c-safe
+			     (goto-char inner-beg)
+			     (if (looking-at "\\s(")
+				 ;; Check balancing of the inner paren
+				 ;; below.
+				 (progn
 				   (c-forward-sexp 1)
-				   (setq end (point))
-				   (= (char-before) ?\)))
-			   (c-safe (goto-char beg)
-				   (forward-char 1)
-				   (c-forward-sexp 1)
-				   ;; Kludges needed to handle inner
-				   ;; chars both with and without
-				   ;; paren syntax.
-				   (or (/= (char-syntax (char-before)) ?\))
-				       (= (char-before) (cdr type)))))
+				   t)
+			       ;; If the inner char isn't a paren then
+			       ;; we can't check balancing, so just
+			       ;; check the char before the outer
+			       ;; closing paren.
+			       (goto-char end)
+			       (backward-char)
+			       (c-backward-syntactic-ws)
+			       (= (char-before) (cdr type)))))
 		      (if (or (/= (char-syntax (char-before)) ?\))
 			      (= (progn
 				   (c-forward-syntactic-ws)
 	    (goto-char containing-sexp)
 	    (setq placeholder (c-point 'boi))
 	    (if (and (c-safe (backward-up-list 1) t)
-		     (> (point) placeholder))
+		     (>= (point) placeholder))
 		(progn
 		  (forward-char)
 		  (skip-chars-forward " \t"))
 	    (goto-char containing-sexp)
 	    (setq placeholder (c-point 'boi))
 	    (when (and (c-safe (backward-up-list 1) t)
-		       (> (point) placeholder))
+		       (>= (point) placeholder))
 	      (forward-char)
 	      (skip-chars-forward " \t")
 	      (setq placeholder (point)))
 	    (goto-char containing-sexp)
 	    (setq placeholder (c-point 'boi))
 	    (if (and (c-safe (backward-up-list 1) t)
-		     (> (point) placeholder))
+		     (>= (point) placeholder))
 		(progn
 		  (forward-char)
 		  (skip-chars-forward " \t"))
    ((vectorp offset)       offset)
    ((null offset)          nil)
    ((listp offset)
+    (if (eq (car offset) 'quote)
+	(error
+"Setting in c-offsets-alist element \"(%s . '%s)\" was mistakenly quoted"
+         symbol (cadr offset)))
     (let (done)
       (while (and (not done) offset)
 	(setq done (c-evaluate-offset (car offset) langelem symbol)
       ;; Fontify leading identifiers in fully qualified names like
       ;; "foo::bar" in languages that supports such things.
       ,@(when (c-lang-const c-opt-identifier-concat-key)
-	  `((,(byte-compile
-	       ;; Must use a function here since we match longer
-	       ;; than we want to move before doing a new search.
-	       ;; This is not necessary for XEmacs >= 20 since it
-	       ;; restarts the search from the end of the first
-	       ;; highlighted submatch (something that causes
-	       ;; problems in other places).
-	       `(lambda (limit)
-		  (while (re-search-forward
-			  ,(concat "\\(\\<" ; 1
-				   "\\(" (c-lang-const c-symbol-key) "\\)" ; 2
-				   "[ \t\n\r\f\v]*"
-				   (c-lang-const c-opt-identifier-concat-key)
-				   "[ \t\n\r\f\v]*"
-				   "\\)"
-				   "\\("
-				   (c-lang-const c-opt-after-id-concat-key)
-				   "\\)")
-			  limit t)
-		    (unless (progn
-			      (goto-char (match-beginning 0))
-			      (c-skip-comments-and-strings limit))
-		      (or (get-text-property (match-beginning 2) 'face)
-			  (c-put-font-lock-face (match-beginning 2)
-						(match-end 2)
-						c-reference-face-name))
-		      (goto-char (match-end 1)))))))))
+	  (if (c-major-mode-is 'java-mode)
+	      ;; Java needs special treatment since "." is used both to
+	      ;; qualify names and in normal indexing.  Here we look for
+	      ;; capital characters at the beginning of an identifier to
+	      ;; recognize the class.  "*" is also recognized to cover
+	      ;; wildcard import declarations.  All preceding dot separated
+	      ;; identifiers are taken as package names and therefore
+	      ;; fontified as references.
+	      `(,(c-make-font-lock-search-function
+		  ;; Search for class identifiers preceded by ".".  The
+		  ;; anchored matcher takes it from there.
+		  (concat (c-lang-const c-opt-identifier-concat-key)
+			  "[ \t\n\r\f\v]*"
+			  (concat "\\("
+				  "[" c-upper "][" (c-lang-const c-symbol-chars) "]*"
+				  "\\|"
+				  "\\*"
+				  "\\)"))
+		  `((let (id-end)
+		      (goto-char (1+ (match-beginning 0)))
+		      (while (and (eq (char-before) ?.)
+				  (progn
+				    (backward-char)
+				    (c-backward-syntactic-ws)
+				    (setq id-end (point))
+				    (< (skip-chars-backward
+					,(c-lang-const c-symbol-chars)) 0))
+				  (not (get-text-property (point) 'face)))
+			(c-put-font-lock-face (point) id-end c-reference-face-name)
+			(c-backward-syntactic-ws)))
+		    nil
+		    (goto-char (match-end 0)))))
+
+	    `((,(byte-compile
+		 ;; Must use a function here since we match longer than we
+		 ;; want to move before doing a new search.  This is not
+		 ;; necessary for XEmacs >= 20 since it restarts the search
+		 ;; from the end of the first highlighted submatch (something
+		 ;; that causes problems in other places).
+		 `(lambda (limit)
+		    (while (re-search-forward
+			    ,(concat "\\(\\<" ; 1
+				     "\\(" (c-lang-const c-symbol-key) "\\)" ; 2
+				     "[ \t\n\r\f\v]*"
+				     (c-lang-const c-opt-identifier-concat-key)
+				     "[ \t\n\r\f\v]*"
+				     "\\)"
+				     "\\("
+				     (c-lang-const c-opt-after-id-concat-key)
+				     "\\)")
+			    limit t)
+		      (unless (progn
+				(goto-char (match-beginning 0))
+				(c-skip-comments-and-strings limit))
+			(or (get-text-property (match-beginning 2) 'face)
+			    (c-put-font-lock-face (match-beginning 2)
+						  (match-end 2)
+						  c-reference-face-name))
+			(goto-char (match-end 1))))))))))
 
       ;; Fontify the special declarations in Objective-C.
       ,@(when (c-major-mode-is 'objc-mode)
 	    (<= (point) limit)
 
 	    ;; Search syntactically to the end of the declarator (";",
-	    ;; ",", ")", ">" (for <> arglists), eob etc) or to the
-	    ;; beginning of an initializer or function prototype ("="
-	    ;; or "\\s\(").
+	    ;; ",", a closen paren, eob etc) or to the beginning of an
+	    ;; initializer or function prototype ("=" or "\\s\(").
+	    ;; Note that the open paren will match array specs in
+	    ;; square brackets, and we treat them as initializers too.
 	    (c-syntactic-re-search-forward
-	     "[\];,\{\}\[\)>]\\|\\'\\|\\(=\\|\\(\\s\(\\)\\)" limit t t))
+	     "[;,]\\|\\s)\\|\\'\\|\\(=\\|\\s(\\)" limit t t))
 
       (setq next-pos (match-beginning 0)
-	    id-face (if (match-beginning 2)
+	    id-face (if (eq (char-after next-pos) ?\()
 			'font-lock-function-name-face
 		      'font-lock-variable-name-face)
-	    got-init (match-beginning 1))
+	    got-init (and (match-beginning 1)
+			  (char-after (match-beginning 1))))
 
       (if types
 	  ;; Register and fontify the identifer as a type.
 		 (goto-char limit)))
 
 	      (got-init
-	       ;; Skip an initializer expression.
-	       (if (c-syntactic-re-search-forward "[;,]" limit 'move t)
-		   (backward-char)))
+	       ;; Skip an initializer expression.  If we're at a '='
+	       ;; then accept a brace list directly after it to cope
+	       ;; with array initializers.  Otherwise stop at braces
+	       ;; to avoid going past full function and class blocks.
+	       (and (if (and (eq got-init ?=)
+			     (= (c-forward-token-2) 0)
+			     (looking-at "{"))
+			(c-safe (c-forward-sexp) t)
+		      t)
+		    (c-syntactic-re-search-forward "[;,{]" limit 'move t)
+		    (backward-char)))
 
 	      (t (c-forward-syntactic-ws limit)))
 
 not contain a \\| operator at the top level."
   t    nil
   c++  "::"
+  ;; Java has "." to concatenate identifiers but it's also used for
+  ;; normal indexing.  There's special code in the Java font lock
+  ;; rules to fontify qualified identifiers based on the standard
+  ;; naming conventions.  We still define "." here to make
+  ;; `c-forward-name' move over as long names as possible which is
+  ;; necessary to e.g. handle throws clauses correctly.
   java "\\."
   idl  "::"
   pike "\\(::\\|\\.\\)")

File cc-mode.texi

 @syncodeindex ss cp
 @syncodeindex ky cp
 
-@macro copyrightblurb
+@copying
 Copyright @copyright{} 1995, 96, 97, 98, 99, 2000, 01, 02, 03 Free Software Foundation, Inc.
-@end macro
+@end copying
 
 @comment Info directory entry for use by install-info. The indentation
 @comment here is by request from the FSF folks.
 @end direntry
 
 @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-@comment The following lines inserts the copyright notice
-@comment into the Info file.
-@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-
-@ifnottex
-@copyrightblurb
-@end ifnottex
-
-@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 @comment TeX title page
 @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
 
 @page
 @vskip 0pt plus 1filll
-@copyrightblurb
+@insertcopying
 @end titlepage
 
 @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 @findex idl-mode
 @findex pike-mode
 @findex awk-mode
-Note that the name of this package is ``@ccmode{}'', but there is no top
+Note that the name of this package is ``@ccmode{},'' but there is no top
 level @code{cc-mode} entry point.  All of the variables, commands, and
 functions in @ccmode{} are prefixed with @code{c-@var{thing}}, and
 @code{c-mode}, @code{c++-mode}, @code{objc-mode}, @code{java-mode},
 @findex toggle-hungry-state (c-)
 @findex toggle-auto-state (c-)
 @findex toggle-auto-hungry-state (c-)
-@ccmode{} provides keybindings which allow you to toggle the minor
+@ccmode{} provides key bindings which allow you to toggle the minor
 modes on the fly while editing code.  To toggle just the auto-newline
 state, hit @kbd{C-c C-a} (bound to @code{c-toggle-auto-state}).  When
 you do this, you should see the @samp{a} indicator either appear or
 @dfn{Clean-ups} are mechanisms complementary to colon and brace hanging.
 On the surface, it would seem that clean-ups overlap the functionality
 provided by the @code{c-hanging-*-alist} variables.  Clean-ups are
-however used to adjust code ``after-the-fact'', i.e. to adjust the
+however used to adjust code ``after-the-fact,'' i.e. to adjust the
 whitespace in constructs after they are typed.
 
 Most of the clean-ups are only applicable to counteract automatically
 @findex setup-paragraph-variables (c-)
 Also note that since @ccmode{} uses the value of
 @code{c-comment-prefix-regexp} to set up several other variables at mode
-initialization, there won't have any effect if you change it inside a
+initialization, there won't be any effect if you just change it inside a
 @ccmode{} buffer.  You need to call the command
-@code{c-setup-paragraph-variables} to update those other variables with
+@code{c-setup-paragraph-variables} too, to update those other variables with
 the new value.  That's also the case if you modify this variable in a
 mode hook, since @ccmode{} sets up all variables before calling them.
 @end defopt
 variable@footnote{In versions before 5.26, this variable was called
 @code{c-comment-continuation-stars}.  As a compatibility measure,
 @ccmode{} still uses the value on that variable if it's set.} is used
-then as the comment prefix.  It defaults to @samp{* }, which makes a
-comment
+then as the comment prefix.  It defaults to @samp{*
+}@footnote{Actually, this default setting of
+@code{c-block-comment-prefix} typically gets overriden by the default
+style @code{gnu}, which sets it to blank.  You can see the line
+splitting effect described here by setting a different style,
+e.g. @code{k&r} @xref{Choosing a Style}}, which makes a comment
 
 @example
 /* Got O(n^2) here, which is a Bad Thing. */
 @vindex tab-always-indent (c-)
 @kindex TAB
 @cindex literal
-This variable controls how @kbd{TAB} (@code{c-indent-command}) operates.
-When it is @code{t}, @kbd{TAB} always indents the current line.  When it
-is @code{nil}, the line is indented only if point is at the left margin,
-or on or before the first non-whitespace character on the line,
-otherwise some whitespace is inserted.  If this variable is the symbol
-@code{other}, then some whitespace is inserted only within strings and
-comments (literals), and inside preprocessor directives, but the line is
+This variable controls how @kbd{TAB} (@code{c-indent-command})
+operates.  When it is @code{t}, @kbd{TAB} always indents the current
+line.  When it is @code{nil}, the line is indented only if point is at
+the left margin, or on or before the first non-whitespace character on
+the line, otherwise some whitespace is inserted.  If this variable is
+some other value (not @code{nil} or @code{t}), then some whitespace is
+inserted only within strings and comments (literals), but the line is
 always reindented.
 @end defopt
 
 @item ellemtel
 @cindex Ellemtel style
 Popular C++ coding standards as defined by ``Programming in C++, Rules
-and Recommendations'', Erik Nyquist and Mats Henricson,
+and Recommendations,'' Erik Nyquist and Mats Henricson,
 Ellemtel@footnote{This document is available at
 @uref{http://www.doc.ic.ac.uk/lab/cplus/c++.rules/} among other
 places.}.
 @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 @node    Adding Styles, File Styles, Choosing a Style, Styles
 @comment node-name, next, previous, up
-@subsection Adding Styles
+@subsection Adding and Amending Styles
 @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
 If none of the built-in styles is appropriate, you'll probably want to
-add a new @dfn{style definition}.  Styles are kept in the
-@code{c-style-alist} variable, but you should never modify this
-variable directly.  Instead, @ccmode{} provides the function
-@code{c-add-style} that you can use to easily add new styles or change
-existing styles:
+create a new @dfn{style definition}, possibly based on an existing
+style.  To do this, put the new style's settings into a list with the
+following format - the list can then be passed as an argument to the
+function @code{c-add-style}:
+
+@cindex style definition
+@defvr {List} style definition
+([@var{base-style}] [(@var{variable} . @var{value}) @dots{}])
+
+Optional @var{base-style}, if present, must be a string which is the
+name of the @dfn{base style} from which this style inherits.  At most
+one @var{base-style} is allowed in a style definition.  If
+@var{base-style} is not specified, the style inherits from a table of
+default values@footnote{This table is stored internally in the
+variable c-fallback-style.  It is computed during the initialisation
+of @ccmode{} from the factory defaults of the style variables and any
+global values they may have been given since starting Emacs.} instead.
+All styles eventually inherit from this internal table.  Style loops
+generate errors.  The list of pre-existing styles can be seen in
+@ref{Built-in Styles}.
+
+The dotted pairs (@var{variable} . @var{value}) each consist of a
+variable and the value it is to be set to when the style is later
+activated.@footnote{In certain circumstances, this value can get
+overridden by another value.}  The variable can be either a @ccmode{}
+style variable or an arbitrary Emacs variable.  In the latter case, it
+is @emph{not} made buffer local by the @ccmode{} style system.
+@end defvr
+
+Two variables are treated specially in the dotted pair list:
+
+@table @code
+@item c-offsets-alist
+The value is in turn a dotted list on the form
+
+(@var{syntactic-symbol} . @var{offset})
+
+as described in @ref{Customizing Indentation}.  These are passed to
+@code{c-set-offset} so there is no need to set every syntactic symbol in
+your style, only those that are different from the inherited style.
+
+@item c-special-indent-hook
+The value is added to @code{c-special-indent-hook} using
+@code{add-hook}, so any functions already on it are kept.  If the value
+is a list, each element of the list is added with @code{add-hook}.
+@end table
+
+Styles are kept in the @code{c-style-alist} variable, but you
+should never modify this variable directly.  Instead, @ccmode{}
+provides the function @code{c-add-style} for this purpose.
 
 @defun c-add-style stylename description &optional set-p
 @findex add-style (c-)
-Add or update a style.  If @var{stylename} is not already in
-@code{c-style-alist} then a new style according to @var{description}
-is added, otherwise the existing style is changed.  If the optional
-@var{set-p} is non-@code{nil} then the new style is applied to the
-current buffer as well.
-
-@comment TBD: The next paragraph is bogus.  I really need to better
-@comment document adding styles, including setting up inherited styles.
+Add or update a style called @var{stylename}, a string.
+@var{description} is the new style definition in the form described
+above.  If @var{stylename} already exists in @code{c-style-alist} then
+it is replaced by @var{description}.  (Note, this replacement is
+total.  The old style is @emph{not} merged into the new one.)
+Otherwise, a new style is added.  If the optional @var{set-p} is
+non-@code{nil} then the new style is applied to the current buffer as
+well.
 
 The sample @file{.emacs} file provides a concrete example of how a new
 style can be added and automatically set.  @xref{Sample .emacs File}.
 Lines continuing the header of a lambda function, i.e. between the
 @code{lambda} keyword and the function body.  Only used in Pike mode.
 @item inexpr-statement
-A statement block inside an expression.  The gcc C extension of this is
-recognized.  It's also used for the special functions that takes a
-statement block as an argument in Pike.
+A statement block inside an expression.  The gcc C and C++ extension for
+this is recognized.  It's also used for the special functions that take
+a statement block as an argument in Pike.
 @item inexpr-class
 A class definition inside an expression.  This is used for anonymous
 classes in Java.  It's also used for anonymous array initializers in
 @code{inexpr-class}.
 
 There are a few occasions where a statement block may be used inside an
-expression.  One is in C code using the gcc extension for this, e.g:
+expression.  One is in C or C++ code using the gcc extension for this,
+e.g:
 
 @example
  1: int res = (@{
 value is an association list that for each language mode specifies the
 value to give to @code{require-final-newline} at mode initialization;
 see that variable for details about the value.  If a language isn't
-present on the association list, CC Mode won't set
+present on the association list, CC Mode won't touch
 @code{require-final-newline} in buffers for that language.
 
 The default is to set @code{require-final-newline} to @code{t} in the
 (somewhat cryptic) error message.}. If you are using the standalone
 @ccmode{} distribution, try recompiling it according to the instructions
 in the @file{README} file.
+
+@item
+@cindex open paren in column zero
+@emph{I have an open paren character at column zero inside a comment or
+multiline string literal, and it causes the fontification and/or
+indentation to go haywire.  What gives?}
+
+It's due to the ad-hoc rule in (X)Emacs that such open parens always
+start defuns (which translates to functions, classes, namespaces or any
+other top-level block constructs in the @ccmode{} languages).
+@xref{Left Margin Paren,,, emacs, The Emacs Editor}, for details
+(@xref{Defuns,,, emacs, The Emacs Editor}, in the Emacs 20 manual).
+
+This heuristic is built into the core syntax analysis routines in
+(X)Emacs, so it's not really a @ccmode{} issue.  However, in Emacs 21.4
+it has become possible to turn it off@footnote{Using the variable
+@code{open-paren-in-column-0-is-defun-start}.} and @ccmode{} does so
+there since it got its own system to keep track of blocks.
+
 @end itemize
 
 
         indent-tabs-mode nil)
   ;; we like auto-newline and hungry-delete
   (c-toggle-auto-hungry-state 1)
-  ;; keybindings for all supported languages.  We can put these in
+  ;; key bindings for all supported languages.  We can put these in
   ;; c-mode-base-map because c-mode-map, c++-mode-map, objc-mode-map,
   ;; java-mode-map, idl-mode-map, and pike-mode-map inherit from it.
   (define-key c-mode-base-map "\C-m" 'c-context-line-break))

File cc-styles.el

 	      (completing-read prompt c-style-alist nil t
 			       (cons c-indentation-style 0)
 			       'c-set-style-history))))))
+  (or (stringp stylename)
+      (error "Argument to c-set-style was not a string"))
   (c-initialize-builtin-style)
   (let ((vars (c-get-style-variables stylename nil)))
     (unless dont-override
 
 (defcustom c-tab-always-indent t
   "*Controls the operation of the TAB key.
-If t, hitting TAB always just indents the current line.  If nil,
-hitting TAB indents the current line if point is at the left margin or
-in the line's indentation, otherwise it insert a `real' tab character
-\(see note\).  If the symbol `other', then tab is inserted only within
-literals -- defined as comments and strings -- and inside preprocessor
-directives, but the line is always reindented.
+If t, hitting TAB always just indents the current line.  If nil, hitting
+TAB indents the current line if point is at the left margin or in the
+line's indentation, otherwise it inserts a `real' tab character \(see
+note\).  If some other value (not nil or t), then tab is inserted only
+within literals \(comments and strings), but the line is always
+reindented.
 
 Note: The value of `indent-tabs-mode' will determine whether a real
 tab character will be inserted, or the equivalent number of spaces.
 (make-variable-buffer-local 'c-current-comment-prefix)
 
 
-;; Figure out what features this Emacs has
-
-(cc-bytecomp-defvar open-paren-in-column-0-is-defun-start)
-
-(defconst c-emacs-features
-  (let (list)
-
-    (if (boundp 'infodock-version)
-	;; I've no idea what this actually is, but it's legacy. /mast
-	(setq list (cons 'infodock list)))
-
-    ;; XEmacs 19 and beyond use 8-bit modify-syntax-entry flags.
-    ;; Emacs 19 uses a 1-bit flag.  We will have to set up our
-    ;; syntax tables differently to handle this.
-    (let ((table (copy-syntax-table))
-	  entry)
-      (modify-syntax-entry ?a ". 12345678" table)
-      (cond
-       ;; XEmacs 19, and beyond Emacs 19.34
-       ((arrayp table)
-	(setq entry (aref table ?a))
-	;; In Emacs, table entries are cons cells
-	(if (consp entry) (setq entry (car entry))))
-       ;; XEmacs 20
-       ((fboundp 'get-char-table) (setq entry (get-char-table ?a table)))
-       ;; before and including Emacs 19.34
-       ((and (fboundp 'char-table-p)
-	     (char-table-p table))
-	(setq entry (car (char-table-range table [?a]))))
-       ;; incompatible
-       (t (error "CC Mode is incompatible with this version of Emacs")))
-      (setq list (cons (if (= (logand (lsh entry -16) 255) 255)
-			   '8-bit
-			 '1-bit)
-		       list)))
-
-    (let ((buf (generate-new-buffer " test"))
-	  parse-sexp-lookup-properties
-	  parse-sexp-ignore-comments
-	  lookup-syntax-properties)
-      (save-excursion
-	(set-buffer buf)
-	(set-syntax-table (make-syntax-table))
-
-	;; For some reason we have to set some of these after the
-	;; buffer has been made current.  (Specifically,
-	;; `parse-sexp-ignore-comments' in Emacs 21.)
-	(setq parse-sexp-lookup-properties t
-	      parse-sexp-ignore-comments t
-	      lookup-syntax-properties t)
-
-	;; Find out if the `syntax-table' text property works.
-	(modify-syntax-entry ?< ".")
-	(modify-syntax-entry ?> ".")
-	(insert "<()>")
-	(c-mark-<-as-paren 1)
-	(c-mark->-as-paren 4)
-	(goto-char 1)
-	(c-forward-sexp)
-	(if (= (point) 5)
-	    (setq list (cons 'syntax-properties list)))
-
-	;; Find out if generic comment delimiters work.
-	(c-safe
-	  (modify-syntax-entry ?x "!")
-	  (if (string-match "\\s!" "x")
-	      (setq list (cons 'gen-comment-delim list))))
-
-	;; Find out if generic string delimiters work.
-	(c-safe
-	  (modify-syntax-entry ?x "|")
-	  (if (string-match "\\s|" "x")
-	      (setq list (cons 'gen-string-delim list))))
-
-	;; See if `open-paren-in-column-0-is-defun-start' exists and
-	;; isn't buggy.
-	(when (boundp 'open-paren-in-column-0-is-defun-start)
-	  (let ((open-paren-in-column-0-is-defun-start nil)
-		(parse-sexp-ignore-comments t))
-	    (set-syntax-table (make-syntax-table))
-	    (modify-syntax-entry ?\' "\"")
-	    (cond
-	     ;; XEmacs.  Afaik this is currently an Emacs-only
-	     ;; feature, but it's good to be prepared.
-	     ((memq '8-bit list)
-	      (modify-syntax-entry ?/ ". 1456")
-	      (modify-syntax-entry ?* ". 23"))
-	     ;; Emacs
-	     ((memq '1-bit list)
-	      (modify-syntax-entry ?/ ". 124b")
-	      (modify-syntax-entry ?* ". 23")))
-	    (modify-syntax-entry ?\n "> b")
-	    (insert "/* '\n   () */")
-	    (backward-sexp)
-	    (if (bobp)
-		(setq list (cons 'col-0-paren list))))
-	  (kill-buffer buf))
-
-	(set-buffer-modified-p nil))
-      (kill-buffer buf))
-
-    ;; See if `parse-partial-sexp' returns the eighth element.
-    (when (c-safe (>= (length (save-excursion (parse-partial-sexp 1 1))) 10))
-      (setq list (cons 'pps-extended-state list)))
-
-    ;; See if POSIX char classes work.
-    (when (string-match "[[:alpha:]]" "a")
-      (setq list (cons 'posix-char-classes list)))
-
-    list)
-  "A list of certain features in the (X)Emacs you are using.
-There are many flavors of Emacs out there, each with different
-features supporting those needed by CC Mode.  The following values
-might be present:
-
-'8-bit              8 bit syntax entry flags (XEmacs style).
-'1-bit              1 bit syntax entry flags (Emacs style).
-'syntax-properties  It works to override the syntax for specific characters
-		    in the buffer with the 'syntax-table property.
-'gen-comment-delim  Generic comment delimiters work
-		    (i.e. the syntax class `!').
-'gen-string-delim   Generic string delimiters work
-		    (i.e. the syntax class `|').
-'pps-extended-state `parse-partial-sexp' returns a list with at least 10
-		    elements, i.e. it contains the position of the
-		    start of the last comment or string.
-'posix-char-classes The regexp engine understands POSIX character classes.
-'col-0-paren        It's possible to turn off the ad-hoc rule that a paren
-		    in column zero is the start of a defun.
-'infodock           This is Infodock (based on XEmacs).
-
-'8-bit and '1-bit are mutually exclusive.")
-
-
 (cc-provide 'cc-vars)
 
 ;;; cc-vars.el ends here