Updated CC Mode to version 5.30.

This commit is contained in:
Martin Stjernholm 2003-07-03 12:30:59 +00:00
parent bac598bbf5
commit d9e94c2273
14 changed files with 14923 additions and 2988 deletions

File diff suppressed because it is too large Load diff

View file

@ -1,10 +1,9 @@
;;; cc-align.el --- custom indentation functions for CC Mode
;; Copyright (C) 1985,1987,1992-2001 Free Software Foundation, Inc.
;; Copyright (C) 1985,1987,1992-2003 Free Software Foundation, Inc.
;; Authors: 2000- Martin Stjernholm
;; 1998-1999 Barry A. Warsaw and Martin Stjernholm
;; 1992-1997 Barry A. Warsaw
;; Authors: 1998- Martin Stjernholm
;; 1992-1999 Barry A. Warsaw
;; 1987 Dave Detlefs and Stewart Clamen
;; 1985 Richard M. Stallman
;; Maintainer: bug-cc-mode@gnu.org
@ -39,16 +38,27 @@
(stringp byte-compile-dest-file))
(cons (file-name-directory byte-compile-dest-file) load-path)
load-path)))
(require 'cc-bytecomp)))
(load "cc-bytecomp" nil t)))
(cc-require 'cc-defs)
(cc-require 'cc-vars)
(cc-require 'cc-langs)
(cc-require 'cc-engine)
;; Standard indentation line-ups
;; Calling convention:
;;
;; The single argument is a cons cell containing the syntactic symbol
;; in the car, and the relpos (a.k.a. anchor position) in the cdr.
;; The cdr may be nil for syntactic symbols which doesn't have an
;; associated relpos.
;;
;; Some syntactic symbols provide more information, usually more
;; interesting positions. The complete list for the syntactic element
;; (beginning with the symbol itself) is available in
;; `c-syntactic-element'.
(defun c-lineup-topmost-intro-cont (langelem)
"Line up declaration continuation lines zero or one indentation step.
For lines in the \"header\" of a definition, zero is used. For other
@ -88,17 +98,55 @@ Works with: topmost-intro-cont."
(defun c-lineup-arglist (langelem)
"Line up the current argument line under the first argument.
As a special case, if an argument on the same line as the open
parenthesis starts with a brace block opener, the indentation is
`c-basic-offset' only. This is intended as a \"DWIM\" measure in
cases like macros that contains statement blocks, e.g:
A_VERY_LONG_MACRO_NAME ({
some (code, with + long, lines * in[it]);
});
<--> c-basic-offset
This is motivated partly because it's more in line with how code
blocks are handled, and partly since it approximates the behavior of
earlier CC Mode versions, which due to inaccurate analysis tended to
indent such cases this way.
Works with: arglist-cont-nonempty, arglist-close."
(save-excursion
(beginning-of-line)
(let ((containing-sexp (c-most-enclosing-brace (c-parse-state))))
(goto-char (1+ containing-sexp))
(let ((eol (c-point 'eol)))
(goto-char (1+ (elt c-syntactic-element 2)))
;; Don't stop in the middle of a special brace list opener
;; like "({".
(when c-special-brace-lists
(let ((special-list (c-looking-at-special-brace-list)))
(when special-list
(goto-char (+ (car (car special-list)) 2)))))
(let ((savepos (point))
(eol (c-point 'eol)))
;; Find out if an argument on the same line starts with an
;; unclosed open brace paren. Note similar code in
;; `c-lineup-close-paren' and
;; `c-lineup-arglist-close-under-paren'.
(if (and (c-syntactic-re-search-forward "{" eol t t)
(looking-at c-syntactic-eol)
(progn (backward-char)
(not (c-looking-at-special-brace-list)))
(progn (c-backward-syntactic-ws)
(or (= (point) savepos)
(eq (char-before) ?,))))
c-basic-offset
;; Normal case. Indent to the token after the arglist open paren.
(goto-char savepos)
(c-forward-syntactic-ws)
(when (< (point) eol)
(goto-char (1+ containing-sexp))
(skip-chars-forward " \t")))
(vector (current-column)))))
(goto-char savepos)
(skip-chars-forward " \t"))
(vector (current-column))))))
;; Contributed by Kevin Ryde <user42@zip.com.au>.
(defun c-lineup-argcont (elem)
@ -118,32 +166,46 @@ Works with: arglist-cont, arglist-cont-nonempty."
(save-excursion
(beginning-of-line)
(let ((bol (point)))
;; Previous line ending in a comma means we're the start of an
;; argument. This should quickly catch most cases not for us.
(c-backward-syntactic-ws)
(let ((c (char-before)))
(unless (eq c ?,)
(when (eq (car elem) 'arglist-cont-nonempty)
;; Our argument list might not be the innermost one. If it
;; isn't, go back to the last position in it. We do this by
;; stepping back over open parens until we get to the open paren
;; of our argument list.
(let ((open-paren (elt c-syntactic-element 2))
(paren-state (c-parse-state)))
(while (not (eq (car paren-state) open-paren))
(goto-char (car paren-state))
(setq paren-state (cdr paren-state)))))
;; In a gcc asm, ":" on the previous line means the start of an
;; argument. And lines starting with ":" are not for us, don't
;; want them to indent to the preceding operand.
(let ((gcc-asm (save-excursion
(goto-char bol)
(c-in-gcc-asm-p))))
(unless (and gcc-asm
(or (eq c ?:)
(save-excursion
(goto-char bol)
(looking-at "[ \t]*:"))))
(let ((start (point)) c)
(c-lineup-argcont-scan (if gcc-asm ?:))
(vector (current-column)))))))))
(when (bolp)
;; Previous line ending in a comma means we're the start of an
;; argument. This should quickly catch most cases not for us.
;; This case is only applicable if we're the innermost arglist.
(c-backward-syntactic-ws)
(setq c (char-before)))
(unless (eq c ?,)
;; In a gcc asm, ":" on the previous line means the start of an
;; argument. And lines starting with ":" are not for us, don't
;; want them to indent to the preceding operand.
(let ((gcc-asm (save-excursion
(goto-char start)
(c-in-gcc-asm-p))))
(unless (and gcc-asm
(or (eq c ?:)
(save-excursion
(goto-char start)
(looking-at "[ \t]*:"))))
(c-lineup-argcont-scan (if gcc-asm ?:))
(vector (current-column))))))))
(defun c-lineup-argcont-scan (&optional other-match)
;; Find the start of an argument, for `c-lineup-argcont'.
(when (eq 0 (c-backward-token-1 1 t))
(when (zerop (c-backward-token-2 1 t))
(let ((c (char-after)))
(if (or (eq c ?,) (eq c other-match))
(progn
@ -152,8 +214,8 @@ Works with: arglist-cont, arglist-cont-nonempty."
(c-lineup-argcont-scan other-match)))))
(defun c-lineup-arglist-intro-after-paren (langelem)
"Line up a line just after the open paren of the surrounding paren or
brace block.
"Line up a line to just after the open paren of the surrounding paren
or brace block.
Works with: defun-block-intro, brace-list-intro,
statement-block-intro, statement-case-intro, arglist-intro."
@ -164,16 +226,79 @@ statement-block-intro, statement-case-intro, arglist-intro."
(vector (1+ (current-column)))))
(defun c-lineup-arglist-close-under-paren (langelem)
"Line up a closing paren line under the corresponding open paren.
"Line up a line under the enclosing open paren.
Normally used to line up a closing paren in the same column as its
corresponding open paren, but can also be used with arglist-cont and
arglist-cont-nonempty to line up all lines inside a parenthesis under
the open paren.
Works with: defun-close, class-close, inline-close, block-close,
brace-list-close, arglist-close, extern-lang-close, namespace-close
\(for most of these, a zero offset will normally produce the same
result, though)."
As a special case, if a brace block is opened at the same line as the
open parenthesis of the argument list, the indentation is
`c-basic-offset' only. See `c-lineup-arglist' for further discussion
of this \"DWIM\" measure.
Works with: Almost all symbols, but are typically most useful on
arglist-close, brace-list-close, arglist-cont and arglist-cont-nonempty."
(save-excursion
(beginning-of-line)
(backward-up-list 1)
(vector (current-column))))
(let (special-list paren-start savepos)
(if (memq (car langelem) '(arglist-cont-nonempty arglist-close))
(goto-char (elt c-syntactic-element 2))
(beginning-of-line)
(c-go-up-list-backward))
(if (and c-special-brace-lists
(setq special-list (c-looking-at-special-brace-list)))
;; Don't stop in the middle of a special brace list opener
;; like "({".
(progn
(setq paren-start (car (car special-list)))
(goto-char (+ paren-start 2)))
(setq paren-start (point))
(forward-char 1))
(setq savepos (point))
;; Find out if an argument on the same line starts with an
;; unclosed open brace paren. Note similar code in
;; `c-lineup-arglist' and `c-lineup-close-paren'.
(if (and (c-syntactic-re-search-forward "{" (c-point 'eol) t t)
(looking-at c-syntactic-eol)
(progn (backward-char)
(not (c-looking-at-special-brace-list)))
(progn (c-backward-syntactic-ws)
(or (= (point) savepos)
(eq (char-before) ?,))))
c-basic-offset
;; Normal case. Indent to the arglist open paren.
(goto-char paren-start)
(vector (current-column))))))
(defun c-lineup-arglist-operators (langelem)
"Line up lines starting with an infix operator under the open paren.
Return nil on lines that don't start with an operator, to leave those
cases to other lineup functions. Example:
if ( x < 10
|| at_limit (x, <- c-lineup-arglist-operators
list) <- c-lineup-arglist-operators returns nil
)
Since this function doesn't do anything for lines without an infix
operator you typically want to use it together with some other lineup
settings, e.g. as follows \(the arglist-close setting is just a
suggestion to get a consistent style):
\(c-set-offset 'arglist-cont '(c-lineup-arglist-operators 0))
\(c-set-offset 'arglist-cont-nonempty '(c-lineup-arglist-operators
c-lineup-arglist))
\(c-set-offset 'arglist-close '(c-lineup-arglist-close-under-paren))
Works with: arglist-cont, arglist-cont-nonempty."
(save-excursion
(back-to-indentation)
(when (looking-at "[-+|&*%<>=]\\|\\(/[^/*]\\)")
;; '-' can be both an infix and a prefix operator, but I'm lazy now..
(c-lineup-arglist-close-under-paren langelem))))
(defun c-lineup-close-paren (langelem)
"Line up the closing paren under its corresponding open paren if the
@ -184,25 +309,45 @@ main (int, main (
char ** int, char **
) <-> ) <- c-lineup-close-paren
Works with: defun-close, class-close, inline-close, block-close,
brace-list-close, arglist-close, extern-lang-close, namespace-close."
As a special case, if a brace block is opened at the same line as the
open parenthesis of the argument list, the indentation is
`c-basic-offset' instead of the open paren column. See
`c-lineup-arglist' for further discussion of this \"DWIM\" measure.
Works with: All *-close symbols."
(save-excursion
(condition-case nil
(let (opencol spec)
(beginning-of-line)
(backward-up-list 1)
(setq spec (c-looking-at-special-brace-list))
(if spec (goto-char (car (car spec))))
(setq opencol (current-column))
(forward-char 1)
(if spec (progn
(c-forward-syntactic-ws)
(forward-char 1)))
(c-forward-syntactic-ws (c-point 'eol))
(if (eolp)
0
(vector opencol)))
(error nil))))
(beginning-of-line)
(c-go-up-list-backward)
(let ((spec (c-looking-at-special-brace-list)) savepos argstart)
(if spec (goto-char (car (car spec))))
(setq savepos (point))
(forward-char 1)
(when spec
(c-forward-syntactic-ws)
(forward-char 1))
(if (looking-at c-syntactic-eol)
;; The arglist is "empty".
0
;; Find out if an argument on the same line starts with an
;; unclosed open brace paren. Note similar code in
;; `c-lineup-arglist' and
;; `c-lineup-arglist-close-under-paren'.
(setq argstart (point))
(if (and (c-syntactic-re-search-forward "{" (c-point 'eol) t t)
(looking-at c-syntactic-eol)
(progn (backward-char)
(not (c-looking-at-special-brace-list)))
(progn (c-backward-syntactic-ws)
(or (= (point) argstart)
(eq (char-before) ?,))))
c-basic-offset
;; Normal case. Indent to the arglist open paren.
(goto-char savepos)
(vector (current-column)))))))
(defun c-lineup-streamop (langelem)
"Line up C++ stream operators under each other.
@ -232,6 +377,7 @@ class Foo Foo::Foo (int a, int b)
Works with: inher-cont, member-init-cont."
(save-excursion
(back-to-indentation)
(let* ((eol (c-point 'eol))
(here (point))
(char-after-ip (progn
@ -253,12 +399,13 @@ Works with: inher-cont, member-init-cont."
(if (or (eolp)
(looking-at c-comment-start-regexp))
(c-forward-syntactic-ws here))
(vector (current-column))
(if (< (point) here)
(vector (current-column)))
)))
(defun c-lineup-java-inher (langelem)
"Line up Java implements and extends declarations.
If class names follows on the same line as the implements/extends
If class names follow on the same line as the implements/extends
keyword, they are lined up under each other. Otherwise, they are
indented by adding `c-basic-offset' to the column of the keyword.
E.g:
@ -279,7 +426,7 @@ Works with: inher-cont."
(defun c-lineup-java-throws (langelem)
"Line up Java throws declarations.
If exception names follows on the same line as the throws keyword,
If exception names follow on the same line as the throws keyword,
they are lined up under each other. Otherwise, they are indented by
adding `c-basic-offset' to the column of the throws keyword. The
throws keyword itself is also indented by `c-basic-offset' from the
@ -295,11 +442,11 @@ Works with: func-decl-cont."
(let* ((lim (1- (c-point 'bol)))
(throws (catch 'done
(goto-char (cdr langelem))
(while (zerop (c-forward-token-1 1 t lim))
(while (zerop (c-forward-token-2 1 t lim))
(if (looking-at "throws\\>[^_]")
(throw 'done t))))))
(if throws
(if (zerop (c-forward-token-1 1 nil (c-point 'eol)))
(if (zerop (c-forward-token-2 1 nil (c-point 'eol)))
(vector (current-column))
(back-to-indentation)
(vector (+ (current-column) c-basic-offset)))
@ -470,7 +617,7 @@ Works with: comment-intro."
(cond
;; CASE 1: preserve aligned comments
((save-excursion
(and (c-forward-comment -1)
(and (c-backward-single-comment)
(= col (current-column))))
(vector col)) ; Return an absolute column.
;; indent as specified by c-comment-only-line-offset
@ -534,46 +681,69 @@ the statement. If there isn't any, indent with `c-basic-offset'. If
the current line contains an equal sign too, try to align it with the
first one.
Works with: statement-cont, arglist-cont, arglist-cont-nonempty."
(save-excursion
(let ((equalp (save-excursion
(goto-char (c-point 'boi))
(let ((eol (c-point 'eol)))
(c-forward-token-1 0 t eol)
(while (and (not (eq (char-after) ?=))
(= (c-forward-token-1 1 t eol) 0))))
(and (eq (char-after) ?=)
(- (point) (c-point 'boi)))))
donep)
(if (cdr langelem) (goto-char (cdr langelem)))
(while (and (not donep)
(< (point) (c-point 'eol)))
(skip-chars-forward "^=" (c-point 'eol))
(if (c-in-literal (cdr langelem))
(forward-char 1)
(setq donep t)))
(if (or (not (eq (char-after) ?=))
Works with: topmost-intro-cont, statement-cont, arglist-cont,
arglist-cont-nonempty."
(let (startpos endpos equalp)
(if (eq (car langelem) 'arglist-cont-nonempty)
;; If it's an arglist-cont-nonempty then we're only interested
;; in equal signs outside it. We don't search for a "=" on
;; the current line since that'd have a different nesting
;; compared to the one we should align with.
(save-excursion
(save-restriction
(setq endpos (nth 2 c-syntactic-element))
(narrow-to-region (cdr langelem) endpos)
(if (setq startpos (c-up-list-backward endpos))
(setq startpos (1+ startpos))
(setq startpos (cdr langelem)))))
(setq startpos (cdr langelem)
endpos (point))
;; Find a syntactically relevant and unnested "=" token on the
;; current line. equalp is in that case set to the number of
;; columns to left shift the current line to align it with the
;; goal column.
(save-excursion
(beginning-of-line)
(when (c-syntactic-re-search-forward
;; This regexp avoids matches on ==.
"\\(\\=\\|[^=]\\)=\\([^=]\\|$\\)"
(c-point 'eol) t t)
(setq equalp (- (match-beginning 2) (c-point 'boi))))))
(save-excursion
(goto-char startpos)
(if (or (if (c-syntactic-re-search-forward
"\\(\\=\\|[^=]\\)=\\([^=]\\|$\\)"
(min endpos (c-point 'eol)) t t)
(progn
(goto-char (match-beginning 2))
nil)
t)
(save-excursion
(forward-char 1)
(c-forward-syntactic-ws (c-point 'eol))
(eolp)))
;; there's no equal sign on the line
;; There's no equal sign on the line, or there is one but
;; nothing follows it.
c-basic-offset
;; calculate indentation column after equals and ws, unless
;; our line contains an equals sign
(if (not equalp)
(progn
(forward-char 1)
(skip-chars-forward " \t")
(setq equalp 0)))
(vector (- (current-column) equalp)))
)))
(defun c-lineup-cascaded-calls (langelem)
"Line up \"cascaded calls\" under each other.
If the line begins with \"->\" and the preceding line ends with one or
more function calls preceded by \"->\", then the arrow is lined up with
the first of those \"->\". E.g:
If the line begins with \"->\" or \".\" and the preceding line ends
with one or more function calls preceded by the same token, then the
arrow is lined up with the first of those tokens. E.g:
result = proc->add(17)->add(18)
->add(19) + <- c-lineup-cascaded-calls
@ -582,22 +752,63 @@ result = proc->add(17)->add(18)
In any other situation nil is returned to allow use in list
expressions.
Works with: statement-cont, arglist-cont, arglist-cont-nonempty."
(save-excursion
(let ((bopl (c-point 'bopl)) col)
Works with: topmost-intro-cont, statement-cont, arglist-cont,
arglist-cont-nonempty."
(if (and (eq (car langelem) 'arglist-cont-nonempty)
(not (eq (nth 2 c-syntactic-element)
(c-most-enclosing-brace (c-parse-state)))))
;; The innermost open paren is not our one, so don't do
;; anything. This can occur for arglist-cont-nonempty with
;; nested arglist starts on the same line.
nil
(save-excursion
(back-to-indentation)
(when (and (looking-at "->")
(= (c-backward-token-1 1 t bopl) 0)
(eq (char-after) ?\()
(= (c-backward-token-1 3 t bopl) 0)
(looking-at "->"))
(setq col (current-column))
(while (and (= (c-backward-token-1 1 t bopl) 0)
(eq (char-after) ?\()
(= (c-backward-token-1 3 t bopl) 0)
(looking-at "->"))
(setq col (current-column)))
(vector col)))))
(let ((operator (and (looking-at "->\\|\\.")
(regexp-quote (match-string 0))))
(stmt-start (cdr langelem)) col)
(when (and operator
(looking-at operator)
(zerop (c-backward-token-2 1 t stmt-start))
(eq (char-after) ?\()
(zerop (c-backward-token-2 2 t stmt-start))
(looking-at operator))
(setq col (current-column))
(while (and (zerop (c-backward-token-2 1 t stmt-start))
(eq (char-after) ?\()
(zerop (c-backward-token-2 2 t stmt-start))
(looking-at operator))
(setq col (current-column)))
(vector col))))))
(defun c-lineup-string-cont (langelem)
"Line up a continued string under the one it continues.
A continued string in this sense is where a string literal follows
directly after another one. E.g:
result = prefix + \"A message \"
\"string.\"; <- c-lineup-string-cont
Nil is returned in other situations, to allow stacking with other
lineup functions.
Works with: topmost-intro-cont, statement-cont, arglist-cont,
arglist-cont-nonempty."
(save-excursion
(back-to-indentation)
(and (looking-at "\\s\"")
(let ((quote (char-after)) pos)
(while (and (progn (c-backward-syntactic-ws)
(eq (char-before) quote))
(c-safe (c-backward-sexp) t)
(/= (setq pos (point)) (c-point 'boi))))
(when pos
(goto-char pos)
(vector (current-column)))))))
(defun c-lineup-template-args (langelem)
"Line up template argument lines under the first argument.
@ -610,11 +821,11 @@ Works with: template-args-cont."
(beginning-of-line)
(backward-up-list 1)
(if (and (eq (char-after) ?<)
(zerop (c-forward-token-1 1 nil (c-point 'eol))))
(zerop (c-forward-token-2 1 nil (c-point 'eol))))
(vector (current-column))))))
(defun c-lineup-ObjC-method-call (langelem)
"Line up selector args as elisp-mode does with function args:
"Line up selector args as Emacs Lisp mode does with function args:
Go to the position right after the message receiver, and if you are at
the end of the line, indent the current line c-basic-offset columns
from the opening bracket; otherwise you are looking at the first
@ -736,8 +947,8 @@ In the first case the indentation is kept unchanged, in the
second `c-basic-offset' is added.
Works with: defun-close, defun-block-intro, block-close,
brace-list-close, brace-list-intro, statement-block-intro, inclass,
inextern-lang, innamespace."
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)
@ -775,13 +986,13 @@ const char msg[] = if (!running)
} while (0) <-> } while (0) <- c-lineup-cpp-define
The relative indentation returned by `c-lineup-cpp-define' is zero and
two, respectively, in these two examples. They are then added to the
two, respectively, in these two examples. They are then added to the
two column indentation that statement-block-intro gives in both cases
here.
If the relative indentation is zero, then nil is returned instead.
This useful in a list expression to specify the default indentation on
the top level.
That is useful in a list expression to specify the default indentation
on the top level.
If `c-syntactic-indentation-in-macros' is nil then this function keeps
the current indentation, except for empty lines \(ignoring the ending
@ -855,6 +1066,13 @@ Works with: arglist-cont, arglist-cont-nonempty."
(and
c-opt-asm-stmt-key
;; Don't do anything if the innermost open paren isn't our one.
;; This can occur for arglist-cont-nonempty with nested arglist
;; starts on the same line.
(or (not (eq (car elem) 'arglist-cont-nonempty))
(eq (elt c-syntactic-element 2)
(c-most-enclosing-brace (c-parse-state))))
;; Find the ":" to align to. Look for this first so as to quickly
;; eliminate pretty much all cases which are not for us.
(re-search-backward "^[ \t]*:[ \t]*\\(.\\)?" (cdr elem) t)
@ -893,7 +1111,7 @@ ACTION associated with `block-close' syntax."
(let (langelem)
(if (and (eq syntax 'block-close)
(setq langelem (assq 'block-close c-syntactic-context))
(progn (goto-char (cdr langelem))
(progn (goto-char (elt langelem 1))
(if (eq (char-after) ?{)
(c-safe (c-forward-sexp -1)))
(looking-at "\\<do\\>[^_]")))
@ -904,27 +1122,32 @@ ACTION associated with `block-close' syntax."
"Imposes a minimum indentation for lines inside a top-level construct.
The variable `c-label-minimum-indentation' specifies the minimum
indentation amount."
(let ((non-top-levels '(defun-block-intro statement statement-cont
statement-block-intro statement-case-intro
statement-case-open substatement substatement-open
case-label label do-while-closure else-clause
))
(syntax c-syntactic-context)
langelem)
(while syntax
(setq langelem (car (car syntax))
syntax (cdr syntax))
;; don't adjust macro or comment-only lines
(cond ((memq langelem '(cpp-macro comment-intro))
(setq syntax nil))
((memq langelem non-top-levels)
(save-excursion
(setq syntax nil)
(back-to-indentation)
(if (zerop (current-column))
(insert-char ?\ c-label-minimum-indentation t))
))
))))
;; Don't adjust macro or comment-only lines.
(unless (or (assq 'cpp-macro c-syntactic-context)
(assq 'comment-intro c-syntactic-context))
(let ((paren-state (save-excursion
;; Get the parenthesis state, but skip past
;; an initial closing paren on the line since
;; the close brace of a block shouldn't be
;; considered to be inside the block.
(back-to-indentation)
(when (looking-at "\\s\)")
(forward-char))
(c-parse-state))))
;; Search for an enclosing brace on paren-state.
(while (and paren-state
(not (and (integer-or-marker-p (car paren-state))
(eq (char-after (car paren-state)) ?{))))
(setq paren-state (cdr paren-state)))
(when paren-state
(save-excursion
(back-to-indentation)
(if (zerop (current-column))
(insert-char ?\ c-label-minimum-indentation t)))))))
;; Useful for c-hanging-semi&comma-criteria

905
lisp/progmodes/cc-awk.el Normal file
View file

@ -0,0 +1,905 @@
;;; cc-awk.el --- AWK specific code within cc-mode.
;; Copyright (C) 1988,94,96,2000,01,02,03 Free Software Foundation, Inc.
;; Author: Alan Mackenzie (originally based on awk-mode.el)
;; Maintainer: FSF
;; Keywords: AWK, cc-mode, unix, languages
;; This file is part of GNU Emacs.
;; GNU Emacs is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 2, or (at your option)
;; any later version.
;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs; see the file COPYING. If not, write to the
;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
;; Boston, MA 02111-1307, USA.
;;; Commentary:
;; This file contains (most of) the adaptations to cc-mode required for the
;; integration of AWK Mode.
;; It is organised thusly:
;; 1. The AWK Mode syntax table.
;; 2. Indentation calculation stuff ("c-awk-NL-prop text-property").
;; 3. Syntax-table property/font-locking stuff, but not including the
;; font-lock-keywords setting.
;; 4. The AWK Mode before/after-change-functions.
;; 5. AWK Mode specific versions of commands like beginning-of-defun.
;; The AWK Mode keymap, abbreviation table, and the mode function itself are
;; in cc-mode.el.
;;; Code:
(eval-when-compile
(let ((load-path
(if (and (boundp 'byte-compile-dest-file)
(stringp byte-compile-dest-file))
(cons (file-name-directory byte-compile-dest-file) load-path)
load-path)))
(load "cc-bytecomp" nil t)))
(cc-require 'cc-defs)
;; Silence the byte compiler.
(cc-bytecomp-defvar font-lock-mode) ; Checked with boundp before use.
;; Some functions in cc-engine that are used below. There's a cyclic
;; dependency so it can't be required here. (Perhaps some functions
;; could be moved to cc-engine to avoid it.)
(cc-bytecomp-defun c-backward-token-1)
(cc-bytecomp-defun c-beginning-of-statement-1)
(cc-bytecomp-defun c-backward-sws)
(defvar awk-mode-syntax-table
(let ((st (make-syntax-table)))
(modify-syntax-entry ?\\ "\\" st)
(modify-syntax-entry ?\n "> " st)
(modify-syntax-entry ?\r "> " st)
(modify-syntax-entry ?\f "> " st)
(modify-syntax-entry ?\# "< " st)
;; / can delimit regexes or be a division operator. By default we assume
;; that it is a division sign, and fix the regexp operator cases with
;; `font-lock-syntactic-keywords'.
(modify-syntax-entry ?/ "." st) ; ACM 2002/4/27.
(modify-syntax-entry ?* "." st)
(modify-syntax-entry ?+ "." st)
(modify-syntax-entry ?- "." st)
(modify-syntax-entry ?= "." st)
(modify-syntax-entry ?% "." st)
(modify-syntax-entry ?< "." st)
(modify-syntax-entry ?> "." st)
(modify-syntax-entry ?& "." st)
(modify-syntax-entry ?| "." st)
(modify-syntax-entry ?_ "_" st)
(modify-syntax-entry ?\' "." st)
st)
"Syntax table in use in AWK Mode buffers.")
;; ACM, 2002/5/29:
;;
;; The next section of code is about determining whether or not an AWK
;; statement is complete or not. We use this to indent the following line.
;; The determination is pretty straightforward in C, where a statement ends
;; with either a ; or a }. Only "while" really gives any trouble there, since
;; it might be the end of a do-while. In AWK, on the other hand, semicolons
;; are rarely used, and EOLs _usually_ act as "virtual semicolons". In
;; addition, we have the complexity of escaped EOLs. The core of this
;; analysis is in the middle of the function
;; c-awk-calculate-NL-prop-prev-line, about 130 lines lower down.
;;
;; To avoid continually repeating this expensive analysis, we "cache" its
;; result in a text-property, c-awk-NL-prop, whose value for a line is set on
;; the EOL (if any) which terminates that line. Should the property be
;; required for the very last line (which has no EOL), it is calculated as
;; required but not cached. The c-awk-NL-prop property should be thought of
;; as only really valid immediately after a buffer change, not a permanently
;; set property. (By contrast, the syntax-table text properties (set by an
;; after-change function) must be constantly updated for the mode to work
;; properly).
;;
;; The valid values for c-awk-NL-prop are:
;;
;; nil The property is not currently set for this line.
;; '#' There is NO statement on this line (at most a comment), and no open
;; statement from a previous line which could have been completed on this
;; line.
;; '{' There is an unfinished statement on this (or a previous) line which
;; doesn't require \s to continue onto another line, e.g. the line ends
;; with {, or the && operator, or "if (condition)". Note that even if the
;; newline is redundantly escaped, it remains a '{' line.
;; '\' There is an escaped newline at the end of this line and this '\' is
;; essential to the syntax of the program. (i.e. if it had been a
;; frivolous \, it would have been ignored and the line been given one of
;; the other property values.)
;; ';' A statement is completed as the last thing (aside from ws) on the line -
;; i.e. there is (at least part of) a statement on this line, and the last
;; statement on the line is complete, OR (2002/10/25) the line is
;; content-free but terminates a statement from the preceding (continued)
;; line (which has property \).
;;
;; This set of values has been chosen so that the property's value on a line
;; is completely determined by the contents of the line and the property on
;; the previous line, EXCEPT for where a "while" might be the closing
;; statement of a do-while.
(defun c-awk-after-if-for-while-condition-p (&optional do-lim)
;; Are we just after the ) in "if/for/while (<condition>)"?
;;
;; Note that the end of the ) in a do .... while (<condition>) doesn't
;; count, since the purpose of this routine is essentially to decide
;; whether to indent the next line.
;;
;; DO-LIM sets a limit on how far back we search for the "do" of a possible
;; do-while.
(and
(eq (char-before) ?\))
(save-excursion
(let ((par-pos (c-safe (scan-lists (point) -1 0))))
(when par-pos
(goto-char par-pos) ; back over "(...)"
(c-backward-token-1) ; BOB isn't a problem.
(or (looking-at "\\(if\\|for\\)\\>\\([^_]\\|$\\)")
(and (looking-at "while\\>\\([^_]\\|$\\)") ; Ensure this isn't a do-while.
(not (eq (c-beginning-of-statement-1 do-lim)
'beginning)))))))))
(defun c-awk-after-function-decl-param-list ()
;; Are we just after the ) in "function foo (bar)" ?
(and (eq (char-before) ?\))
(save-excursion
(let ((par-pos (c-safe (scan-lists (point) -1 0))))
(when par-pos
(goto-char par-pos) ; back over "(...)"
(c-backward-token-1) ; BOB isn't a problem
(and (looking-at "[_a-zA-Z][_a-zA-Z0-9]*\\>")
(progn (c-backward-token-1)
(looking-at "func\\(tion\\)?\\>"))))))))
;; 2002/11/8: FIXME! Check c-backward-token-1/2 for success (0 return code).
(defun c-awk-after-continue-token ()
;; Are we just after a token which can be continued onto the next line without
;; a backslash?
(save-excursion
(c-backward-token-1) ; FIXME 2002/10/27. What if this fails?
(if (and (looking-at "[&|]") (not (bobp)))
(backward-char)) ; c-backward-token-1 doesn't do this :-(
(looking-at "[,{?:]\\|&&\\|||\\|do\\>\\|else\\>")))
(defun c-awk-after-rbrace-or-statement-semicolon ()
;; Are we just after a } or a ; which closes a statement?
;; Be careful about ;s in for loop control bits. They don't count!
(or (eq (char-before) ?\})
(and
(eq (char-before) ?\;)
(save-excursion
(let ((par-pos (c-safe (scan-lists (point) -1 1))))
(when par-pos
(goto-char par-pos) ; go back to containing (
(not (and (looking-at "(")
(c-backward-token-1) ; BOB isn't a problem
(looking-at "for\\>")))))))))
(defun c-awk-back-to-contentful-text-or-NL-prop ()
;; Move back to just after the first found of either (i) an EOL which has
;; the c-awk-NL-prop text-property set; or (ii) non-ws text; or (iii) BOB.
;; We return either the value of c-awk-NL-prop (in case (i)) or nil.
;; Calling function can best distinguish cases (ii) and (iii) with (bolp).
;;
;; Note that an escaped eol counts as whitespace here.
;;
;; Kludge: If c-backward-syntactic-ws gets stuck at a BOL, it is likely
;; that the previous line contains an unterminated string (without \). In
;; this case, assume that the previous line's c-awk-NL-prop is a ;.
;;
;; POINT MUST BE AT THE START OF A LINE when calling this function. This
;; is to ensure that the various backward-comment functions will work
;; properly.
(let ((nl-prop nil)
bol-pos bsws-pos) ; starting pos for a backward-syntactic-ws call.
(while ;; We are at a BOL here. Go back one line each iteration.
(and
(not (bobp))
(not (setq nl-prop (c-get-char-property (1- (point)) 'c-awk-NL-prop)))
(progn (setq bol-pos (c-point 'bopl))
(setq bsws-pos (point))
;; N.B. the following function will not go back past an EOL if
;; there is an open string (without \) on the previous line.
(c-backward-syntactic-ws bol-pos)
(or (/= (point) bsws-pos)
(progn (setq nl-prop ?\;)
nil)))
;; If we had a backslash at EOL, c-backward-syntactic-ws will
;; have gone backwards over it. Check the backslash was "real".
(progn
(if (looking-at "[ \t]*\\\\+$")
(if (progn
(end-of-line)
(search-backward-regexp
"\\(^\\|[^\\]\\)\\(\\\\\\\\\\)*\\\\$" ; ODD number of \s at EOL :-)
bol-pos t))
(progn (end-of-line) ; escaped EOL.
(backward-char)
(c-backward-syntactic-ws bol-pos))
(end-of-line))) ; The \ at eol is a fake.
(bolp))))
nl-prop))
(defun c-awk-calculate-NL-prop-prev-line (&optional do-lim)
;; Calculate and set the value of the c-awk-NL-prop on the immediately
;; preceding EOL. This may also involve doing the same for several
;; preceding EOLs.
;;
;; NOTE that if the property was already set, we return it without
;; recalculation. (This is by accident rather than design.)
;;
;; Return the property which got set (or was already set) on the previous
;; line. Return nil if we hit BOB.
;;
;; See c-awk-after-if-for-while-condition-p for a description of DO-LIM.
(save-excursion
(save-match-data
(beginning-of-line)
(let* ((pos (point))
(nl-prop (c-awk-back-to-contentful-text-or-NL-prop)))
;; We are either (1) at a BOL (with nl-prop containing the previous
;; line's c-awk-NL-prop) or (2) after contentful text on a line. At
;; the BOB counts as case (1), so we test next for bolp rather than
;; non-nil nl-prop.
(when (not (bolp))
(setq nl-prop
(cond
;; Incomplete statement which doesn't require escaped EOL?
((or (c-awk-after-if-for-while-condition-p do-lim)
(c-awk-after-function-decl-param-list)
(c-awk-after-continue-token))
?\{)
;; Escaped EOL (where there's also something to continue)?
((and (looking-at "[ \t]*\\\\$")
(not (c-awk-after-rbrace-or-statement-semicolon)))
?\\)
(t ?\;))) ; A statement was completed on this line
(end-of-line)
(c-put-char-property (point) 'c-awk-NL-prop nl-prop)
(forward-line))
;; We are now at a (possibly empty) sequence of content-free lines.
;; Set c-awk-NL-prop on each of these lines's EOL.
(while (< (point) pos) ; one content-free line each iteration.
(cond ; recalculate nl-prop from previous line's value.
((memq nl-prop '(?\; nil)) (setq nl-prop ?\#))
((eq nl-prop ?\\)
(if (not (looking-at "[ \t]*\\\\$")) (setq nl-prop ?\;))) ; was ?\# 2002/10/25
;; ?\# (empty line) and ?\{ (open stmt) don't change.
)
(forward-line)
(c-put-char-property (1- (point)) 'c-awk-NL-prop nl-prop))
nl-prop))))
(defun c-awk-get-NL-prop-prev-line (&optional do-lim)
;; Get the c-awk-NL-prop text-property from the previous line, calculating
;; it if necessary. Return nil iff we're already at BOB.
;; See c-awk-after-if-for-while-condition-p for a description of DO-LIM.
(if (bobp)
nil
(or (c-get-char-property (c-point 'eopl) 'c-awk-NL-prop)
(c-awk-calculate-NL-prop-prev-line do-lim))))
(defun c-awk-get-NL-prop-cur-line (&optional do-lim)
;; Get the c-awk-NL-prop text-property from the current line, calculating it
;; if necessary. (As a special case, the property doesn't get set on an
;; empty line at EOB (there's no position to set the property on), but the
;; function returns the property value an EOL would have got.)
;;
;; See c-awk-after-if-for-while-condition-p for a description of DO-LIM.
(save-excursion
(let ((extra-nl nil))
(end-of-line) ; Necessary for the following test to work.
(when (= (forward-line) 1) ; if we were on the last line....
(insert-char ?\n 1) ; ...artificial eol is needed for comment detection.
(setq extra-nl t))
(prog1 (c-awk-get-NL-prop-prev-line do-lim)
(if extra-nl (delete-backward-char 1))))))
(defun c-awk-prev-line-incomplete-p (&optional do-lim)
;; Is there an incomplete statement at the end of the previous line?
;; See c-awk-after-if-for-while-condition-p for a description of DO-LIM.
(memq (c-awk-get-NL-prop-prev-line do-lim) '(?\\ ?\{)))
(defun c-awk-cur-line-incomplete-p (&optional do-lim)
;; Is there an incomplete statement at the end of the current line?
;; See c-awk-after-if-for-while-condition-p for a description of DO-LIM.
(memq (c-awk-get-NL-prop-cur-line do-lim) '(?\\ ?\{)))
(defun c-awk-completed-stmt-ws-ends-prev-line-p (&optional do-lim)
;; Is there a termination of a statement as the last thing (apart from an
;; optional comment) on the previous line?
;; See c-awk-after-if-for-while-condition-p for a description of DO-LIM.
(eq (c-awk-get-NL-prop-prev-line do-lim) ?\;))
(defun c-awk-completed-stmt-ws-ends-line-p (&optional pos do-lim)
;; Same as previous function, but for the line containing position POS (or
;; the current line if POS is omitted).
;; See c-awk-after-if-for-while-condition-p for a description of DO-LIM.
(save-excursion
(if pos (goto-char pos))
(eq (c-awk-get-NL-prop-cur-line do-lim) ?\;)))
(defun c-awk-after-logical-semicolon (&optional do-lim)
;; Are we at BOL, the preceding EOL being a "logical semicolon"?
;; See c-awk-after-if-for-while-condition-p for a description of DO-LIM.
(and (bolp)
(eq (c-awk-get-NL-prop-prev-line do-lim) ?\;)))
(defun c-awk-backward-syntactic-ws (&optional lim)
;; Skip backwards over awk-syntactic whitespace. This is whitespace
;; characters, comments, and NEWLINES WHICH AREN'T "VIRTUAL SEMICOLONS". For
;; this function, a newline isn't a "virtual semicolon" if that line ends with
;; a real semicolon (or closing brace).
;; However if point starts inside a comment or preprocessor directive, the
;; content of it is not treated as whitespace. LIM (optional) sets a limit on
;; the backward movement.
(let ((lim (or lim (point-min)))
after-real-br)
(c-backward-syntactic-ws (max lim (c-point 'bol)))
(while ; go back one WS line each time round this loop.
(and (bolp)
(> (point) lim)
(/= (c-awk-get-NL-prop-prev-line) ?\;)
(/= (point)
;; The following function requires point at BONL [not EOL] to
;; recognise a preceding comment,.
(progn (c-backward-syntactic-ws (max lim (c-point 'bopl)))
(point)))))
;; Does the previous line end with a real ; or }? If so, go back to it.
(if (and (bolp)
(eq (c-awk-get-NL-prop-prev-line) ?\;)
(save-excursion
(c-backward-syntactic-ws (max lim (c-point 'bopl)))
(setq after-real-br (point))
(c-awk-after-rbrace-or-statement-semicolon)))
(goto-char after-real-br))))
(defun c-awk-NL-prop-not-set ()
;; Is the NL-prop on the current line either nil or unset?
(not (c-get-char-property (c-point 'eol) 'c-awk-NL-prop)))
(defun c-awk-clear-NL-props (beg end)
;; This function is run from before-change-hooks. It clears the
;; c-awk-NL-prop text property from beg to the end of the buffer (The END
;; parameter is ignored). This ensures that the indentation engine will
;; never use stale values for this property.
(save-restriction
(widen)
(c-clear-char-properties beg (point-max) 'c-awk-NL-prop)))
(defun c-awk-unstick-NL-prop ()
;; Ensure that the text property c-awk-NL-prop is "non-sticky". Without
;; this, a new newline inserted after an old newline (e.g. by C-j) would
;; inherit any c-awk-NL-prop from the old newline. This would be a Bad
;; Thing. This function's action is required by c-put-char-property.
(if (and (boundp 'text-property-default-nonsticky) ; doesn't exist in Xemacs
(not (assoc 'c-awk-NL-prop text-property-default-nonsticky)))
(setq text-property-default-nonsticky
(cons '(c-awk-NL-prop . t) text-property-default-nonsticky))))
;; The following is purely a diagnostic command, to be commented out of the
;; final release. ACM, 2002/6/1
;; (defun NL-props ()
;; (interactive)
;; (let (pl-prop cl-prop)
;; (message "Prev-line: %s Cur-line: %s"
;; (if (setq pl-prop (c-get-char-property (c-point 'eopl) 'c-awk-NL-prop))
;; (char-to-string pl-prop)
;; "nil")
;; (if (setq cl-prop (c-get-char-property (c-point 'eol) 'c-awk-NL-prop))
;; (char-to-string cl-prop)
;; "nil"))))
;(define-key awk-mode-map [?\C-c ?\r] 'NL-props) ; commented out, 2002/8/31
;for now. In the byte compiled version, this causes things to crash because
;awk-mode-map isn't yet defined. :-(
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; The following section of the code is to do with font-locking. The biggest
;; problem for font-locking is deciding whether a / is a regular expression
;; delimiter or a division sign - determining precisely where strings and
;; regular expressions start and stop is also troublesome. This is the
;; purpose of the function c-awk-set-syntax-table-properties and the myriad
;; elisp regular expressions it uses.
;;
;; Because AWK is a line oriented language, I felt the normal cc-mode strategy
;; for font-locking unterminated strings (i.e. font-locking the buffer up to
;; the next string delimiter as a string) was inappropriate. Instead,
;; unbalanced string/regexp delimiters are given the warning font, being
;; refonted with the string font as soon as the matching delimiter is entered.
;;
;; This requires the region processed by the current font-lock after-change
;; function to have access to the start of the string/regexp, which may be
;; several lines back. The elisp "advice" feature is used on these functions
;; to allow this.
(defun c-awk-beginning-of-logical-line (&optional pos)
;; Go back to the start of the (apparent) current line (or the start of the
;; line containing POS), returning the buffer position of that point. I.e.,
;; go back to the last line which doesn't have an escaped EOL before it.
;;
;; This is guaranteed to be "safe" for syntactic analysis, i.e. outwith any
;; comment, string or regexp. IT MAY WELL BE that this function should not be
;; executed on a narrowed buffer.
(if pos (goto-char pos))
(forward-line 0)
(while (and (> (point) (point-min))
(eq (char-before (1- (point))) ?\\))
(forward-line -1))
(point))
(defun c-awk-end-of-logical-line (&optional pos)
;; Go forward to the end of the (apparent) current logical line (or the end of
;; the line containing POS), returning the buffer position of that point. I.e.,
;; go to the end of the next line which doesn't have an escaped EOL.
;;
;; This is guaranteed to be "safe" for syntactic analysis, i.e. outwith any
;; comment, string or regexp. IT MAY WELL BE that this function should not be
;; executed on a narrowed buffer.
(if pos (goto-char pos))
(end-of-line)
(while (and (< (point) (point-max))
(eq (char-before) ?\\))
(end-of-line 2))
(point))
;; N.B. In the following regexps, an EOL is either \n OR \r. This is because
;; Emacs has in the past used \r to mark hidden lines in some fashion (and
;; maybe still does).
(defconst c-awk-esc-pair-re "\\\\\\(.\\|\n\\|\r\\|\\'\\)")
;; Matches any escaped (with \) character-pair, including an escaped newline.
(defconst c-awk-comment-without-nl "#.*")
;; Matches an AWK comment, not including the terminating NL (if any). Note
;; that the "enclosing" (elisp) regexp must ensure the # is real.
(defconst c-awk-nl-or-eob "\\(\n\\|\r\\|\\'\\)")
;; Matches a newline, or the end of buffer.
;; "Space" regular expressions.
(defconst c-awk-escaped-nl "\\\\[\n\r]")
;; Matches an escaped newline.
(defconst c-awk-escaped-nls* (concat "\\(" c-awk-escaped-nl "\\)*"))
;; Matches a possibly empty sequence of escaped newlines. Used in
;; awk-font-lock-keywords.
;; (defconst c-awk-escaped-nls*-with-space*
;; (concat "\\(" c-awk-escaped-nls* "\\|" "[ \t]+" "\\)*"))
;; The above RE was very slow. It's runtime was doubling with each additional
;; space :-( Reformulate it as below:
(defconst c-awk-escaped-nls*-with-space*
(concat "\\(" c-awk-escaped-nl "\\|" "[ \t]" "\\)*"))
;; Matches a possibly empty sequence of escaped newlines with optional
;; interspersed spaces and tabs. Used in awk-font-lock-keywords.
;; REGEXPS FOR "HARMLESS" STRINGS/LINES.
(defconst c-awk-harmless-char-re "[^_#/\"\\\\\n\r]")
;; Matches any character but a _, #, /, ", \, or newline. N.B. _" starts a
;; localisation string in gawk 3.1
(defconst c-awk-harmless-_ "_\\([^\"]\\|\\'\\)")
;; Matches an underline NOT followed by ".
(defconst c-awk-harmless-string*-re
(concat "\\(" c-awk-harmless-char-re "\\|" c-awk-esc-pair-re "\\|" c-awk-harmless-_ "\\)*"))
;; Matches a (possibly empty) sequence of chars without unescaped /, ", \,
;; #, or newlines.
(defconst c-awk-harmless-string*-here-re
(concat "\\=" c-awk-harmless-string*-re))
;; Matches the (possibly empty) sequence of chars without unescaped /, ", \,
;; at point.
(defconst c-awk-harmless-line-re
(concat c-awk-harmless-string*-re
"\\(" c-awk-comment-without-nl "\\)?" c-awk-nl-or-eob))
;; Matches (the tail of) an AWK \"logical\" line not containing an unescaped
;; " or /. "logical" means "possibly containing escaped newlines". A comment
;; is matched as part of the line even if it contains a " or a /. The End of
;; buffer is also an end of line.
(defconst c-awk-harmless-lines+-here-re
(concat "\\=\\(" c-awk-harmless-line-re "\\)+"))
;; Matches a sequence of (at least one) \"harmless-line\" at point.
;; REGEXPS FOR AWK STRINGS.
(defconst c-awk-string-ch-re "[^\"\\\n\r]")
;; Matches any character which can appear unescaped in a string.
(defconst c-awk-string-innards-re
(concat "\\(" c-awk-string-ch-re "\\|" c-awk-esc-pair-re "\\)*"))
;; Matches the inside of an AWK string (i.e. without the enclosing quotes).
(defconst c-awk-string-without-end-here-re
(concat "\\=_?\"" c-awk-string-innards-re))
;; Matches an AWK string at point up to, but not including, any terminator.
;; A gawk 3.1+ string may look like _"localisable string".
;; REGEXPS FOR AWK REGEXPS.
(defconst c-awk-regexp-normal-re "[^[/\\\n\r]")
;; Matches any AWK regexp character which doesn't require special analysis.
(defconst c-awk-escaped-newlines*-re "\\(\\\\[\n\r]\\)*")
;; Matches a (possibly empty) sequence of escaped newlines.
(defconst c-awk-regexp-char-class-re
(concat "\\[" c-awk-escaped-newlines*-re "^?" c-awk-escaped-newlines*-re "]?"
"\\(" c-awk-esc-pair-re "\\|" "[^]\n\r]" "\\)*" "\\(]\\|$\\)"))
;; Matches a regexp char class, up to (but not including) EOL if the ] is
;; missing.
(defconst c-awk-regexp-innards-re
(concat "\\(" c-awk-esc-pair-re "\\|" c-awk-regexp-char-class-re
"\\|" c-awk-regexp-normal-re "\\)*"))
;; Matches the inside of an AWK regexp (i.e. without the enclosing /s)
(defconst c-awk-regexp-without-end-re
(concat "/" c-awk-regexp-innards-re))
;; Matches an AWK regexp up to, but not including, any terminating /.
;; REGEXPS used for scanning an AWK buffer in order to decide IF A '/' IS A
;; REGEXP OPENER OR A DIVISION SIGN. By "state" in the following is meant
;; whether a '/' at the current position would by a regexp opener or a
;; division sign.
(defconst c-awk-neutral-re
; "\\([{}@` \t]\\|\\+\\+\\|--\\|\\\\.\\)+") ; changed, 2003/6/7
"\\([{}@` \t]\\|\\+\\+\\|--\\|\\\\.\\)")
;; A "neutral" char(pair). Doesn't change the "state" of a subsequent /.
;; This is space/tab, braces, an auto-increment/decrement operator or an
;; escaped character. Or one of the (illegal) characters @ or `. But NOT an
;; end of line (even if escpaed).
(defconst c-awk-neutrals*-re
(concat "\\(" c-awk-neutral-re "\\)*"))
;; A (possibly empty) string of neutral characters (or character pairs).
(defconst c-awk-var-num-ket-re "[]\)0-9a-zA-Z_$.\x80-\xff]+")
;; Matches a char which is a constituent of a variable or number, or a ket
;; (i.e. closing bracKET), round or square. Assume that all characters \x80 to
;; \xff are "letters".
(defconst c-awk-div-sign-re
(concat c-awk-var-num-ket-re c-awk-neutrals*-re "/"))
;; Will match a piece of AWK buffer ending in / which is a division sign, in
;; a context where an immediate / would be a regexp bracket. It follows a
;; variable or number (with optional intervening "neutral" characters). This
;; will only work when there won't be a preceding " or / before the sought /
;; to foul things up.
(defconst c-awk-non-arith-op-bra-re
"[[\(&=:!><,?;'~|]")
;; Matches an openeing BRAcket ,round or square, or any operator character
;; apart from +,-,/,*,%. For the purpose at hand (detecting a / which is a
;; regexp bracket) these arith ops are unnecessary and a pain, because of "++"
;; and "--".
(defconst c-awk-regexp-sign-re
(concat c-awk-non-arith-op-bra-re c-awk-neutrals*-re "/"))
;; Will match a piece of AWK buffer ending in / which is an opening regexp
;; bracket, in a context where an immediate / would be a division sign. This
;; will only work when there won't be a preceding " or / before the sought /
;; to foul things up.
;; ACM, 2002/02/15: The idea of the next function is to put the "Error font"
;; on strings/regexps which are missing their closing delimiter.
;; 2002/4/28. The default syntax for / has been changed from "string" to
;; "punctuation", to reduce hassle when this character appears within a string
;; or comment.
(defun c-awk-set-string-regexp-syntax-table-properties (beg end)
;; BEG and END bracket a (possibly unterminated) string or regexp. The
;; opening delimiter is after BEG, and the closing delimiter, IF ANY, is AFTER
;; END. Set the appropriate syntax-table properties on the delimiters and
;; contents of this string/regex.
;;
;; "String" here can also mean a gawk 3.1 "localizable" string which starts
;; with _". In this case, we step over the _ and ignore it; It will get it's
;; font from an entry in awk-font-lock-keywords.
;;
;; If the closing delimiter is missing (i.e., there is an EOL there) set the
;; STRING-FENCE property on the opening " or / and closing EOL.
(if (eq (char-after beg) ?_) (setq beg (1+ beg)))
;; First put the properties on the delimiters.
(cond ((eq end (point-max)) ; string/regexp terminated by EOB
(put-text-property beg (1+ beg) 'syntax-table '(15))) ; (15) = "string fence"
((/= (char-after beg) (char-after end)) ; missing end delimiter
(put-text-property beg (1+ beg) 'syntax-table '(15))
(put-text-property end (1+ end) 'syntax-table '(15)))
((eq (char-after beg) ?/) ; Properly bracketed regexp
(put-text-property beg (1+ beg) 'syntax-table '(7)) ; (7) = "string"
(put-text-property end (1+ end) 'syntax-table '(7)))
(t)) ; Properly bracketed string: Nothing to do.
;; Now change the properties of any escaped "s in the string to punctuation.
(save-excursion
(goto-char (1+ beg))
(or (eobp)
(while (search-forward "\"" end t)
(put-text-property (1- (point)) (point) 'syntax-table '(1))))))
(defun c-awk-syntax-tablify-string ()
;; Point is at the opening " or _" of a string. Set the syntax-table
;; properties on this string, leaving point just after the string.
;;
;; The result is nil if a / immediately after the string would be a regexp
;; opener, t if it would be a division sign.
(search-forward-regexp c-awk-string-without-end-here-re nil t) ; a (possibly unterminated) string
(c-awk-set-string-regexp-syntax-table-properties
(match-beginning 0) (match-end 0))
(cond ((looking-at "\"")
(forward-char)
t) ; In AWK, ("15" / 5) gives 3 ;-)
((looking-at "[\n\r]") ; Unterminated string with EOL.
(forward-char)
nil) ; / on next line would start a regexp
(t nil))) ; Unterminated string at EOB
(defun c-awk-syntax-tablify-/ (anchor anchor-state-/div)
;; Point is at a /. Determine whether this is a division sign or a regexp
;; opener, and if the latter, apply syntax-table properties to the entire
;; regexp. Point is left immediately after the division sign or regexp, as
;; the case may be.
;;
;; ANCHOR-STATE-/DIV identifies whether a / at ANCHOR would have been a
;; division sign (value t) or a regexp opener (value nil). The idea is that
;; we analyse the line from ANCHOR up till point to determine what the / at
;; point is.
;;
;; The result is what ANCHOR-STATE-/DIV (see above) is where point is left.
(let ((/point (point)))
(goto-char anchor)
;; Analyse the line to find out what the / is.
(if (if anchor-state-/div
(not (search-forward-regexp c-awk-regexp-sign-re (1+ /point) t))
(search-forward-regexp c-awk-div-sign-re (1+ /point) t))
;; A division sign.
(progn (goto-char (1+ /point)) nil)
;; A regexp opener
;; Jump over the regexp innards, setting the match data.
(goto-char /point)
(search-forward-regexp c-awk-regexp-without-end-re)
(c-awk-set-string-regexp-syntax-table-properties
(match-beginning 0) (match-end 0))
(cond ((looking-at "/") ; Terminating /
(forward-char)
t)
((looking-at "[\n\r]") ; Incomplete regexp terminated by EOL
(forward-char)
nil) ; / on next line would start another regexp
(t nil))))) ; Unterminated regexp at EOB
(defun c-awk-set-syntax-table-properties (lim)
;; Scan the buffer text between point and LIM, setting (and clearing) the
;; syntax-table property where necessary.
;;
;; This function is designed to be called as the FUNCTION in a MATCHER in
;; font-lock-syntactic-keywords, and it always returns NIL (to inhibit
;; repeated calls from font-lock: See elisp info page "Search-based
;; Fontification"). It also gets called, with a bit of glue, from
;; after-change-functions when font-lock isn't active. Point is left
;; "undefined" after this function exits. THE BUFFER SHOULD HAVE BEEN
;; WIDENED, AND ANY PRECIOUS MATCH-DATA SAVED BEFORE CALLING THIS ROUTINE.
;;
;; We need to set/clear the syntax-table property on:
;; (i) / - It is set to "string" on a / which is the opening or closing
;; delimiter of the properly terminated regexp (and left unset on a
;; division sign).
;; (ii) the opener of an unterminated string/regexp, we set the property
;; "generic string delimiter" on both the opening " or / and the end of the
;; line where the closing delimiter is missing.
;; (iii) "s inside strings/regexps (these will all be escaped "s). They are
;; given the property "punctuation". This will later allow other routines
;; to use the regexp "\\S\"*" to skip over the string innards.
;; (iv) Inside a comment, all syntax-table properties are cleared.
(let (anchor
(anchor-state-/div nil)) ; t means a following / would be a div sign.
(c-awk-beginning-of-logical-line) ; ACM 2002/7/21. This is probably redundant.
(put-text-property (point) lim 'syntax-table nil)
(search-forward-regexp c-awk-harmless-lines+-here-re nil t) ; skip harmless lines.
;; Once round the next loop for each string, regexp, or div sign
(while (< (point) lim)
(setq anchor (point))
(search-forward-regexp c-awk-harmless-string*-here-re nil t)
;; We are now looking at either a " or a /.
;; Do our thing on the string, regexp or divsion sign.
(setq anchor-state-/div
(if (looking-at "_?\"")
(c-awk-syntax-tablify-string)
(c-awk-syntax-tablify-/ anchor anchor-state-/div)))
;; Skip any further "harmless" lines before the next tricky one.
(if (search-forward-regexp c-awk-harmless-lines+-here-re nil t)
(setq anchor-state-/div nil)))
nil))
;; ACM, 2002/07/21: Thoughts: We need an AWK Mode after-change function to set
;; the syntax-table properties even when font-lock isn't enabled, for the
;; subsequent use of movement functions, etc. However, it seems that if font
;; lock _is_ enabled, we can always leave it to do the job.
(defvar c-awk-old-EOLL 0)
(make-variable-buffer-local 'c-awk-old-EOLL)
;; End of logical line following the region which is about to be changed. Set
;; in c-awk-before-change and used in c-awk-after-change.
(defun c-awk-before-change (beg end)
;; This function is called exclusively from the before-change-functions hook.
;; It does two things: Finds the end of the (logical) line on which END lies,
;; and clears c-awk-NL-prop text properties from this point onwards.
(save-restriction
(save-excursion
(setq c-awk-old-EOLL (c-awk-end-of-logical-line end))
(c-save-buffer-state nil
(c-awk-clear-NL-props end (point-max))))))
(defun c-awk-end-of-change-region (beg end old-len)
;; Find the end of the region which needs to be font-locked after a change.
;; This is the end of the logical line on which the change happened, either
;; as it was before the change, or as it is now, which ever is later.
;; N.B. point is left undefined.
(max (+ (- c-awk-old-EOLL old-len) (- end beg))
(c-awk-end-of-logical-line end)))
(defun c-awk-after-change (beg end old-len)
;; This function is called exclusively as an after-change function in
;; AWK Mode. It ensures that the syntax-table properties get set in the
;; changed region. However, if font-lock is enabled, this function does
;; nothing, since an enabled font-lock after-change function will always do
;; this.
(unless (and (boundp 'font-lock-mode) font-lock-mode)
(save-restriction
(save-excursion
(setq end (c-awk-end-of-change-region beg end old-len))
(c-awk-beginning-of-logical-line beg)
(c-save-buffer-state nil ; So that read-only status isn't affected.
; (e.g. when first loading the buffer)
(c-awk-set-syntax-table-properties end))))))
;; ACM 2002/5/25. When font-locking is invoked by a buffer change, the region
;; specified by the font-lock after-change function must be expanded to
;; include ALL of any string or regexp within the region. The simplest way to
;; do this in practice is to use the beginning/end-of-logical-line functions.
;; Don't overlook the possibility of the buffer change being the "recapturing"
;; of a previously escaped newline.
(defmacro c-awk-advise-fl-for-awk-region (function)
`(defadvice ,function (before get-awk-region activate)
;; When font-locking an AWK Mode buffer, make sure that any string/regexp is
;; completely font-locked.
(when (eq major-mode 'awk-mode)
(save-excursion
(ad-set-arg 1 (c-awk-end-of-change-region
(ad-get-arg 0) ; beg
(ad-get-arg 1) ; end
(ad-get-arg 2))) ; old-len
(ad-set-arg 0 (c-awk-beginning-of-logical-line (ad-get-arg 0)))))))
(c-awk-advise-fl-for-awk-region font-lock-after-change-function)
(c-awk-advise-fl-for-awk-region jit-lock-after-change)
(c-awk-advise-fl-for-awk-region lazy-lock-defer-rest-after-change)
(c-awk-advise-fl-for-awk-region lazy-lock-defer-line-after-change)
;; ACM 2002/9/29. Functions for C-M-a and C-M-e
(defconst c-awk-terminated-regexp-or-string-here-re "\\=\\s\"\\S\"*\\s\"")
;; Matches a terminated string/regexp (utilising syntax-table properties).
(defconst c-awk-unterminated-regexp-or-string-here-re "\\=\\s|\\S|*$")
;; Matches an unterminated string/regexp, NOT including the eol at the end.
(defconst c-awk-harmless-pattern-characters*
(concat "\\([^{;#/\"\\\\\n\r]\\|" c-awk-esc-pair-re "\\)*"))
;; Matches any "harmless" character in a pattern or an escaped character pair.
(defun c-awk-beginning-of-defun (&optional arg)
"Move backward to the beginning of an AWK \"defun\". With ARG, do it that
many times. Negative arg -N means move forward to Nth following beginning of
defun. Returns t unless search stops due to beginning or end of buffer.
By a \"defun\" is meant either a pattern-action pair or a function. The start
of a defun is recognised as code starting at column zero which is neither a
closing brace nor a comment nor a continuation of the previous line. Unlike
in some other modes, having an opening brace at column 0 is neither necessary
nor helpful."
(interactive "p")
(save-match-data
(c-save-buffer-state ; ensures the buffer is writable.
nil
(let ((found t)) ; Has the most recent regexp search found b-of-defun?
(if (>= arg 0)
;; Go back one defun each time round the following loop. (For +ve arg)
(while (and found (> arg 0) (not (eq (point) (point-min))))
;; Go back one "candidate" each time round the next loop until one
;; is genuinely a beginning-of-defun.
(while (and (setq found (search-backward-regexp
"^[^#} \t\n\r]" (point-min) 'stop-at-limit))
(not (memq (c-awk-get-NL-prop-prev-line) '(?\; ?\#)))))
(setq arg (1- arg)))
;; The same for a -ve arg.
(if (not (eq (point) (point-max))) (forward-char 1))
(while (and found (< arg 0) (not (eq (point) (point-max)))) ; The same for -ve arg.
(while (and (setq found (search-forward-regexp
"^[^#} \t\n\r]" (point-max) 'stop-at-limit))
(not (memq (c-awk-get-NL-prop-prev-line) '(?\; ?\#)))))
(setq arg (1+ arg)))
(if found (goto-char (match-beginning 0))))
(eq arg 0)))))
(defun c-awk-forward-awk-pattern ()
;; Point is at the start of an AWK pattern (which may be null) or function
;; declaration. Move to the pattern's end, and past any trailing space or
;; comment. Typically, we stop at the { which denotes the corresponding AWK
;; action/function body. Otherwise we stop at the EOL (or ;) marking the
;; absence of an explicit action.
(while
(progn
(search-forward-regexp c-awk-harmless-pattern-characters*)
(if (looking-at "#") (end-of-line))
(cond
((eobp) nil)
((looking-at "[{;]") nil) ; We've finished!
((eolp)
(if (c-awk-cur-line-incomplete-p)
(forward-line) ; returns non-nil
nil))
((search-forward-regexp c-awk-terminated-regexp-or-string-here-re nil t))
((search-forward-regexp c-awk-unterminated-regexp-or-string-here-re nil t))
((looking-at "/") (forward-char) t))))) ; division sign.
(defun c-awk-end-of-defun1 ()
;; point is at the start of a "defun". Move to its end. Return end position.
(c-awk-forward-awk-pattern)
(cond
((looking-at "{") (goto-char (scan-sexps (point) 1)))
((looking-at ";") (forward-char))
((eolp))
(t (error "c-awk-end-of-defun1: Failure of c-awk-forward-awk-pattern")))
(point))
(defun c-awk-beginning-of-defun-p ()
;; Are we already at the beginning of a defun? (i.e. at code in column 0
;; which isn't a }, and isn't a continuation line of any sort.
(and (looking-at "^[^#} \t\n\r]")
(not (c-awk-prev-line-incomplete-p))))
(defun c-awk-end-of-defun (&optional arg)
"Move forward to next end of defun. With argument, do it that many times.
Negative argument -N means move back to Nth preceding end of defun.
An end of a defun occurs right after the closing brace that matches the
opening brace at its start, or immediately after the AWK pattern when there is
no explicit action; see function `c-awk-beginning-of-defun'."
(interactive "p")
(or arg (setq arg 1))
(save-match-data
(c-save-buffer-state
nil
(let ((start-point (point)) end-point)
;; Strategy: (For +ve ARG): If we're not already at a beginning-of-defun,
;; move backwards to one.
;; Repeat [(i) move forward to end-of-current-defun (see below);
;; (ii) If this isn't it, move forward to beginning-of-defun].
;; We start counting ARG only when step (i) has passed the original point.
(when (> arg 0)
;; Try to move back to a beginning-of-defun, if not already at one.
(if (not (c-awk-beginning-of-defun-p))
(when (not (c-awk-beginning-of-defun 1)) ; No bo-defun before point.
(goto-char start-point)
(c-awk-beginning-of-defun -1))) ; if this fails, we're at EOB, tough!
;; Now count forward, one defun at a time
(while (and (not (eobp))
(c-awk-end-of-defun1)
(if (> (point) start-point) (setq arg (1- arg)) t)
(> arg 0)
(c-awk-beginning-of-defun -1))))
(when (< arg 0)
(setq end-point start-point)
(while (and (not (bobp))
(c-awk-beginning-of-defun 1)
(if (< (setq end-point (if (bobp) (point)
(save-excursion (c-awk-end-of-defun1))))
start-point)
(setq arg (1+ arg)) t)
(< arg 0)))
(goto-char (min start-point end-point)))))))
(cc-provide 'cc-awk) ; Changed from 'awk-mode, ACM 2002/5/21
;;; awk-mode.el ends here

View file

@ -1,6 +1,6 @@
;;; cc-bytecomp.el --- compile time setup for proper compilation
;; Copyright (C) 2000, 01 Free Software Foundation, Inc.
;; Copyright (C) 2000, 01, 02, 03 Free Software Foundation, Inc.
;; Author: Martin Stjernholm
;; Maintainer: bug-cc-mode@gnu.org
@ -34,7 +34,44 @@
;;
;; There's really nothing CC Mode specific here; this functionality
;; ought to be provided by the byte compilers or some accompanying
;; library.
;; library. To use it from some package "foo.el", begin by putting
;; the following blurb at the top of the file:
;;
;; (eval-when-compile
;; (let ((load-path
;; (if (and (boundp 'byte-compile-dest-file)
;; (stringp byte-compile-dest-file))
;; (cons (file-name-directory byte-compile-dest-file) load-path)
;; load-path)))
;; (load "cc-bytecomp" nil t))
;;
;; This (unfortunately rather clumsy) form will ensure that the
;; cc-bytecomp.el in the same directory as foo.el is loaded during
;; byte compilation of the latter.
;;
;; At the end of foo.el there should normally be a "(provide 'foo)".
;; Replace it with "(cc-provide 'foo)"; that is necessary to restore
;; the environment after the byte compilation. If you don't have a
;; `provide' at the end, you have to add the following as the very
;; last form in the file:
;;
;; (eval-when-compile (cc-bytecomp-restore-environment))
;;
;; Now everything is set to use the various functions and macros in
;; this package.
;;
;; If your package is split into several files, you should use
;; `cc-require', `cc-require-when-compile' or `cc-load' to load them.
;; That ensures that the files in the same directory always are
;; loaded, to avoid mixup with other versions of them that might exist
;; elsewhere in the load path.
;;
;; To suppress byte compiler warnings, use the macros
;; `cc-bytecomp-defun', `cc-bytecomp-defvar',
;; `cc-bytecomp-obsolete-fun', and `cc-bytecomp-obsolete-var'.
;;
;; This file is not used at all after the package has been byte
;; compiled. It is however necessary when running uncompiled.
;;; Code:
@ -42,53 +79,20 @@
(defvar cc-bytecomp-unbound-variables nil)
(defvar cc-bytecomp-original-functions nil)
(defvar cc-bytecomp-original-properties nil)
(defvar cc-bytecomp-load-depth 0)
(defvar cc-bytecomp-loaded-files nil)
(defvar cc-bytecomp-environment-set nil)
(put 'cc-eval-when-compile 'lisp-indent-hook 0)
(defmacro cc-eval-when-compile (&rest body)
"Like `progn', but evaluates the body at compile time.
The result of the body appears to the compiler as a quoted constant.
This variant works around what looks like a bug in
`eval-when-compile': During byte compilation it byte compiles its
contents before evaluating it. That can cause forms to be compiled in
situations they aren't intended to be compiled. See cc-bytecomp.el
for further discussion."
;;
;; Example: It's not possible to defsubst a primitive, e.g. the
;; following will produce an error (in any emacs flavor), since
;; `nthcdr' is a primitive function that's handled specially by the
;; byte compiler and thus can't be redefined:
;;
;; (defsubst nthcdr (val) val)
;;
;; `defsubst', like `defmacro', needs to be evaluated at compile
;; time, so this will produce an error during byte compilation.
;;
;; CC Mode occasionally needs to do things like this for cross-emacs
;; compatibility (although we try to avoid it since it results in
;; byte code that isn't compatible between emacsen). It therefore
;; uses the following to conditionally do a `defsubst':
;;
;; (eval-when-compile
;; (if (not (fboundp 'foo))
;; (defsubst foo ...)))
;;
;; But `eval-when-compile' byte compiles its contents and _then_
;; evaluates it (in all current emacs versions, up to and including
;; Emacs 20.6 and XEmacs 21.1 as of this writing). So this will
;; still produce an error, since the byte compiler will get to the
;; defsubst anyway. That's arguably a bug because the point with
;; `eval-when-compile' is that it should evaluate rather than
;; compile its contents.
`(eval-when-compile (eval '(progn ,@body))))
(defmacro cc-bytecomp-debug-msg (&rest args)
;;`(message ,@args)
)
(defun cc-bytecomp-setup-environment ()
;; Eval'ed during compilation to setup variables, functions etc
;; declared with `cc-bytecomp-defvar' et al.
(if (= cc-bytecomp-load-depth 0)
(if (not load-in-progress)
;; Look at `load-in-progress' to tell whether we're called
;; directly in the file being compiled or just from some file
;; being loaded during compilation.
(let (p)
(if cc-bytecomp-environment-set
(error "Byte compilation environment already set - \
@ -98,46 +102,85 @@ perhaps a `cc-bytecomp-restore-environment' is forgotten somewhere"))
(if (not (boundp (car p)))
(progn
(eval `(defvar ,(car p)))
(set (car p) 'cc-bytecomp-ignore)))
(set (car p) (intern (concat "cc-bytecomp-ignore-var:"
(symbol-name (car p)))))
(cc-bytecomp-debug-msg
"cc-bytecomp-setup-environment: Covered variable %s"
(car p))))
(setq p (cdr p)))
(setq p cc-bytecomp-original-functions)
(while p
(let ((fun (car (car p)))
(temp-macro (car (cdr (car p)))))
(if temp-macro
(eval `(defmacro ,fun ,@temp-macro))
(fset fun 'cc-bytecomp-ignore)))
(if (not (fboundp fun))
(if temp-macro
(progn
(eval `(defmacro ,fun ,@temp-macro))
(cc-bytecomp-debug-msg
"cc-bytecomp-setup-environment: Bound macro %s" fun))
(fset fun (intern (concat "cc-bytecomp-ignore-fun:"
(symbol-name fun))))
(cc-bytecomp-debug-msg
"cc-bytecomp-setup-environment: Covered function %s" fun))))
(setq p (cdr p)))
(setq p cc-bytecomp-original-properties)
(while p
(let ((sym (car (car (car p))))
(prop (cdr (car (car p))))
(tempdef (car (cdr (car p)))))
(put sym prop tempdef))
(put sym prop tempdef)
(cc-bytecomp-debug-msg
"cc-bytecomp-setup-environment: Bound property %s for %s to %s"
prop sym tempdef))
(setq p (cdr p)))
(setq cc-bytecomp-environment-set t))))
(setq cc-bytecomp-environment-set t)
(cc-bytecomp-debug-msg
"cc-bytecomp-setup-environment: Done"))))
(defun cc-bytecomp-restore-environment ()
;; Eval'ed during compilation to restore variables, functions etc
;; declared with `cc-bytecomp-defvar' et al.
(if (= cc-bytecomp-load-depth 0)
(if (not load-in-progress)
(let (p)
(setq p cc-bytecomp-unbound-variables)
(while p
(let ((var (car p)))
(if (and (boundp var)
(eq var 'cc-bytecomp-ignore))
(makunbound var)))
(if (boundp var)
(if (eq (intern (concat "cc-bytecomp-ignore-var:"
(symbol-name var)))
(symbol-value var))
(progn
(makunbound var)
(cc-bytecomp-debug-msg
"cc-bytecomp-restore-environment: Unbound variable %s"
var))
(cc-bytecomp-debug-msg
"cc-bytecomp-restore-environment: Not restoring variable %s"
var))))
(setq p (cdr p)))
(setq p cc-bytecomp-original-functions)
(while p
(let ((fun (car (car p)))
(temp-macro (car (cdr (car p))))
(def (car (cdr (cdr (car p))))))
(if (and (fboundp fun)
(eq (symbol-function fun) 'cc-bytecomp-ignore))
(if (eq def 'unbound)
(fmakunbound fun)
(fset fun def))))
(if (fboundp fun)
(if (eq (or temp-macro
(intern (concat "cc-bytecomp-ignore-fun:"
(symbol-name fun))))
(symbol-function fun))
(if (eq def 'unbound)
(progn
(fmakunbound fun)
(cc-bytecomp-debug-msg
"cc-bytecomp-restore-environment: Unbound function %s"
fun))
(fset fun def)
(cc-bytecomp-debug-msg
"cc-bytecomp-restore-environment: Restored function %s"
fun))
(cc-bytecomp-debug-msg
"cc-bytecomp-restore-environment: Not restoring function %s"
fun))))
(setq p (cdr p)))
(setq p cc-bytecomp-original-properties)
(while p
@ -146,40 +189,60 @@ perhaps a `cc-bytecomp-restore-environment' is forgotten somewhere"))
(tempdef (car (cdr (car p))))
(origdef (cdr (cdr (car p)))))
(if (eq (get sym prop) tempdef)
(put sym prop origdef)))
(progn
(put sym prop origdef)
(cc-bytecomp-debug-msg
"cc-bytecomp-restore-environment: Restored property %s for %s to %s"
prop sym origdef))
(cc-bytecomp-debug-msg
"cc-bytecomp-restore-environment: Not restoring property %s for %s"
prop sym)))
(setq p (cdr p)))
(setq cc-bytecomp-environment-set nil))))
(setq cc-bytecomp-environment-set nil)
(cc-bytecomp-debug-msg
"cc-bytecomp-restore-environment: Done"))))
(defun cc-bytecomp-load (cc-part)
;; Eval'ed during compilation to load a CC Mode file from the source
;; directory (assuming it's the same as the compiled file
;; destination dir).
(if (and (boundp 'byte-compile-dest-file)
(stringp byte-compile-dest-file))
(progn
(cc-bytecomp-restore-environment)
(let ((cc-bytecomp-load-depth (1+ cc-bytecomp-load-depth))
(load-path
(cons (file-name-directory byte-compile-dest-file)
load-path))
(cc-file (concat cc-part ".el")))
(if (member cc-file cc-bytecomp-loaded-files)
()
(setq cc-bytecomp-loaded-files
(cons cc-file cc-bytecomp-loaded-files))
(load cc-file nil t t)))
(cc-bytecomp-setup-environment)
t)))
(eval
;; This eval is to avoid byte compilation of the function below.
;; There's some bug in XEmacs 21.4.6 that can cause it to dump core
;; here otherwise. My theory is that `cc-bytecomp-load' might be
;; redefined recursively during the `load' inside it, and if it in
;; that case is byte compiled then the byte interpreter gets
;; confused. I haven't succeeded in isolating the bug, though. /mast
'(defun cc-bytecomp-load (cc-part)
;; Eval'ed during compilation to load a CC Mode file from the source
;; directory (assuming it's the same as the compiled file
;; destination dir).
(if (and (boundp 'byte-compile-dest-file)
(stringp byte-compile-dest-file))
(progn
(cc-bytecomp-restore-environment)
(let ((load-path
(cons (file-name-directory byte-compile-dest-file)
load-path))
(cc-file (concat cc-part ".el")))
(if (member cc-file cc-bytecomp-loaded-files)
()
(setq cc-bytecomp-loaded-files
(cons cc-file cc-bytecomp-loaded-files))
(cc-bytecomp-debug-msg
"cc-bytecomp-load: Loading %S" cc-file)
(load cc-file nil t t)
(cc-bytecomp-debug-msg
"cc-bytecomp-load: Loaded %S" cc-file)))
(cc-bytecomp-setup-environment)
t))))
(defmacro cc-require (cc-part)
"Force loading of the corresponding .el file in the current
directory during compilation, but compile in a `require'. Don't use
within `eval-when-compile'.
"Force loading of the corresponding .el file in the current directory
during compilation, but compile in a `require'. Don't use within
`eval-when-compile'.
Having cyclic cc-require's will result in infinite recursion. That's
somewhat intentional."
`(progn
(cc-eval-when-compile (cc-bytecomp-load (symbol-name ,cc-part)))
(eval-when-compile (cc-bytecomp-load (symbol-name ,cc-part)))
(require ,cc-part)))
(defmacro cc-provide (feature)
@ -190,9 +253,9 @@ after the compilation. Don't use within `eval-when-compile'."
(provide ,feature)))
(defmacro cc-load (cc-part)
"Force loading of the corresponding .el file in the current
directory during compilation. Don't use outside `eval-when-compile'
or `eval-and-compile'.
"Force loading of the corresponding .el file in the current directory
during compilation. Don't use outside `eval-when-compile' or
`eval-and-compile'.
Having cyclic cc-load's will result in infinite recursion. That's
somewhat intentional."
@ -200,6 +263,27 @@ somewhat intentional."
(cc-bytecomp-load ,cc-part))
(load ,cc-part nil t nil)))
(defmacro cc-require-when-compile (cc-part)
"Force loading of the corresponding .el file in the current directory
during compilation, but do a compile time `require' otherwise. Don't
use within `eval-when-compile'."
`(eval-when-compile
(if (and (featurep 'cc-bytecomp)
(cc-bytecomp-is-compiling))
(if (or (not load-in-progress)
(not (featurep ,cc-part)))
(cc-bytecomp-load (symbol-name ,cc-part)))
(require ,cc-part))))
(defmacro cc-external-require (feature)
"Do a `require' of an external package.
This restores and sets up the compilation environment before and
afterwards. Don't use within `eval-when-compile'."
`(progn
(eval-when-compile (cc-bytecomp-restore-environment))
(require ,feature)
(eval-when-compile (cc-bytecomp-setup-environment))))
(defun cc-bytecomp-is-compiling ()
"Return non-nil if eval'ed during compilation. Don't use outside
`eval-when-compile'."
@ -211,58 +295,95 @@ somewhat intentional."
to silence the byte compiler. Don't use within `eval-when-compile'."
`(eval-when-compile
(if (boundp ',var)
nil
(cc-bytecomp-debug-msg
"cc-bytecomp-defvar: %s bound already as variable" ',var)
(if (not (memq ',var cc-bytecomp-unbound-variables))
(setq cc-bytecomp-unbound-variables
(cons ',var cc-bytecomp-unbound-variables)))
(progn
(cc-bytecomp-debug-msg
"cc-bytecomp-defvar: Saving %s (as unbound)" ',var)
(setq cc-bytecomp-unbound-variables
(cons ',var cc-bytecomp-unbound-variables))))
(if (and (cc-bytecomp-is-compiling)
(= cc-bytecomp-load-depth 0))
(not load-in-progress))
(progn
(defvar ,var)
(set ',var 'cc-bytecomp-ignore))))))
(set ',var (intern (concat "cc-bytecomp-ignore-var:"
(symbol-name ',var))))
(cc-bytecomp-debug-msg
"cc-bytecomp-defvar: Covered variable %s" ',var))))))
(defmacro cc-bytecomp-defun (fun)
"Bind the symbol as a function during compilation of the file,
to silence the byte compiler. Don't use within `eval-when-compile'."
to silence the byte compiler. Don't use within `eval-when-compile'.
If the symbol already is bound as a function, it will keep that
definition. That means that this macro will not shut up warnings
about incorrect number of arguments. It's dangerous to try to replace
existing functions since the byte compiler might need the definition
at compile time, e.g. for macros and inline functions."
`(eval-when-compile
(if (fboundp ',fun)
nil
(cc-bytecomp-debug-msg
"cc-bytecomp-defun: %s bound already as function" ',fun)
(if (not (assq ',fun cc-bytecomp-original-functions))
(setq cc-bytecomp-original-functions
(cons (list ',fun nil 'unbound)
cc-bytecomp-original-functions)))
(progn
(cc-bytecomp-debug-msg
"cc-bytecomp-defun: Saving %s (as unbound)" ',fun)
(setq cc-bytecomp-original-functions
(cons (list ',fun nil 'unbound)
cc-bytecomp-original-functions))))
(if (and (cc-bytecomp-is-compiling)
(= cc-bytecomp-load-depth 0))
(fset ',fun 'cc-bytecomp-ignore)))))
(not load-in-progress))
(progn
(fset ',fun (intern (concat "cc-bytecomp-ignore-fun:"
(symbol-name ',fun))))
(cc-bytecomp-debug-msg
"cc-bytecomp-defun: Covered function %s" ',fun))))))
(put 'cc-bytecomp-defmacro 'lisp-indent-function 'defun)
(defmacro cc-bytecomp-defmacro (fun &rest temp-macro)
"Bind the symbol as a macro during compilation (and evaluation) of the
file. Don't use outside `eval-when-compile'."
`(progn
(if (not (assq ',fun cc-bytecomp-original-functions))
(setq cc-bytecomp-original-functions
(cons (list ',fun
',temp-macro
(if (fboundp ',fun)
(symbol-function ',fun)
'unbound))
cc-bytecomp-original-functions)))
(defmacro ,fun ,@temp-macro)))
`(let ((orig-fun (assq ',fun cc-bytecomp-original-functions)))
(if (not orig-fun)
(setq orig-fun
(list ',fun
nil
(if (fboundp ',fun)
(progn
(cc-bytecomp-debug-msg
"cc-bytecomp-defmacro: Saving %s" ',fun)
(symbol-function ',fun))
(cc-bytecomp-debug-msg
"cc-bytecomp-defmacro: Saving %s as unbound" ',fun)
'unbound))
cc-bytecomp-original-functions
(cons orig-fun cc-bytecomp-original-functions)))
(defmacro ,fun ,@temp-macro)
(cc-bytecomp-debug-msg
"cc-bytecomp-defmacro: Bound macro %s" ',fun)
(setcar (cdr orig-fun) (symbol-function ',fun))))
(defmacro cc-bytecomp-put (symbol propname value)
"Set a property on a symbol during compilation (and evaluation) of
the file. Don't use outside `eval-when-compile'."
`(cc-eval-when-compile
`(eval-when-compile
(if (not (assoc (cons ,symbol ,propname) cc-bytecomp-original-properties))
(setq cc-bytecomp-original-properties
(cons (cons (cons ,symbol ,propname)
(cons ,value (get ,symbol ,propname)))
cc-bytecomp-original-properties)))
(put ,symbol ,propname ,value)))
(progn
(cc-bytecomp-debug-msg
"cc-bytecomp-put: Saving property %s for %s with value %s"
,propname ,symbol (get ,symbol ,propname))
(setq cc-bytecomp-original-properties
(cons (cons (cons ,symbol ,propname)
(cons ,value (get ,symbol ,propname)))
cc-bytecomp-original-properties))))
(put ,symbol ,propname ,value)
(cc-bytecomp-debug-msg
"cc-bytecomp-put: Bound property %s for %s to %s"
,propname ,symbol ,value)))
(defmacro cc-bytecomp-obsolete-var (symbol)
"Suppress warnings about that the given symbol is an obsolete variable.
"Suppress warnings that the given symbol is an obsolete variable.
Don't use within `eval-when-compile'."
`(eval-when-compile
(if (get ',symbol 'byte-obsolete-variable)
@ -278,21 +399,38 @@ Don't use within `eval-when-compile'."
(byte-compile-obsolete form)))
(defmacro cc-bytecomp-obsolete-fun (symbol)
"Suppress warnings about that the given symbol is an obsolete function.
"Suppress warnings that the given symbol is an obsolete function.
Don't use within `eval-when-compile'."
`(eval-when-compile
(if (eq (get ',symbol 'byte-compile) 'byte-compile-obsolete)
(cc-bytecomp-put ',symbol 'byte-compile
'cc-bytecomp-ignore-obsolete))))
'cc-bytecomp-ignore-obsolete)
;; This avoids a superfluous compiler warning
;; about calling `get' for effect.
t)))
;; Override ourselves with a version loaded from source if we're
;; compiling, like cc-require does for all the other files.
(if (and (cc-bytecomp-is-compiling)
(= cc-bytecomp-load-depth 0))
(let ((load-path
(cons (file-name-directory byte-compile-dest-file) load-path))
(cc-bytecomp-load-depth 1))
(load "cc-bytecomp.el" nil t t)))
(defmacro cc-bytecomp-boundp (symbol)
"Return non-nil if the given symbol is bound as a variable outside
the compilation. This is the same as using `boundp' but additionally
exclude any variables that have been bound during compilation with
`cc-bytecomp-defvar'."
(if (and (cc-bytecomp-is-compiling)
(memq (car (cdr symbol)) cc-bytecomp-unbound-variables))
nil
`(boundp ,symbol)))
(defmacro cc-bytecomp-fboundp (symbol)
"Return non-nil if the given symbol is bound as a function outside
the compilation. This is the same as using `fboundp' but additionally
exclude any functions that have been bound during compilation with
`cc-bytecomp-defun'."
(let (fun-elem)
(if (and (cc-bytecomp-is-compiling)
(setq fun-elem (assq (car (cdr symbol))
cc-bytecomp-original-functions))
(eq (elt fun-elem 2) 'unbound))
nil
`(fboundp ,symbol))))
(provide 'cc-bytecomp)

File diff suppressed because it is too large Load diff

View file

@ -1,10 +1,9 @@
;;; cc-compat.el --- cc-mode compatibility with c-mode.el confusion
;; Copyright (C) 1985,1987,1992-2001 Free Software Foundation, Inc.
;; Copyright (C) 1985,1987,1992-2003 Free Software Foundation, Inc.
;; Authors: 2000- Martin Stjernholm
;; 1998-1999 Barry A. Warsaw and Martin Stjernholm
;; 1994-1997 Barry A. Warsaw
;; Authors: 1998- Martin Stjernholm
;; 1994-1999 Barry A. Warsaw
;; Maintainer: bug-cc-mode@gnu.org
;; Created: August 1994, split from cc-mode.el
;; Version: See cc-mode.el
@ -51,7 +50,7 @@
(stringp byte-compile-dest-file))
(cons (file-name-directory byte-compile-dest-file) load-path)
load-path)))
(require 'cc-bytecomp)))
(load "cc-bytecomp" nil t)))
(cc-require 'cc-defs)
(cc-require 'cc-vars)
@ -106,7 +105,7 @@ This is in addition to c-continued-statement-offset.")
(if (eq (char-before) ?{)
(forward-char -1)
(goto-char (cdr langelem)))
(let* ((curcol (save-excursion
(let* ((curcol (save-excursion
(goto-char (cdr langelem))
(current-column)))
(bocm-lossage
@ -138,7 +137,7 @@ This is in addition to c-continued-statement-offset.")
(defun cc-block-close-offset (langelem)
(save-excursion
(let* ((here (point))
bracep
bracep
(curcol (progn
(goto-char (cdr langelem))
(current-column)))
@ -154,7 +153,7 @@ This is in addition to c-continued-statement-offset.")
(current-column))))
(- bocm-lossage curcol
(if bracep 0 c-indent-level)))))
(defun cc-substatement-open-offset (langelem)
(+ c-continued-statement-offset c-continued-brace-offset))

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

2879
lisp/progmodes/cc-fonts.el Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,10 +1,9 @@
;;; cc-menus.el --- imenu support for CC Mode
;; Copyright (C) 1985,1987,1992-2001 Free Software Foundation, Inc.
;; Copyright (C) 1985,1987,1992-2003 Free Software Foundation, Inc.
;; Authors: 2000- Martin Stjernholm
;; 1998-1999 Barry A. Warsaw and Martin Stjernholm
;; 1992-1997 Barry A. Warsaw
;; Authors: 1998- Martin Stjernholm
;; 1992-1999 Barry A. Warsaw
;; 1987 Dave Detlefs and Stewart Clamen
;; 1985 Richard M. Stallman
;; Maintainer: bug-cc-mode@gnu.org
@ -39,11 +38,14 @@
(stringp byte-compile-dest-file))
(cons (file-name-directory byte-compile-dest-file) load-path)
load-path)))
(require 'cc-bytecomp)))
(load "cc-bytecomp" nil t)))
(cc-require 'cc-defs)
;; The things referenced in imenu, which we don't require.
(cc-bytecomp-defvar imenu-case-fold-search)
(cc-bytecomp-defvar imenu-generic-expression)
(cc-bytecomp-defvar imenu-create-index-function)
(cc-bytecomp-defun imenu-progress-message)
@ -71,10 +73,10 @@ A sample value might look like: `\\(_P\\|_PROTO\\)'.")
(nil
,(concat
"^\\<.*"
"[^a-zA-Z0-9_:<>~]" ; match any non-identifier char
"[^" c-alnum "_:<>~]" ; match any non-identifier char
; (note: this can be `\n')
"\\("
"\\([a-zA-Z0-9_:<>~]*::\\)?" ; match an operator
"\\([" c-alnum "_:<>~]*::\\)?" ; match an operator
"operator\\>[ \t]*"
"\\(()\\|[^(]*\\)" ; special case for `()' operator
"\\)"
@ -93,7 +95,7 @@ A sample value might look like: `\\(_P\\|_PROTO\\)'.")
(nil
,(concat
"^"
"\\([a-zA-Z_][a-zA-Z0-9_:<>~]*\\)" ; match function name
"\\([" c-alpha "_][" c-alnum "_:<>~]*\\)" ; match function name
"[ \t]*(" ; see above, BUT
"[ \t]*\\([^ \t(*][^)]*\\)?)" ; the arg list must not start
"[ \t]*[^ \t;(]" ; with an asterisk or parentheses
@ -103,8 +105,8 @@ A sample value might look like: `\\(_P\\|_PROTO\\)'.")
,(concat
"^\\<" ; line MUST start with word char
"[^()]*" ; no parentheses before
"[^a-zA-Z0-9_:<>~]" ; match any non-identifier char
"\\([a-zA-Z_][a-zA-Z0-9_:<>~]*\\)" ; match function name
"[^" c-alnum "_:<>~]" ; match any non-identifier char
"\\([" c-alpha "_][" c-alnum "_:<>~]*\\)" ; match function name
"\\([ \t\n]\\|\\\\\n\\)*(" ; see above, BUT the arg list
"\\([ \t\n]\\|\\\\\n\\)*\\([^ \t\n(*][^)]*\\)?)" ; must not start
"\\([ \t\n]\\|\\\\\n\\)*[^ \t\n;(]" ; with an asterisk or parentheses
@ -117,27 +119,27 @@ A sample value might look like: `\\(_P\\|_PROTO\\)'.")
`((nil
,(concat
"^\\<.*" ; line MUST start with word char
"[^a-zA-Z0-9_]" ; match any non-identifier char
"\\([a-zA-Z_][a-zA-Z0-9_]*\\)" ; match function name
"[^" c-alnum "_]" ; match any non-identifier char
"\\([" c-alpha "_][" c-alnum "_]*\\)" ; match function name
"[ \t]*" ; whitespace before macro name
cc-imenu-c-prototype-macro-regexp
"[ \t]*(" ; ws followed by first paren.
"[ \t]*([^)]*)[ \t]*)[ \t]*[^ \t;]" ; see above
) 1)))
;; Class definitions
("Class"
("Class"
,(concat
"^" ; beginning of line is required
"\\(template[ \t]*<[^>]+>[ \t]*\\)?" ; there may be a `template <...>'
"\\(class\\|struct\\)[ \t]+"
"\\(" ; the string we want to get
"[a-zA-Z0-9_]+" ; class name
"[" c-alnum "_]+" ; class name
"\\(<[^>]+>\\)?" ; possibly explicitly specialized
"\\)"
"\\([ \t\n]\\|\\\\\n\\)*[:{]"
) 3))
"Imenu generic expression for C++ mode. See `imenu-generic-expression'.")
(defvar cc-imenu-c-generic-expression
cc-imenu-c++-generic-expression
"Imenu generic expression for C mode. See `imenu-generic-expression'.")
@ -145,21 +147,24 @@ A sample value might look like: `\\(_P\\|_PROTO\\)'.")
(defvar cc-imenu-java-generic-expression
`((nil
,(concat
"^\\([ \t]\\)*"
"\\([.A-Za-z0-9_-]+[ \t]+\\)?" ; type specs; there can be
"\\([.A-Za-z0-9_-]+[ \t]+\\)?" ; more than 3 tokens, right?
"\\([.A-Za-z0-9_-]+[ \t]*[[]?[]]?\\)"
"\\([ \t]\\)"
"\\([A-Za-z0-9_-]+\\)" ; the string we want to get
"\\([ \t]*\\)+("
"[][a-zA-Z,_1-9\n \t]*" ; arguments
")[ \t]*"
; "[^;(]"
"[,a-zA-Z_1-9\n \t]*{"
) 6))
"[" c-alpha "_][\]\[." c-alnum "_]+[ \t\n\r]+" ; type spec
"\\([" c-alpha "_][" c-alnum "_]+\\)" ; method name
"[ \t\n\r]*"
;; An argument list that is either empty or contains at least
;; two identifiers with only space between them. This avoids
;; matching e.g. "else if (foo)".
(concat "([ \t\n\r]*"
"\\([\]\[.," c-alnum "_]+"
"[ \t\n\r]+"
"[\]\[.," c-alnum "_]"
"[\]\[.," c-alnum "_ \t\n\r]*"
"\\)?)")
"[.," c-alnum "_ \t\n\r]*"
"{"
) 1))
"Imenu generic expression for Java mode. See `imenu-generic-expression'.")
;; *Warning for cc-mode developers*
;; *Warning for cc-mode developers*
;;
;; `cc-imenu-objc-generic-expression' elements depend on
;; `cc-imenu-c++-generic-expression'. So if you change this
@ -169,8 +174,8 @@ A sample value might look like: `\\(_P\\|_PROTO\\)'.")
;; order to know where the each regexp *group \\(foobar\\)* elements
;; are started.
;;
;; *-index variables are initialized during `cc-imenu-objc-generic-expression'
;; being initialized.
;; *-index variables are initialized during `cc-imenu-objc-generic-expression'
;; being initialized.
;;
;; Internal variables
@ -179,10 +184,10 @@ A sample value might look like: `\\(_P\\|_PROTO\\)'.")
(defvar cc-imenu-objc-generic-expression-proto-index nil)
(defvar cc-imenu-objc-generic-expression-objc-base-index nil)
(defvar cc-imenu-objc-generic-expression
(concat
(defvar cc-imenu-objc-generic-expression
(concat
;;
;; For C
;; For C
;;
;; > Special case to match a line like `main() {}'
;; > e.g. no return type, not even on the previous line.
@ -192,52 +197,53 @@ A sample value might look like: `\\(_P\\|_PROTO\\)'.")
"\\|"
;; > General function name regexp
;; Pick a token by (match-string 3)
(car (cdr (nth 2 cc-imenu-c++-generic-expression))) ; -> index += 2
(car (cdr (nth 2 cc-imenu-c++-generic-expression))) ; -> index += 5
(prog2 (setq cc-imenu-objc-generic-expression-general-func-index 3) "")
;; > Special case for definitions using phony prototype macros like:
;; > `int main _PROTO( (int argc,char *argv[]) )'.
;; Pick a token by (match-string 5)
;; Pick a token by (match-string 8)
(if cc-imenu-c-prototype-macro-regexp
(concat
(concat
"\\|"
(car (cdr (nth 3 cc-imenu-c++-generic-expression))) ; -> index += 1
(prog2 (setq cc-imenu-objc-generic-expression-objc-base-index 6) "")
(prog2 (setq cc-imenu-objc-generic-expression-objc-base-index 9) "")
)
(prog2 (setq cc-imenu-objc-generic-expression-objc-base-index 5) "")
(prog2 (setq cc-imenu-objc-generic-expression-objc-base-index 8) "")
"") ; -> index += 0
(prog2 (setq cc-imenu-objc-generic-expression-proto-index 5) "")
(prog2 (setq cc-imenu-objc-generic-expression-proto-index 8) "")
;;
;; For Objective-C
;; Pick a token by (match-string 5 or 6)
;; Pick a token by (match-string 8 or 9)
;;
"\\|\\("
"^[-+][:a-zA-Z0-9()*_<>\n\t ]*[;{]" ; Methods
"\\|"
"^@interface[\t ]+[a-zA-Z0-9_]+[\t ]*:"
"\\|"
"^@interface[\t ]+[a-zA-Z0-9_]+[\t ]*([a-zA-Z0-9_]+)"
"\\|"
"\\|\\("
"^[-+][:" c-alnum "()*_<>\n\t ]*[;{]" ; Methods
"\\|"
"^@interface[\t ]+[" c-alnum "_]+[\t ]*:"
"\\|"
"^@interface[\t ]+[" c-alnum "_]+[\t ]*([" c-alnum "_]+)"
"\\|"
;; For NSObject, NSProxy and Object... They don't have super class.
"^@interface[\t ]+[a-zA-Z0-9_]+[\t ]*.*$"
"\\|"
"^@implementation[\t ]+[a-zA-Z0-9_]+[\t ]*([a-zA-Z0-9_]+)"
"\\|"
"^@implementation[\t ]+[a-zA-Z0-9_]+"
"\\|"
"^@protocol[\t ]+[a-zA-Z0-9_]+" "\\)")
"^@interface[\t ]+[" c-alnum "_]+[\t ]*.*$"
"\\|"
"^@implementation[\t ]+[" c-alnum "_]+[\t ]*([" c-alnum "_]+)"
"\\|"
"^@implementation[\t ]+[" c-alnum "_]+"
"\\|"
"^@protocol[\t ]+[" c-alnum "_]+" "\\)")
"Imenu generic expression for ObjC mode. See `imenu-generic-expression'.")
;; Imenu support for objective-c uses functions.
(defsubst cc-imenu-objc-method-to-selector (method)
"Return the objc selector style string of METHOD.
Example:
Example:
- perform: (SEL)aSelector withObject: object1 withObject: object2; /* METHOD */
=>
-perform:withObject:withObject:withObject: /* selector */"
;; This function does not do any hidden buffer changes.
(let ((return "") ; String to be returned
(p 0) ; Current scanning position in METHOD
(pmax (length method)) ;
(p 0) ; Current scanning position in METHOD
(pmax (length method)) ;
char ; Current scanning target
(betweenparen 0) ; CHAR is in parentheses.
argreq ; An argument is required.
@ -253,17 +259,17 @@ Example:
(and (<= ?A char) (<= char ?Z))
(and (<= ?0 char) (<= char ?9))
(= ?_ char)))
(if argreq
(if argreq
(setq inargvar t
argreq nil)
(setq return (concat return (char-to-string char)))))
;; Or a white space?
((and inargvar (or (eq ?\ char) (eq ?\n char))
((and inargvar (or (eq ?\ char) (eq ?\n char))
(setq inargvar nil)))
;; Or a method separator?
;; If a method separator, the next token will be an argument variable.
((eq ?: char)
(setq argreq t
((eq ?: char)
(setq argreq t
return (concat return (char-to-string char))))
;; Or an open parentheses?
((eq ?\( char)
@ -275,9 +281,10 @@ Example:
(defun cc-imenu-objc-remove-white-space (str)
"Remove all spaces and tabs from STR."
;; This function does not do any hidden buffer changes.
(let ((return "")
(p 0)
(max (length str))
(max (length str))
char)
(while (< p max)
(setq char (aref str p))
@ -289,12 +296,13 @@ Example:
(defun cc-imenu-objc-function ()
"imenu supports for objc-mode."
;; This function does not do any hidden buffer changes.
(let (methodlist
clist
;;
;; OBJC, Cnoreturn, Cgeneralfunc, Cproto are constants.
;;
;; *Warning for developers*
;; *Warning for developers*
;; These constants depend on `cc-imenu-c++-generic-expression'.
;;
(OBJC cc-imenu-objc-generic-expression-objc-base-index)
@ -310,13 +318,13 @@ Example:
toplist
stupid
str
str2
str2
(intflen (length "@interface"))
(implen (length "@implementation"))
(prtlen (length "@protocol"))
(func
;;
;; Does this emacs has buffer-substring-no-properties?
;; Does this emacs has buffer-substring-no-properties?
;;
(if (fboundp 'buffer-substring-no-properties)
'buffer-substring-no-properties
@ -326,7 +334,7 @@ Example:
;;
(while (re-search-backward cc-imenu-objc-generic-expression nil t)
(imenu-progress-message stupid)
(setq langnum (if (match-beginning OBJC)
(setq langnum (if (match-beginning OBJC)
OBJC
(cond
((match-beginning Cproto) Cproto)
@ -334,7 +342,7 @@ Example:
((match-beginning Cnoreturn) Cnoreturn))))
(setq str (funcall func (match-beginning langnum) (match-end langnum)))
;;
(cond
(cond
;;
;; C
;;
@ -342,7 +350,7 @@ Example:
(setq clist (cons (cons str (match-beginning langnum)) clist)))
;;
;; ObjC
;;
;;
;; An instance Method
((eq (aref str 0) ?-)
(setq str (concat "-" (cc-imenu-objc-method-to-selector str)))
@ -355,10 +363,10 @@ Example:
(setq methodlist (cons (cons str
(match-beginning langnum))
methodlist)))
;; Interface or implementation or protocol
;; Interface or implementation or protocol
((eq (aref str 0) ?@)
(setq classcount (1+ classcount))
(cond
(cond
((and (> (length str) implen)
(string= (substring str 0 implen) "@implementation"))
(setq str (substring str implen)
@ -376,7 +384,7 @@ Example:
(setq toplist (cons nil (cons (cons str
methodlist) toplist))
methodlist nil))))
;;
;;
(imenu-progress-message stupid 100)
(if (eq (car toplist) nil)
(setq toplist (cdr toplist)))
@ -395,7 +403,8 @@ Example:
(setq last (cdr last)))
(setcdr last clist))))
;; Add C lang tokens as a sub menu
(setq toplist (cons (cons "C" clist) toplist)))
(if clist
(setq toplist (cons (cons "C" clist) toplist))))
;;
toplist
))
@ -404,9 +413,13 @@ Example:
; ())
; FIXME: Please contribute one!
(defun cc-imenu-init (mode-generic-expression)
(defun cc-imenu-init (mode-generic-expression
&optional mode-create-index-function)
;; This function does not do any hidden buffer changes.
(setq imenu-generic-expression mode-generic-expression
imenu-case-fold-search nil))
imenu-case-fold-search nil)
(when mode-create-index-function
(setq imenu-create-index-function mode-create-index-function)))
(cc-provide 'cc-menus)

File diff suppressed because it is too large Load diff

View file

@ -1,10 +1,9 @@
;;; cc-styles.el --- support for styles in CC Mode
;; Copyright (C) 1985,1987,1992-2001 Free Software Foundation, Inc.
;; Copyright (C) 1985,1987,1992-2003 Free Software Foundation, Inc.
;; Authors: 2000- Martin Stjernholm
;; 1998-1999 Barry A. Warsaw and Martin Stjernholm
;; 1992-1997 Barry A. Warsaw
;; Authors: 1998- Martin Stjernholm
;; 1992-1999 Barry A. Warsaw
;; 1987 Dave Detlefs and Stewart Clamen
;; 1985 Richard M. Stallman
;; Maintainer: bug-cc-mode@gnu.org
@ -39,10 +38,9 @@
(stringp byte-compile-dest-file))
(cons (file-name-directory byte-compile-dest-file) load-path)
load-path)))
(require 'cc-bytecomp)))
(load "cc-bytecomp" nil t)))
(cc-require 'cc-defs)
(cc-require 'cc-langs)
(cc-require 'cc-vars)
(cc-require 'cc-align)
;; cc-align is only indirectly required: Styles added with
@ -135,6 +133,12 @@
(namespace-open . +)
(innamespace . c-lineup-whitesmith-in-block)
(namespace-close . +)
(module-open . +)
(inmodule . c-lineup-whitesmith-in-block)
(module-close . +)
(composition-open . +)
(incomposition . c-lineup-whitesmith-in-block)
(composition-close . +)
))
)
("ellemtel"
@ -242,6 +246,8 @@ the existing style.")
;; Functions that manipulate styles
(defun c-set-style-1 (conscell dont-override)
;; Set the style for one variable
;;
;; This function does not do any hidden buffer changes.
(let ((attr (car conscell))
(val (cdr conscell)))
(cond
@ -285,6 +291,8 @@ the existing style.")
(defun c-get-style-variables (style basestyles)
;; Return all variables in a style by resolving inheritances.
;;
;; This function does not do any hidden buffer changes.
(if (not style)
(copy-alist c-fallback-style)
(let ((vars (cdr (or (assoc (downcase style) c-style-alist)
@ -367,10 +375,10 @@ when used elsewhere."
(c-keep-region-active))
;;;###autoload
(defun c-add-style (style descrip &optional set-p)
(defun c-add-style (style description &optional set-p)
"Adds a style to `c-style-alist', or updates an existing one.
STYLE is a string identifying the style to add or update. DESCRIP is
an association list describing the style and must be of the form:
STYLE is a string identifying the style to add or update. DESCRIPTION
is an association list describing the style and must be of the form:
([BASESTYLE] (VARIABLE . VALUE) [(VARIABLE . VALUE) ...])
@ -380,14 +388,14 @@ STYLE using `c-set-style' if the optional SET-P flag is non-nil."
(interactive
(let ((stylename (completing-read "Style to add: " c-style-alist
nil nil nil 'c-set-style-history))
(description (eval-minibuffer "Style description: ")))
(list stylename description
(descr (eval-minibuffer "Style description: ")))
(list stylename descr
(y-or-n-p "Set the style too? "))))
(setq style (downcase style))
(let ((s (assoc style c-style-alist)))
(if s
(setcdr s (copy-alist descrip)) ; replace
(setq c-style-alist (cons (cons style descrip) c-style-alist))))
(setcdr s (copy-alist description)) ; replace
(setq c-style-alist (cons (cons style description) c-style-alist))))
(and set-p (c-set-style style)))
@ -396,6 +404,8 @@ STYLE using `c-set-style' if the optional SET-P flag is non-nil."
(defun c-read-offset (langelem)
;; read new offset value for LANGELEM from minibuffer. return a
;; legal value only
;;
;; This function does not do any hidden buffer changes.
(let* ((oldoff (cdr-safe (or (assq langelem c-offsets-alist)
(assq langelem (get 'c-offsets-alist
'c-stylevar-fallback)))))
@ -446,9 +456,10 @@ and exists only for compatibility reasons."
;; on the syntactic analysis list for the current
;; line
(and c-buffer-is-cc-mode
(let* ((syntax (c-guess-basic-syntax))
(len (length syntax))
(ic (format "%s" (car (nth (1- len) syntax)))))
(c-save-buffer-state
((syntax (c-guess-basic-syntax))
(len (length syntax))
(ic (format "%s" (car (nth (1- len) syntax)))))
(cons ic 0)))
)))
(offset (c-read-offset langelem)))
@ -471,6 +482,9 @@ and exists only for compatibility reasons."
"Fix things up for paragraph recognition and filling inside comments by
incorporating the value of `c-comment-prefix-regexp' in the relevant
variables."
;;
;; This function does not do any hidden buffer changes.
(setq c-current-comment-prefix
(if (listp c-comment-prefix-regexp)
(cdr-safe (or (assoc major-mode c-comment-prefix-regexp)
@ -479,11 +493,11 @@ variables."
(let ((comment-line-prefix
(concat "[ \t]*\\(" c-current-comment-prefix "\\)[ \t]*")))
(setq paragraph-start (concat comment-line-prefix
(c-lang-var paragraph-start)
c-paragraph-start
"\\|"
page-delimiter)
paragraph-separate (concat comment-line-prefix
(c-lang-var paragraph-separate)
c-paragraph-separate
"\\|"
page-delimiter)
paragraph-ignore-fill-prefix t
@ -521,6 +535,8 @@ CC Mode by making sure the proper entries are present on
;; This function is intended to be used explicitly by the end user
;; only.
;;
;; This function does not do any hidden buffer changes.
;; The default configuration already handles C++ comments, but we
;; need to add handling of C block comments. A new filladapt token
;; `c-comment' is added for that.
@ -549,6 +565,8 @@ CC Mode by making sure the proper entries are present on
;; crucial because future c-set-style calls will always reset the
;; variables first to the `cc-mode' style before instituting the new
;; style. Only do this once!
;;
;; This function does not do any hidden buffer changes.
(unless (get 'c-initialize-builtin-style 'is-run)
(put 'c-initialize-builtin-style 'is-run t)
;;(c-initialize-cc-mode)
@ -573,24 +591,16 @@ CC Mode by making sure the proper entries are present on
(defun c-make-styles-buffer-local (&optional this-buf-only-p)
"Make all CC Mode style variables buffer local.
If you edit primarily one style of C (or C++, Objective-C, Java, etc)
code, you probably want style variables to be global. This is the
default.
If `this-buf-only-p' is non-nil, the style variables will be made
buffer local only in the current buffer. Otherwise they'll be made
permanently buffer local in any buffer that change their values.
If you edit many different styles of C (or C++, Objective-C, Java,
etc) at the same time, you probably want the CC Mode style variables
to be buffer local. If you do, it's advisable to set any CC Mode
style variables in a hook function (e.g. off of `c-mode-common-hook'),
instead of at the top level of your ~/.emacs file.
The buffer localness of the style variables are normally controlled
with the variable `c-style-variables-are-local-p', so there's seldom
any reason to call this function directly."
;;
;; This function does not do any hidden buffer changes.
This function makes all the CC Mode style variables buffer local.
Call it after CC Mode is loaded into your Emacs environment.
Conversely, set the variable `c-style-variables-are-local-p' to t in
your .emacs file, before CC Mode is loaded, and this function will be
automatically called when CC Mode is loaded.
Optional argument, when non-nil, means use `make-local-variable'
instead of `make-variable-buffer-local'."
;; style variables
(let ((func (if this-buf-only-p
'make-local-variable

View file

@ -1,10 +1,9 @@
;;; cc-vars.el --- user customization variables for CC Mode
;; Copyright (C) 1985,1987,1992-2001 Free Software Foundation, Inc.
;; Copyright (C) 1985,1987,1992-2003 Free Software Foundation, Inc.
;; Authors: 2000- Martin Stjernholm
;; 1998-1999 Barry A. Warsaw and Martin Stjernholm
;; 1992-1997 Barry A. Warsaw
;; Authors: 1998- Martin Stjernholm
;; 1992-1999 Barry A. Warsaw
;; 1987 Dave Detlefs and Stewart Clamen
;; 1985 Richard M. Stallman
;; Maintainer: bug-cc-mode@gnu.org
@ -39,7 +38,7 @@
(stringp byte-compile-dest-file))
(cons (file-name-directory byte-compile-dest-file) load-path)
load-path)))
(require 'cc-bytecomp)))
(load "cc-bytecomp" nil t)))
(cc-require 'cc-defs)
@ -50,9 +49,27 @@
;; Pull in custom if it exists and is recent enough (the one in Emacs
;; 19.34 isn't).
(eval-when-compile
(require 'custom)
(require 'wid-edit))
(eval
(cc-eval-when-compile
(condition-case nil
(progn
(require 'custom)
(or (fboundp 'defcustom) (error ""))
(require 'widget)
'(progn ; Compile in the require's.
(require 'custom)
(require 'widget)))
(error
(message "Warning: Compiling without Customize support \
since a (good enough) custom library wasn't found")
(cc-bytecomp-defmacro define-widget (name class doc &rest args))
(cc-bytecomp-defmacro defgroup (symbol members doc &rest args))
(cc-bytecomp-defmacro defcustom (symbol value doc &rest args)
`(defvar ,symbol ,value ,doc))
(cc-bytecomp-defmacro custom-declare-variable (symbol value doc
&rest args)
`(defvar ,(eval symbol) ,(eval value) ,doc))
nil))))
(cc-eval-when-compile
;; Need the function form of `backquote', which isn't standardized
@ -66,7 +83,7 @@
;;; Helpers
;; This widget will show up in newer versions of the Custom library
;; This widget exists in newer versions of the Custom library
(or (get 'other 'widget-type)
(define-widget 'other 'sexp
"Matches everything, but doesn't let the user edit the value.
@ -104,13 +121,51 @@ Useful as last item in a `choice' widget."
:tag "Optional integer"
:match (lambda (widget value) (or (integerp value) (null value))))
(define-widget 'c-symbol-list 'sexp
"A single symbol or a list of symbols."
:tag "Symbols separated by spaces"
:validate 'widget-field-validate
:match
(lambda (widget value)
(or (symbolp value)
(catch 'ok
(while (listp value)
(unless (symbolp (car value))
(throw 'ok nil))
(setq value (cdr value)))
(null value))))
:value-to-internal
(lambda (widget value)
(cond ((null value)
"")
((symbolp value)
(symbol-name value))
((consp value)
(mapconcat (lambda (symbol)
(symbol-name symbol))
value
" "))
(t
value)))
:value-to-external
(lambda (widget value)
(if (stringp value)
(let (list end)
(while (string-match "\\S +" value end)
(setq list (cons (intern (match-string 0 value)) list)
end (match-end 0)))
(if (and list (not (cdr list)))
(car list)
(nreverse list)))
value)))
(defvar c-style-variables
'(c-basic-offset c-comment-only-line-offset c-indent-comment-alist
c-indent-comments-syntactically-p c-block-comment-prefix
c-comment-prefix-regexp c-cleanup-list c-hanging-braces-alist
c-hanging-colons-alist c-hanging-semi&comma-criteria c-backslash-column
c-backslash-max-column c-special-indent-hook c-label-minimum-indentation
c-offsets-alist)
c-comment-prefix-regexp c-doc-comment-style c-cleanup-list
c-hanging-braces-alist c-hanging-colons-alist
c-hanging-semi&comma-criteria c-backslash-column c-backslash-max-column
c-special-indent-hook c-label-minimum-indentation c-offsets-alist)
"List of the style variables.")
(defvar c-fallback-style nil)
@ -152,6 +207,7 @@ the value set here overrides the style system (there is a variable
(defun c-valid-offset (offset)
"Return non-nil iff OFFSET is a valid offset for a syntactic symbol.
See `c-offsets-alist'."
;; This function does not do any hidden buffer changes.
(or (eq offset '+)
(eq offset '-)
(eq offset '++)
@ -268,7 +324,7 @@ it might complicate editing if CC Mode doesn't recognize the context
of the macro content. The default context inside the macro is the
same as the top level, so if it contains \"bare\" statements they
might be indented wrongly, although there are special cases that
handles this in most cases. If this problem occurs, it's usually
handle this in most cases. If this problem occurs, it's usually
countered easily by surrounding the statements by a block \(or even
better with the \"do { ... } while \(0)\" trick)."
:type 'boolean
@ -434,7 +490,7 @@ which is sometimes inserted by CC Mode inside block comments. It
should not match any surrounding whitespace.
Note that CC Mode uses this variable to set many other variables that
handles the paragraph filling. That's done at mode initialization or
handle the paragraph filling. That's done at mode initialization or
when you switch to a style which sets this variable. Thus, if you
change it in some other way, e.g. interactively in a CC Mode buffer,
you will need to do \\[c-mode] (or whatever mode you're currently
@ -466,6 +522,74 @@ to redo it."
(const :format "Other " other) (regexp :format "%v"))))
:group 'c)
(defcustom-c-stylevar c-doc-comment-style
'((java-mode . javadoc)
(pike-mode . autodoc))
"*Specifies documentation comment style(s) to recognize.
This is primarily used to fontify doc comments and the markup within
them, e.g. Javadoc comments.
The value can be any of the following symbols for various known doc
comment styles:
javadoc -- Javadoc style for \"/** ... */\" comments (default in Java mode).
autodoc -- Pike autodoc style for \"//! ...\" comments (default in Pike mode).
The value may also be a list of doc comment styles, in which case all
of them are recognized simultaneously (presumably with markup cues
that don't conflict).
The value may also be an association list to specify different doc
comment styles for different languages. The symbol for the major mode
is then looked up in the alist, and the value of that element is
interpreted as above if found. If it isn't found then the symbol
`other' is looked up and its value is used instead.
Note that CC Mode uses this variable to set other variables that
handle fontification etc. That's done at mode initialization or when
you switch to a style which sets this variable. Thus, if you change
it in some other way, e.g. interactively in a CC Mode buffer, you will
need to do \\[java-mode] (or whatever mode you're currently using) to
reinitialize.
Note also that when CC Mode starts up, the other variables are
modified before the mode hooks are run. If you change this variable
in a mode hook, you have to call `c-setup-doc-comment-style'
afterwards to redo that work."
;; Symbols other than those documented above may be used on this
;; variable. If a variable exists that has that name with
;; "-font-lock-keywords" appended, it's value is prepended to the
;; font lock keywords list. If it's a function then it's called and
;; the result is prepended.
:type '(radio
(c-symbol-list :tag "Doc style(s) in all modes")
(list
:tag "Mode-specific doc styles"
(set
:inline t :format "%v"
(cons :format "%v"
(const :format "C " c-mode)
(c-symbol-list :format "%v"))
(cons :format "%v"
(const :format "C++ " c++-mode)
(c-symbol-list :format "%v"))
(cons :format "%v"
(const :format "ObjC " objc-mode)
(c-symbol-list :format "%v"))
(cons :format "%v"
(const :format "Java " java-mode)
(c-symbol-list :format "%v"))
(cons :format "%v"
(const :format "IDL " idl-mode)
(c-symbol-list :format "%v"))
(cons :format "%v"
(const :format "Pike " pike-mode)
(c-symbol-list :format "%v"))
(cons :format "%v"
(const :format "Other " other)
(c-symbol-list :format "%v")))))
:group 'c)
(defcustom c-ignore-auto-fill '(string cpp code)
"*List of contexts in which automatic filling never occurs.
If Auto Fill mode is active, it will be temporarily disabled if point
@ -559,9 +683,13 @@ involve auto-newline inserted newlines:
(defcustom-c-stylevar c-hanging-braces-alist '((brace-list-open)
(brace-entry-open)
(statement-cont)
(substatement-open after)
(block-close . c-snug-do-while)
(extern-lang-open after)
(namespace-open after)
(module-open after)
(composition-open after)
(inexpr-class-open after)
(inexpr-class-close before))
"*Controls the insertion of newlines before and after braces
@ -575,16 +703,13 @@ associated ACTION is used to determine where newlines are inserted.
If the context is not found, the default is to insert a newline both
before and after the brace.
SYNTACTIC-SYMBOL can be any of: defun-open, defun-close, class-open,
class-close, inline-open, inline-close, block-open, block-close,
substatement-open, statement-case-open, extern-lang-open,
extern-lang-close, brace-list-open, brace-list-close,
brace-list-intro, brace-entry-open, namespace-open, namespace-close,
inexpr-class-open, or inexpr-class-close. See `c-offsets-alist' for
details, except for inexpr-class-open and inexpr-class-close, which
doesn't have any corresponding symbols there. Those two symbols are
used for the opening and closing braces, respectively, of anonymous
inner classes in Java.
SYNTACTIC-SYMBOL can be statement-cont, brace-list-intro,
inexpr-class-open, inexpr-class-close, and any of the *-open and
*-close symbols. See `c-offsets-alist' for details, except for
inexpr-class-open and inexpr-class-close, which doesn't have any
corresponding symbols there. Those two symbols are used for the
opening and closing braces, respectively, of anonymous inner classes
in Java.
ACTION can be either a function symbol or a list containing any
combination of the symbols `before' or `after'. If the list is empty,
@ -616,11 +741,13 @@ syntactic context for the brace line."
class-open class-close
inline-open inline-close
block-open block-close
substatement-open statement-case-open
extern-lang-open extern-lang-close
statement-cont substatement-open statement-case-open
brace-list-open brace-list-close
brace-list-intro brace-entry-open
extern-lang-open extern-lang-close
namespace-open namespace-close
module-open module-close
composition-open composition-close
inexpr-class-open inexpr-class-close)))
:group 'c)
@ -700,7 +827,7 @@ space."
:group 'c)
(defcustom c-delete-function 'delete-char
"*Function called by `c-electric-delete' when deleting forwards."
"*Function called by `c-electric-delete-forward' when deleting forwards."
:type 'function
:group 'c)
@ -928,11 +1055,11 @@ can always override the use of `c-default-style' by making calls to
(arglist-cont . (c-lineup-gcc-asm-reg 0))
;; Relpos: At the first token after the open paren.
(arglist-cont-nonempty . (c-lineup-gcc-asm-reg c-lineup-arglist))
;; Relpos: Boi at the open paren, or at the first non-ws after
;; the open paren of the surrounding sexp, whichever is later.
;; Relpos: At the containing statement(*).
;; 2nd pos: At the open paren.
(arglist-close . +)
;; Relpos: Boi at the open paren, or at the first non-ws after
;; the open paren of the surrounding sexp, whichever is later.
;; Relpos: At the containing statement(*).
;; 2nd pos: At the open paren.
(stream-op . c-lineup-streamop)
;; Relpos: Boi at the first stream op in the statement.
(inclass . +)
@ -953,19 +1080,21 @@ can always override the use of `c-default-style' by making calls to
(objc-method-call-cont . c-lineup-ObjC-method-call)
;; Relpos: At the open bracket.
(extern-lang-open . 0)
;; Relpos: Boi at the extern keyword.
(extern-lang-close . 0)
;; Relpos: Boi at the corresponding extern keyword.
(inextern-lang . +)
;; Relpos: At the extern block open brace if it's at boi,
;; otherwise boi at the extern keyword.
(namespace-open . 0)
;; Relpos: Boi at the namespace keyword.
(module-open . 0)
(composition-open . 0)
;; Relpos: Boi at the extern/namespace/etc keyword.
(extern-lang-close . 0)
(namespace-close . 0)
;; Relpos: Boi at the corresponding namespace keyword.
(module-close . 0)
(composition-close . 0)
;; Relpos: Boi at the corresponding extern/namespace/etc keyword.
(inextern-lang . +)
(innamespace . +)
;; Relpos: At the namespace block open brace if it's at boi,
;; otherwise boi at the namespace keyword.
(inmodule . +)
(incomposition . +)
;; Relpos: At the extern/namespace/etc block open brace if it's
;; at boi, otherwise boi at the keyword.
(template-args-cont . (c-lineup-template-args +))
;; Relpos: Boi at the decl start. This might be changed; the
;; logical position is clearly the opening '<'.
@ -1014,7 +1143,7 @@ If OFFSET is one of the symbols `+', `-', `++', `--', `*', or `/', a
positive or negative multiple of `c-basic-offset' is added; 1, -1, 2,
-2, 0.5, and -0.5, respectively.
If OFFSET is a vector, its first element, which must be an integer,
If OFFSET is a vector, it's first element, which must be an integer,
is used as an absolute indentation column. This overrides all
relative offsets. If there are several syntactic elements which
evaluates to absolute indentation columns, the first one takes
@ -1103,14 +1232,19 @@ Here is the current list of valid syntactic element symbols:
objc-method-intro -- The first line of an Objective-C method definition.
objc-method-args-cont -- Lines continuing an Objective-C method definition.
objc-method-call-cont -- Lines continuing an Objective-C method call.
extern-lang-open -- Brace that opens an external language block.
extern-lang-close -- Brace that closes an external language block.
extern-lang-open -- Brace that opens an \"extern\" block.
extern-lang-close -- Brace that closes an \"extern\" block.
inextern-lang -- Analogous to the `inclass' syntactic symbol,
but used inside extern constructs.
namespace-open -- Brace that opens a C++ namespace block.
namespace-close -- Brace that closes a C++ namespace block.
innamespace -- Analogous to the `inextern-lang' syntactic
symbol, but used inside C++ namespace constructs.
but used inside \"extern\" blocks.
namespace-open, namespace-close, innamespace
-- Similar to the three `extern-lang' symbols, but for
C++ \"namespace\" blocks.
module-open, module-close, inmodule
-- Similar to the three `extern-lang' symbols, but for
CORBA IDL \"module\" blocks.
composition-open, composition-close, incomposition
-- Similar to the three `extern-lang' symbols, but for
CORBA CIDL \"composition\" blocks.
template-args-cont -- C++ template argument list continuations.
inlambda -- In the header or body of a lambda function.
lambda-intro-cont -- Continuation of the header of a lambda function.
@ -1144,18 +1278,24 @@ buffer local by default. If nil, they will remain global. Variables
are made buffer local when this file is loaded, and once buffer
localized, they cannot be made global again.
This variable must be set appropriately before CC Mode is loaded.
The list of variables to buffer localize are:
c-offsets-alist
c-basic-offset
c-comment-only-line-offset
c-indent-comment-alist
c-indent-comments-syntactically-p
c-block-comment-prefix
c-comment-prefix-regexp
c-doc-comment-style
c-cleanup-list
c-hanging-braces-alist
c-hanging-colons-alist
c-hanging-semi&comma-criteria
c-backslash-column
c-backslash-max-column
c-label-minimum-indentation
c-offsets-alist
c-special-indent-hook
c-indentation-style"
:type 'boolean
@ -1193,7 +1333,7 @@ The list of variables to buffer localize are:
(defcustom c-mode-common-hook nil
"*Hook called by all CC Mode modes for common initializations."
:type '(hook :format "%{CC Mode Common Hook%}:\n%v")
:type 'hook
:group 'c)
(defcustom c-initialization-hook nil
@ -1230,6 +1370,106 @@ all style variables are per default set in a special non-override
state. Set this variable only if your configuration has stopped
working due to this change.")
(define-widget 'c-extra-types-widget 'radio
;; Widget for a list of regexps for the extra types.
:args '((const :tag "none" nil)
(repeat :tag "types" regexp)))
(eval-and-compile
;; XEmacs 19 evaluates this at compile time below, while most other
;; versions delays the evaluation until the package is loaded.
(defun c-make-font-lock-extra-types-blurb (mode1 mode2 example)
(concat "\
*List of extra types (aside from the type keywords) to recognize in "
mode1 " mode.
Each list item should be a regexp matching a single identifier.
" example "
On decoration level 3 (and higher, where applicable), a method is used
that finds most types and declarations by syntax alone. This variable
is still used as a first step, but other types are recognized
correctly anyway in most cases. Therefore this variable should be
fairly restrictive and not contain patterns that are uncertain.
Note that this variable is only consulted when the major mode is
initialized. If you change it later you have to reinitialize CC Mode
by doing \\[" mode2 "].
Despite the name, this variable is not only used for font locking but
also elsewhere in CC Mode to tell types from other identifiers.")))
;; Note: Most of the variables below are also defined in font-lock.el
;; in older versions in Emacs, so depending on the load order we might
;; not install the values below. There's no kludge to cope with this
;; (as opposed to the *-font-lock-keywords-* variables) since the old
;; values works fairly well anyway.
(defcustom c-font-lock-extra-types
'("FILE" "\\sw+_t"
"bool" "complex" "imaginary" ; Defined in C99.
;; I do not appreciate the following very Emacs-specific luggage
;; in the default value, but otoh it can hardly get in the way for
;; other users, and removing it would cause unnecessary grief for
;; the old timers that are used to it. /mast
"Lisp_Object")
(c-make-font-lock-extra-types-blurb "C" "c-mode"
"For example, a value of (\"FILE\" \"\\\\sw+_t\") means the word FILE
and words ending in _t are treated as type names.")
:type 'c-extra-types-widget
:group 'c)
(defcustom c++-font-lock-extra-types
'("\\sw+_t"
"\\([iof]\\|str\\)+stream\\(buf\\)?" "ios"
"string" "rope"
"list" "slist"
"deque" "vector" "bit_vector"
"set" "multiset"
"map" "multimap"
"hash\\(_\\(m\\(ap\\|ulti\\(map\\|set\\)\\)\\|set\\)\\)?"
"stack" "queue" "priority_queue"
"type_info"
"iterator" "const_iterator" "reverse_iterator" "const_reverse_iterator"
"reference" "const_reference")
(c-make-font-lock-extra-types-blurb "C++" "c++-mode"
"For example, a value of (\"string\") means the word string is treated
as a type name.")
:type 'c-extra-types-widget
:group 'c)
(defcustom objc-font-lock-extra-types
(list (concat "[" c-upper "]\\sw*[" c-lower "]\\sw*"))
(c-make-font-lock-extra-types-blurb "ObjC" "objc-mode" (concat
"For example, a value of (\"[" c-upper "]\\\\sw*[" c-lower "]\\\\sw*\") means
capitalized words are treated as type names (the requirement for a
lower case char is to avoid recognizing all-caps macro and constant
names)."))
:type 'c-extra-types-widget
:group 'c)
(defcustom java-font-lock-extra-types
(list (concat "[" c-upper "]\\sw*[" c-lower "]\\sw*"))
(c-make-font-lock-extra-types-blurb "Java" "java-mode" (concat
"For example, a value of (\"[" c-upper "]\\\\sw*[" c-lower "]\\\\sw*\") means
capitalized words are treated as type names (the requirement for a
lower case char is to avoid recognizing all-caps constant names)."))
:type 'c-extra-types-widget
:group 'c)
(defcustom idl-font-lock-extra-types nil
(c-make-font-lock-extra-types-blurb "IDL" "idl-mode" "")
:type 'c-extra-types-widget
:group 'c)
(defcustom pike-font-lock-extra-types
(list (concat "[" c-upper "]\\sw*[" c-lower "]\\sw*"))
(c-make-font-lock-extra-types-blurb "Pike" "pike-mode" (concat
"For example, a value of (\"[" c-upper "]\\\\sw*[" c-lower "]\\\\sw*\") means
capitalized words are treated as type names (the requirement for a
lower case char is to avoid recognizing all-caps macro and constant
names)."))
:type 'c-extra-types-widget
:group 'c)
;; Non-customizable variables, still part of the interface to CC Mode
@ -1254,10 +1494,35 @@ Note that file offset settings are applied after file style settings
as designated in the variable `c-file-style'.")
(make-variable-buffer-local 'c-file-offsets)
(defvar c-syntactic-context nil
"Variable containing syntactic analysis list during indentation.
This is always bound dynamically. It should never be set statically
\(e.g. with `setq').")
;; It isn't possible to specify a docstring without specifying an
;; initial value with `defvar', so the following two variables have
;; only doc comments even though they are part of the API. It's
;; really good not to have an initial value for variables like these
;; that always should be dynamically bound, so it's worth the
;; inconvenience.
(cc-bytecomp-defvar c-syntactic-context)
(defvar c-syntactic-context)
;; Variable containing the syntactic analysis list during indentation.
;; It is a list with one element for each found syntactic symbol.
;; Each element is a list with the symbol name in the first position,
;; followed by zero or more elements containing any additional info
;; associated with the syntactic symbol. Specifically, the second
;; element is the relpos (a.k.a. anchor position), or nil if there
;; isn't any. See the comments in the `c-offsets-alist' variable for
;; more detailed info about the data each syntactic symbol provides.
;;
;; This is always bound dynamically. It should never be set
;; statically (e.g. with `setq').
(cc-bytecomp-defvar c-syntactic-element)
(defvar c-syntactic-element)
;; Variable containing the info regarding the current syntactic
;; element during calls to the lineup functions. The value is one of
;; the elements in the list in `c-syntactic-context'.
;;
;; This is always bound dynamically. It should never be set
;; statically (e.g. with `setq').
(defvar c-indentation-style nil
"Name of the currently installed style.
@ -1268,62 +1533,139 @@ Don't change this directly; call `c-set-style' instead.")
Set from `c-comment-prefix-regexp' at mode initialization.")
(make-variable-buffer-local 'c-current-comment-prefix)
(defvar c-buffer-is-cc-mode nil
"Non-nil for all buffers with a major mode derived from CC Mode.
Otherwise, this variable is nil. I.e. this variable is non-nil for
`c-mode', `c++-mode', `objc-mode', `java-mode', `idl-mode',
`pike-mode', and any other non-CC Mode mode that calls
`c-initialize-cc-mode' (e.g. `awk-mode'). The value is the mode
symbol itself (i.e. `c-mode' etc) of the original CC Mode mode, or
just t if it's not known.")
(make-variable-buffer-local 'c-buffer-is-cc-mode)
;; Have to make `c-buffer-is-cc-mode' permanently local so that it
;; survives the initialization of the derived mode.
(put 'c-buffer-is-cc-mode 'permanent-local t)
;; Figure out what features this Emacs has
;;;###autoload
(cc-bytecomp-defvar open-paren-in-column-0-is-defun-start)
(defconst c-emacs-features
(let ((infodock-p (boundp 'infodock-version))
(comments
;; 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")))
(if (= (logand (lsh entry -16) 255) 255)
'8-bit
'1-bit))))
(if infodock-p
(list comments 'infodock)
(list comments)))
"A list of features extant in the Emacs you are using.
(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. Here's the current
supported list, along with the values for this variable:
features supporting those needed by CC Mode. The following values
might be present:
XEmacs 19, 20, 21: (8-bit)
Emacs 19, 20: (1-bit)
'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).
Infodock (based on XEmacs) has an additional symbol on this list:
`infodock'.")
'8-bit and '1-bit are mutually exclusive.")
(cc-provide 'cc-vars)