]> git.eshelyaron.com Git - emacs.git/commitdiff
Amend to indent and fontify macros "which include their own semicolon"
authorAlan Mackenzie <acm@muc.de>
Thu, 27 Oct 2011 20:34:23 +0000 (20:34 +0000)
committerAlan Mackenzie <acm@muc.de>
Thu, 27 Oct 2011 20:34:23 +0000 (20:34 +0000)
correctly, using the "virtual semicolon" mechanism.

cc-defs.el: Update "virtual semicolon" comments.

cc-engine.el (c-crosses-statement-barrier-p): Recoded to scan one line at
at time rather than having \n and \r explicitly in c-stmt-delim-chars
(for some modes, e.g. AWK).
(c-forward-label): Amend for virtual semicolons.
(c-at-macro-vsemi-p, c-macro-vsemi-status-unknown-p): New functions

cc-fonts.el (c-font-lock-declarations): Take account of the new C macros.

cc-langs.el (c-at-vsemi-p-fn, c-vsemi-status-unknown-p-fn): move to
earlier in the file.
(c-opt-cpp-symbol, c-line-comment-start-regexp): New language variables.
(c-opt-cpp-macro-define): Make into a full language variable.
(c-stmt-delim-chars, c-stmt-delim-chars-with-comma): Special value for
AWK Mode (including \n, \r) removed, no longer needed.

cc-mode.el (c-mode, c++-mode, objc-mode): Invoke
c-make-macro-with-semi-re.

cc-vars.el (c-macro-with-semi-re, c-macro-names-with-semicolon): New
variables.
(c-make-macro-with-semi-re): New function

cc-mode.texi (Indentation Commands): Mention "macros with semicolons".
(Other Special Indentations): Add an xref to "Macros with ;".
(Customizing Macros): Add stuff about syntax in macros.  Add an xref to
"Macros with ;".
(Macros with ;): New page.

doc/misc/cc-mode.texi
lisp/progmodes/cc-defs.el
lisp/progmodes/cc-engine.el
lisp/progmodes/cc-fonts.el
lisp/progmodes/cc-langs.el
lisp/progmodes/cc-mode.el
lisp/progmodes/cc-vars.el

index a9339162666d38ece461a6f9a1c9c94cd624c031..4cc7f351c2e87e32a53997b10f440be1f7c703c7 100644 (file)
@@ -341,6 +341,11 @@ Line-Up Functions
 * Comment Line-Up::
 * Misc Line-Up::
 
+Customizing Macros
+
+* Macro Backslashes::           
+* Macros with ;::               
+
 @end detailmenu
 @end menu
 
@@ -655,6 +660,10 @@ expression, to some statements, or perhaps to whole functions, the
 syntactic recognition can be wrong.  @ccmode{} manages to figure it
 out correctly most of the time, though.
 
+Some macros, when invoked, ''have their own semicolon''.  To get the
+next line indented correctly, rather than as a continuation line,
+@xref{Macros with ;}.
+
 Reindenting large sections of code can take a long time.  When
 @ccmode{} reindents a region of code, it is essentially equivalent to
 hitting @key{TAB} on every line of the region.
@@ -6550,6 +6559,9 @@ custom line-up function associated with it.
 @section Other Special Indentations
 @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
+To configure macros which you invoke without a terminating @samp{;},
+see @xref{Macros with ;}.
+
 Here are the remaining odds and ends regarding indentation:
 
 @defopt c-label-minimum-indentation
@@ -6601,6 +6613,13 @@ functions to this hook, not remove them.  @xref{Style Variables}.
 @cindex preprocessor directives
 @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
+Preprocessor macros in C, C++, and Objective C (introduced by
+@code{#define}) have a syntax different from the main language---for
+example, a macro declaration is not terminated by a semicolon, and if
+it is more than a line long, line breaks in it must be escaped with
+backslashes.  @ccmode{} has some commands to manipulate these, see
+@ref{Macro Backslashes}.
+
 Normally, the lines in a multi-line macro are indented relative to
 each other as though they were code.  You can suppress this behavior
 by setting the following user option:
@@ -6612,6 +6631,28 @@ is @code{nil}, all lines inside macro definitions are analyzed as
 @code{cpp-macro-cont}.
 @end defopt
 
+Because a macro can expand into anything at all, near where one is
+invoked @ccmode{} can only indent and fontify code heuristically.
+Sometimes it gets it wrong.  Usually you should try to design your
+macros so that they ''look like ordinary code'' when you invoke them.
+However, one situation is so common that @ccmode{} handles it
+specially: that is when certain macros needn't (or mustn't) be
+followed by a @samp{;}.  You need to configure @ccmode{} to handle
+these macros properly, see @ref{Macros with ;}.
+
+@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+@menu
+* Macro Backslashes::           
+* Macros with ;::               
+@end menu
+
+@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+@node     Macro Backslashes, Macros with ;, Custom Macros, Custom Macros
+@comment  node-name,  next,  previous,  up
+@section Customizing Macro Backslashes
+@cindex #define
+@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
 @ccmode{} provides some tools to help keep the line continuation
 backslashes in macros neat and tidy.  Their precise action is
 customized with these variables:
@@ -6653,6 +6694,62 @@ get aligned only when you explicitly invoke the command
 @code{c-backslash-region} (@kbd{C-c C-\}).
 @end defopt
 
+@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+@node Macros with ;,  , Macro Backslashes, Custom Macros
+@comment  node-name,  next,  previous,  up
+@section Macros with semicolons
+@cindex macros with semicolons
+@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+Macros which needn't (or mustn't) be followed by a semicolon when you
+invoke them, @dfn{macros with semicolons}, are very common.  These can
+cause @ccmode{} to parse the next line wrongly as a
+@code{statement-cont} (@pxref{Function Symbols}) and thus mis-indent
+it.
+
+You can prevent this by specifying which macros have semicolons.  It
+doesn't matter whether or not such a macro has a parameter list:
+
+@defopt c-macro-names-with-semicolon
+@vindex macro-names-with-semicolon (c-)
+This buffer-local variable specifies which macros have semicolons.
+After setting its value, you need to call
+@code{c-make-macro-with-semi-re} for it to take effect.  It should be
+set to one of these values:
+
+@table @asis
+@item nil
+There are no macros with semicolons.
+@item a list of strings
+Each string is the name of a macro with a semicolon.  Only valid
+@code{#define} names are allowed here.  For example, to set the
+default value, you could write the following into your @file{.emacs}:
+
+@example
+(setq c-macro-names-with-semicolon
+      '("Q_OBJECT" "Q_PROPERTY" "Q_DECLARE" "Q_ENUMS"))
+@end example
+
+@item a regular expression
+This matches each symbol which is a macro with a semicolon.  It must
+not match any string which isn't a valid @code{#define} name.  For
+example:
+
+@example
+(setq c-macro-names-with-semicolon
+      "\\<\\(CLEAN_UP_AND_RETURN\\|Q_[[:upper:]]+\\)\\>")
+@end example
+@end table
+@end defopt
+
+@defun c-make-macro-with-semi-re
+@findex make-macro-with-semi-re (c-)
+Call this (non-interactive) function, which sets internal variables,
+each time you change the value of
+@code{c-macro-names-with-semicolon}.  It takes no arguments, and its
+return value has no meaning.  This function is called by @ccmode{}'s
+initialization code.
+@end defun
+
 @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 @node    Odds and Ends, Sample .emacs File, Custom Macros, Top
 @comment node-name, next, previous, up
index e5b4d7e35a4af00406ffafd123b5c553ffc8bae6..93da6e3e2be725ebaff0c83600bf66168e7bf182 100644 (file)
@@ -744,19 +744,20 @@ be after it."
 ;; V i r t u a l   S e m i c o l o n s
 ;;
 ;; In most CC Mode languages, statements are terminated explicitly by
-;; semicolons or closing braces.  In some of the CC modes (currently only AWK
-;; Mode (April 2004)), statements are (or can be) terminated by EOLs.  Such a
-;; statement is said to be terminated by a "virtual semicolon" (VS).  A
-;; statement terminated by an actual semicolon or brace is never considered to
-;; have a VS.
+;; semicolons or closing braces.  In some of the CC modes (currently AWK Mode
+;; and certain user-specified #define macros in C, C++, etc. (November 2008)),
+;; statements are (or can be) terminated by EOLs.  Such a statement is said to
+;; be terminated by a "virtual semicolon" (VS).  A statement terminated by an
+;; actual semicolon or brace is never considered to have a VS.
 ;;
 ;; The indentation engine (or whatever) tests for a VS at a specific position
 ;; by invoking the macro `c-at-vsemi-p', which in its turn calls the mode
 ;; specific function (if any) which is the value of the language variable
-;; `c-at-vsemi-p-fn'.  The actual details of what constitutes a VS in a
-;; language are thus encapsulated in code specific to that language
-;; (e.g. cc-awk.el).  `c-at-vsemi-p' returns non-nil if point (or the optional
-;; parameter POS) is at a VS, nil otherwise.
+;; `c-at-vsemi-p-fn'.  This function should only use "low-level" features of
+;; CC Mode, i.e. features which won't trigger infinite recursion.  ;-) The
+;; actual details of what constitutes a VS in a language are thus encapsulated
+;; in code specific to that language (e.g. cc-awk.el).  `c-at-vsemi-p' returns
+;; non-nil if point (or the optional parameter POS) is at a VS, nil otherwise.
 ;;
 ;; The language specific function might well do extensive analysis of the
 ;; source text, and may use a cacheing scheme to speed up repeated calls.
index b2c548847c34f02f1955a5cc8f023b2ca04c0c0c..c7e02a1bbd531657e37b18e7269353351d477703 100644 (file)
@@ -1149,42 +1149,65 @@ the line.  If this virtual semicolon is _at_ from, the function recognizes it.
 
 Note that this function might do hidden buffer changes.  See the
 comment at the start of cc-engine.el for more info."
-  (let ((skip-chars c-stmt-delim-chars)
-       lit-range)
-    (save-excursion
-      (catch 'done
-       (goto-char from)
-       (while (progn (skip-chars-forward skip-chars to)
-                     (< (point) to))
-         (cond
-          ((setq lit-range (c-literal-limits from)) ; Have we landed in a string/comment?
-           (goto-char (cdr lit-range)))
-          ((eq (char-after) ?:)
-           (forward-char)
-           (if (and (eq (char-after) ?:)
-                    (< (point) to))
-               ;; Ignore scope operators.
-               (forward-char)
-             (setq c-maybe-labelp (1- (point)))))
-          ((eq (char-after) ??)
-           ;; A question mark.  Can't be a label, so stop
-           ;; looking for more : and ?.
-           (setq c-maybe-labelp nil
-                 skip-chars (substring c-stmt-delim-chars 0 -2)))
-          ((memq (char-after) '(?# ?\n ?\r)) ; A virtual semicolon?
-           (if (and (eq (char-before) ?\\) (memq (char-after) '(?\n ?\r)))
-               (backward-char))
-           (skip-chars-backward " \t" from)
-           (if (c-at-vsemi-p)
-               (throw 'done (point))
-             (forward-line)))
-          (t (throw 'done (point)))))
-       ;; In trailing space after an as yet undetected virtual semicolon?
-       (c-backward-syntactic-ws from)
-       (if (and (< (point) to)
-                (c-at-vsemi-p))
-           (point)
-         nil)))))
+  (let* ((skip-chars
+         ;; If the current language has CPP macros, insert # into skip-chars.
+         (if c-opt-cpp-symbol
+             (concat (substring c-stmt-delim-chars 0 1) ; "^"
+                     c-opt-cpp-symbol                   ; usually "#"
+                     (substring c-stmt-delim-chars 1))  ; e.g. ";{}?:"
+           c-stmt-delim-chars))
+        (non-skip-list
+         (append (substring skip-chars 1) nil)) ; e.g. (?# ?\; ?{ ?} ?? ?:)
+        lit-range vsemi-pos)
+    (save-restriction
+      (widen)
+      (save-excursion
+       (catch 'done
+         (goto-char from)
+         (while (progn (skip-chars-forward
+                        skip-chars
+                        (min to (c-point 'bonl)))
+                       (< (point) to))
+           (cond
+            ;; Virtual semicolon?
+            ((and (bolp)
+                  (save-excursion
+                    (progn
+                      (if (setq lit-range (c-literal-limits from)) ; Have we landed in a string/comment?
+                          (goto-char (car lit-range)))
+                      (c-backward-syntactic-ws) ; ? put a limit here, maybe?
+                      (setq vsemi-pos (point))
+                      (c-at-vsemi-p))))
+             (throw 'done vsemi-pos))
+            ;; In a string/comment?
+            ((setq lit-range (c-literal-limits))
+             (goto-char (cdr lit-range)))
+            ((eq (char-after) ?:)
+             (forward-char)
+             (if (and (eq (char-after) ?:)
+                      (< (point) to))
+                 ;; Ignore scope operators.
+                 (forward-char)
+               (setq c-maybe-labelp (1- (point)))))
+            ((eq (char-after) ??)
+             ;; A question mark.  Can't be a label, so stop
+             ;; looking for more : and ?.
+             (setq c-maybe-labelp nil
+                   skip-chars (substring c-stmt-delim-chars 0 -2)))
+            ;; At a CPP construct?
+            ((and c-opt-cpp-symbol (looking-at c-opt-cpp-symbol)
+                  (save-excursion
+                    (forward-line 0)
+                    (looking-at c-opt-cpp-prefix)))
+             (c-end-of-macro))
+            ((memq (char-after) non-skip-list)
+             (throw 'done (point)))))
+         ;; In trailing space after an as yet undetected virtual semicolon?
+         (c-backward-syntactic-ws from)
+         (if (and (< (point) to)
+                  (c-at-vsemi-p))
+             (point)
+           nil))))))
 
 (defun c-at-statement-start-p ()
   "Return non-nil if the point is at the first token in a statement
@@ -7158,12 +7181,14 @@ comment at the start of cc-engine.el for more info."
           ;; Check that we're not after a token that can't precede a label.
           (or
            ;; Trivially succeeds when there's no preceding token.
+           ;; Succeeds when we're at a virtual semicolon.
            (if preceding-token-end
                (<= preceding-token-end (point-min))
              (save-excursion
                (c-backward-syntactic-ws)
                (setq preceding-token-end (point))
-               (bobp)))
+               (or (bobp)
+                   (c-at-vsemi-p))))
 
            ;; Check if we're after a label, if we're after a closing
            ;; paren that belong to statement, and with
@@ -8372,6 +8397,57 @@ comment at the start of cc-engine.el for more info."
                                                    paren-state)
                                   containing-sexp)))))
 
+(defun c-at-macro-vsemi-p (&optional pos)
+  ;; Is there a "virtual semicolon" at POS or point?
+  ;; (See cc-defs.el for full details of "virtual semicolons".)
+  ;;
+  ;; This is true when point is at the last non syntactic WS position on the
+  ;; line, there is a macro call last on the line, and this particular macro's
+  ;; name is defined by the regexp `c-vs-macro-regexp' as not needing a
+  ;; semicolon.
+  (save-excursion
+    (save-restriction
+      (widen)
+      (if pos
+         (goto-char pos)
+       (setq pos (point)))
+      (and
+       c-macro-with-semi-re
+       (not (c-in-literal))
+       (eq (skip-chars-backward " \t") 0)
+
+       ;; Check we've got nothing after this except comments and empty lines
+       ;; joined by escaped EOLs.
+       (skip-chars-forward " \t")      ; always returns non-nil.
+       (progn
+        (while                       ; go over 1 block comment per iteration.
+            (and
+             (looking-at "\\(\\\\[\n\r][ \t]*\\)*")
+             (goto-char (match-end 0))
+             (cond
+              ((looking-at c-block-comment-start-regexp)
+               (and (forward-comment 1)
+                    (skip-chars-forward " \t"))) ; always returns non-nil
+              ((looking-at c-line-comment-start-regexp)
+               (end-of-line)
+               nil)
+              (t nil))))
+        (eolp))
+            
+       (goto-char pos)
+       (progn (c-backward-syntactic-ws)
+             (eq (point) pos))
+
+       ;; Check for one of the listed macros being before point.
+       (or (not (eq (char-before) ?\)))
+          (when (c-go-list-backward)
+            (c-backward-syntactic-ws)
+            t))
+       (c-simple-skip-symbol-backward)
+       (looking-at c-macro-with-semi-re)))))
+
+(defun c-macro-vsemi-status-unknown-p () t) ; See cc-defs.el.
+
 \f
 ;; `c-guess-basic-syntax' and the functions that precedes it below
 ;; implements the main decision tree for determining the syntactic
index fd817e3b4f48e59e4966d6e67b0219c1035127be..9a83d5196db8254944756a95071a65d3695404c0 100644 (file)
@@ -1277,9 +1277,11 @@ casts and declarations are fontified.  Used on level 2 and higher."
         (when
          ;; The result of the form below is true when we don't recognize a
          ;; declaration or cast.
-         (if (and (eq (get-text-property (point) 'face)
-                      'font-lock-keyword-face)
-                  (looking-at c-not-decl-init-keywords))
+         (if (or (and (eq (get-text-property (point) 'face)
+                          'font-lock-keyword-face)
+                      (looking-at c-not-decl-init-keywords))
+                 (and c-macro-with-semi-re
+                      (looking-at c-macro-with-semi-re))) ; 2008-11-04
              ;; Don't do anything more if we're looking at a keyword that
              ;; can't start a declaration.
              t
index 279c5e46c46e05a08f2b2a4353b8e2f2648e4f5f..09f8b318378fcffe358a51fb88fcc01f36e44677 100644 (file)
@@ -508,6 +508,31 @@ parameters \(point-min), \(point-max) and <buffer size>."
 (c-lang-defvar c-before-font-lock-function
               (c-lang-const c-before-font-lock-function))
 
+\f
+;;; Syntactic analysis ("virtual semicolons") for line-oriented languages (AWK).
+(c-lang-defconst c-at-vsemi-p-fn
+  "Contains a function \"Is there a virtual semicolon at POS or point?\".
+Such a function takes one optional parameter, a buffer position (defaults to
+point), and returns nil or t.  This variable contains nil for languages which
+don't have EOL terminated statements. "
+  t nil
+  (c c++ objc) 'c-at-macro-vsemi-p
+  awk 'c-awk-at-vsemi-p)
+(c-lang-defvar c-at-vsemi-p-fn (c-lang-const c-at-vsemi-p-fn))
+
+(c-lang-defconst c-vsemi-status-unknown-p-fn
+  "Contains a function \"are we unsure whether there is a virtual semicolon on this line?\".
+The (admittedly kludgey) purpose of such a function is to prevent an infinite
+recursion in c-beginning-of-statement-1 when point starts at a `while' token.
+The function MUST NOT UNDER ANY CIRCUMSTANCES call c-beginning-of-statement-1,
+even indirectly.  This variable contains nil for languages which don't have
+EOL terminated statements."
+  t nil
+  (c c++ objc) 'c-macro-vsemi-status-unknown-p
+  awk 'c-awk-vsemi-status-unknown-p)
+(c-lang-defvar c-vsemi-status-unknown-p-fn
+  (c-lang-const c-vsemi-status-unknown-p-fn))
+
 \f
 ;;; Lexer-level syntax (identifiers, tokens etc).
 
@@ -737,6 +762,12 @@ literal are multiline."
 (c-lang-defvar c-multiline-string-start-char
   (c-lang-const c-multiline-string-start-char))
 
+(c-lang-defconst c-opt-cpp-symbol
+  "The symbol which starts preprocessor constructs when in the margin."
+  t "#"
+  (java awk) nil)
+(c-lang-defvar c-opt-cpp-symbol (c-lang-const c-opt-cpp-symbol))
+
 (c-lang-defconst c-opt-cpp-prefix
   "Regexp matching the prefix of a cpp directive in the languages that
 normally use that macro preprocessor.  Tested at bol or at boi.
@@ -785,6 +816,8 @@ file name in angle brackets or quotes."
 definition, or nil if the language doesn't have any."
   t (if (c-lang-const c-opt-cpp-prefix)
        "define"))
+(c-lang-defvar c-opt-cpp-macro-define
+  (c-lang-const c-opt-cpp-macro-define))
 
 (c-lang-defconst c-opt-cpp-macro-define-start
   ;; Regexp matching everything up to the macro body of a cpp define, or the
@@ -1171,14 +1204,12 @@ operators."
   ;; optimize `c-crosses-statement-barrier-p' somewhat, it's assumed to
   ;; begin with "^" to negate the set.  If ? : operators should be
   ;; detected then the string must end with "?:".
-  t    "^;{}?:"
-  awk  "^;{}#\n\r?:") ; The newline chars gets special treatment.
+  t "^;{}?:")
 (c-lang-defvar c-stmt-delim-chars (c-lang-const c-stmt-delim-chars))
 
 (c-lang-defconst c-stmt-delim-chars-with-comma
   ;; Variant of `c-stmt-delim-chars' that additionally contains ','.
-  t    "^;,{}?:"
-  awk  "^;,{}\n\r?:") ; The newline chars gets special treatment.
+  t    "^;,{}?:")
 (c-lang-defvar c-stmt-delim-chars-with-comma
   (c-lang-const c-stmt-delim-chars-with-comma))
 
@@ -1238,7 +1269,6 @@ properly."
        re)))
 (c-lang-defvar c-comment-start-regexp (c-lang-const c-comment-start-regexp))
 
-;;;; Added by ACM, 2003/9/18.
 (c-lang-defconst c-block-comment-start-regexp
   ;; Regexp which matches the start of a block comment (if such exists in the
   ;; language)
@@ -1248,6 +1278,15 @@ properly."
 (c-lang-defvar c-block-comment-start-regexp
   (c-lang-const c-block-comment-start-regexp))
 
+(c-lang-defconst c-line-comment-start-regexp
+  ;; Regexp which matches the start of a line comment (if such exists in the
+  ;; language; it does in all 7 CC Mode languages).
+  t (if (c-lang-const c-line-comment-starter)
+       (regexp-quote (c-lang-const c-line-comment-starter))
+      "\\<\\>"))
+(c-lang-defvar c-line-comment-start-regexp
+              (c-lang-const c-line-comment-start-regexp))
+
 (c-lang-defconst c-literal-start-regexp
   ;; Regexp to match the start of comments and string literals.
   t (concat (c-lang-const c-comment-start-regexp)
@@ -1474,29 +1513,6 @@ properly."
            "\\)"))
 (c-lang-defvar c-syntactic-eol (c-lang-const c-syntactic-eol))
 
-\f
-;;; Syntactic analysis ("virtual semicolons") for line-oriented languages (AWK).
-(c-lang-defconst c-at-vsemi-p-fn
-  "Contains a function \"Is there a virtual semicolon at POS or point?\".
-Such a function takes one optional parameter, a buffer position (defaults to
-point), and returns nil or t.  This variable contains nil for languages which
-don't have EOL terminated statements. "
-  t nil
-  awk 'c-awk-at-vsemi-p)
-(c-lang-defvar c-at-vsemi-p-fn (c-lang-const c-at-vsemi-p-fn))
-
-(c-lang-defconst c-vsemi-status-unknown-p-fn
-  "Contains a function \"are we unsure whether there is a virtual semicolon on this line?\".
-The (admittedly kludgey) purpose of such a function is to prevent an infinite
-recursion in c-beginning-of-statement-1 when point starts at a `while' token.
-The function MUST NOT UNDER ANY CIRCUMSTANCES call c-beginning-of-statement-1,
-even indirectly.  This variable contains nil for languages which don't have
-EOL terminated statements."
-  t nil
-  awk 'c-awk-vsemi-status-unknown-p)
-(c-lang-defvar c-vsemi-status-unknown-p-fn
-  (c-lang-const c-vsemi-status-unknown-p-fn))
-
 \f
 ;;; Defun functions
 
index eec63b4fa3b91fd5d8ed2c3023d6c71259155a12..a6bf241f0dbae6edfab93cc49a0d126ef2988583 100644 (file)
@@ -1187,6 +1187,7 @@ Key bindings:
        abbrev-mode t)
   (use-local-map c-mode-map)
   (c-init-language-vars-for 'c-mode)
+  (c-make-macro-with-semi-re) ; matches macro names whose expansion ends with ;
   (c-common-init 'c-mode)
   (easy-menu-add c-c-menu)
   (cc-imenu-init cc-imenu-c-generic-expression)
@@ -1246,6 +1247,7 @@ Key bindings:
        abbrev-mode t)
   (use-local-map c++-mode-map)
   (c-init-language-vars-for 'c++-mode)
+  (c-make-macro-with-semi-re) ; matches macro names whose expansion ends with ;
   (c-common-init 'c++-mode)
   (easy-menu-add c-c++-menu)
   (cc-imenu-init cc-imenu-c++-generic-expression)
@@ -1303,6 +1305,7 @@ Key bindings:
        abbrev-mode t)
   (use-local-map objc-mode-map)
   (c-init-language-vars-for 'objc-mode)
+  (c-make-macro-with-semi-re) ; matches macro names whose expansion ends with ;
   (c-common-init 'objc-mode)
   (easy-menu-add c-objc-menu)
   (cc-imenu-init nil 'cc-imenu-objc-function)
index 58dc1737c5a8b14514eb747030c2f32d7f4417db..055d5f4c57c3d15a6b256cad9a165fd4165259ed 100644 (file)
@@ -1608,6 +1608,54 @@ names)."))
 
 \f
 ;; Non-customizable variables, still part of the interface to CC Mode
+(defvar c-macro-with-semi-re nil
+  ;; Regular expression which matches a (#define'd) symbol whose expansion
+  ;; ends with a semicolon.
+  ;; 
+  ;; This variable should be set by `c-make-macros-with-semi-re' rather than
+  ;; directly.
+)
+(make-variable-buffer-local 'c-macro-with-semi-re)
+
+(defun c-make-macro-with-semi-re ()
+  ;; Convert `c-macro-names-with-semicolon' into the regexp
+  ;; `c-macro-with-semi-re' (or just copy it if it's already a re).
+  (setq c-macro-with-semi-re
+       (and
+        c-opt-cpp-macro-define
+        (cond
+         ((stringp c-macro-names-with-semicolon)
+          (copy-sequence c-macro-names-with-semicolon))
+         ((consp c-macro-names-with-semicolon)
+          (concat
+           "\\<"
+           (regexp-opt c-macro-names-with-semicolon)
+           "\\>"))   ; N.B. the PAREN param of regexp-opt isn't supported by
+                     ; all XEmacsen.
+         ((null c-macro-names-with-semicolon)
+          nil)
+         (t (error "c-make-macro-with-semi-re: invalid \
+c-macro-names-with-semicolon: %s"
+                   c-macro-names-with-semicolon))))))
+    
+(defvar c-macro-names-with-semicolon
+  '("Q_OBJECT" "Q_PROPERTY" "Q_DECLARE" "Q_ENUMS")
+  "List of #defined symbols whose expansion ends with a semicolon.
+Alternatively it can be a string, a regular expression which
+matches all such symbols.
+
+The \"symbols\" must be syntactically valid identifiers in the
+target language \(C, C++, Objective C), or \(as the case may be)
+the regular expression must match only valid identifiers.
+
+If you change this variable's value, call the function
+`c-make-macros-with-semi-re' to set the necessary internal
+variables.
+
+Note that currently \(2008-11-04) this variable is a prototype,
+and is likely to disappear or change its form soon.")
+(make-variable-buffer-local 'c-macro-names-with-semicolon)
+
 (defvar c-file-style nil
   "Variable interface for setting style via File Local Variables.
 In a file's Local Variable section, you can set this variable to a