+2004-08-11 Martin Stjernholm <bug-cc-mode@gnu.org>
+
+ CC Mode update to 5.30.9:
+
+ * progmodes/cc-defs.el, progmodes/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.
+
+ * progmodes/cc-align.el (c-lineup-arglist): Fixed bug when the
+ first argument starts with a special brace list.
+
+ * progmodes/cc-engine.el (c-forward-type): Fixed promotion bug
+ when `c-opt-type-concat-key' is used (i.e. in Pike).
+
+ * progmodes/cc-engine.el (c-looking-at-special-brace-list): Fixed
+ bug when the inner char pair doesn't have paren syntax, i.e. "(<
+ >)".
+
+ * progmodes/cc-align.el (c-lineup-multi-inher): Made it syntactic
+ whitespace safe.
+
+ * progmodes/cc-engine.el (c-guess-basic-syntax): Fixed anchor
+ position for `arglist-intro', `arglist-cont-nonempty' and
+ `arglist-close' when there are two arglist open parens on the same
+ line and there's nothing in front of the first.
+
+ * progmodes/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.
+
+ * progmodes/cc-align.el (c-lineup-whitesmith-in-block): Fixed
+ inconsistency wrt opening parens on the first line inside a paren
+ block.
+
+ * progmodes/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'.
+
+ * progmodes/cc-defs.el (c-major-mode-is): Fixed expansion inside
+ `c-lang-defconst' so that it works better with fallback languages.
+
+ * progmodes/cc-defs.el (c-add-language): Fixed a typo that caused
+ it to fail to record the base mode.
+
+ * progmodes/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.
+
+ * progmodes/cc-cmds.el (c-electric-brace): Don't trip up on a line
+ continuation which might precede the newly inserted '{'.
+
+ * progmodes/cc-engine.el (c-syntactic-re-search-forward): Fixed
+ cases where it could loop indefinitely.
+
+ * progmodes/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.
+
+ * progmodes/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.
+
+ * progmodes/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.
+
+ * progmodes/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.
+
+ * progmodes/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.
+
+2004-08-11 Alan Mackenzie <bug-cc-mode@gnu.org>
+
+ CC Mode update to 5.30.9:
+
+ * progmodes/cc-cmds.el, progmodes/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.
+
+ * progmodes/cc-styles.el, progmodes/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.
+
+ * progmodes/cc-cmds.el: (c-electric-brace): don't delete a comment
+ which precedes the newly inserted `{'.
+
2004-08-10 Michael Albinus <michael.albinus@gmx.de>
Sync with Tramp 2.0.44.
;; 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
\f
;;; 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)
+\f
+;; 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.")
+
\f
;;; 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))
+
\f
(cc-provide 'cc-defs)
(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 search-pos (point))
+ (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 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)))
- ((and not-inside-token
- (or (< check-pos last-token-end-pos)
- (< check-pos
- (save-excursion
- (goto-char 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"))))
+ ;; 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-end-of-macro)
(cond ((<= (point) bound) t)
(noerror nil)
- (t (signal 'search-failed "end of macro"))))
+ (t (signal 'search-failed (list regexp)))))
- ((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))))
+ ((and not-inside-token
+ (or (< check-pos last-token-end-pos)
+ (< check-pos
+ (save-excursion
+ (goto-char check-pos)
+ (save-match-data
+ (c-end-of-current-token last-token-end-pos))
+ (setq last-token-end-pos (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)
- (c-forward-sexp 1)
- (setq end (point))
- (= (char-before) ?\)))
- (c-safe (goto-char beg)
- (forward-char 1)
+ (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)
- ;; 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 "\\(::\\|\\.\\)")
(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.
Set from `c-comment-prefix-regexp' at mode initialization.")
(make-variable-buffer-local 'c-current-comment-prefix)
-\f
-;; 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.")
-
\f
(cc-provide 'cc-vars)
+2004-08-11 Martin Stjernholm <bug-cc-mode@gnu.org>
+
+ * cc-mode.texi: Various updates for CC Mode 5.30.9.
+
2004-08-10 Michael Albinus <michael.albinus@gmx.de>
Sync with Tramp 2.0.44.
@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
@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