Merge from emacs-23
[bpt/emacs.git] / lisp / progmodes / cc-defs.el
index 39036b7..f0d9bee 100644 (file)
@@ -1,7 +1,7 @@
 ;;; cc-defs.el --- compile time definitions for CC Mode
 
 ;; Copyright (C) 1985, 1987, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-;;   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+;;   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
 ;;   Free Software Foundation, Inc.
 
 ;; Authors:    2003- Alan Mackenzie
@@ -12,8 +12,8 @@
 ;;             1985 Richard M. Stallman
 ;; Maintainer: bug-cc-mode@gnu.org
 ;; Created:    22-Apr-1997 (split from cc-mode.el)
-;; Version:    See cc-mode.el
-;; Keywords:   c languages oop
+;; Keywords:   c languages
+;; Package:    cc-mode
 
 ;; This file is part of GNU Emacs.
 
@@ -1029,6 +1029,44 @@ MODE is either a mode symbol or a list of mode symbols."
     ;; Emacs.
     `(remove-text-properties ,from ,to '(,property nil))))
 
+(defmacro c-search-forward-char-property (property value &optional limit)
+  "Search forward for a text-property PROPERTY having value VALUE.
+LIMIT bounds the search.  The comparison is done with `equal'.
+
+Leave point just after the character, and set the match data on
+this character, and return point.  If VALUE isn't found, Return
+nil; point is then left undefined."
+  `(let ((place (point)))
+     (while
+        (and
+         (< place ,(or limit '(point-max)))
+         (not (equal (get-text-property place ,property) ,value)))
+       (setq place (next-single-property-change
+                   place ,property nil ,(or limit '(point-max)))))
+     (when (< place ,(or limit '(point-max)))
+       (goto-char place)
+       (search-forward-regexp ".")     ; to set the match-data.
+       (point))))
+
+(defmacro c-search-backward-char-property (property value &optional limit)
+  "Search backward for a text-property PROPERTY having value VALUE.
+LIMIT bounds the search.  The comparison is done with `equal'.
+
+Leave point just before the character, set the match data on this
+character, and return point.  If VALUE isn't found, Return nil;
+point is then left undefined."
+  `(let ((place (point)))
+     (while
+        (and
+         (> place ,(or limit '(point-min)))
+         (not (equal (get-text-property (1- place) ,property) ,value)))
+       (setq place (previous-single-property-change
+                   place ,property nil ,(or limit '(point-min)))))
+     (when (> place ,(or limit '(point-max)))
+       (goto-char place)
+       (search-backward-regexp ".")    ; to set the match-data.
+       (point))))
+
 (defun c-clear-char-property-with-value-function (from to property value)
   "Remove all text-properties PROPERTY from the region (FROM, TO)
 which have the value VALUE, as tested by `equal'.  These
@@ -1044,7 +1082,7 @@ been put there by c-put-char-property.  POINT remains unchanged."
            (setq place (next-single-property-change place property nil to)))
          (< place to))
       (setq end-place (next-single-property-change place property nil to))
-      (put-text-property place end-place property nil)
+      (remove-text-properties place end-place (cons property nil))
       ;; Do we have to do anything with stickiness here?
       (setq place end-place))))
 
@@ -1145,23 +1183,117 @@ been put there by c-put-char-property.  POINT remains unchanged."
        (goto-char (point-max)))))
 
 (defconst c-<-as-paren-syntax '(4 . ?>))
+(put 'c-<-as-paren-syntax 'syntax-table c-<-as-paren-syntax)
 
 (defsubst c-mark-<-as-paren (pos)
-  ;; Mark the "<" character at POS as an sexp list opener using the
-  ;; syntax-table property.
+  ;; Mark the "<" character at POS as a template opener using the
+  ;; `syntax-table' property via the `category' property.
   ;;
-  ;; This function does a hidden buffer change.
-  (c-put-char-property pos 'syntax-table c-<-as-paren-syntax))
+  ;; This function does a hidden buffer change.  Note that we use
+  ;; indirection through the `category' text property.  This allows us to
+  ;; toggle the property in all template brackets simultaneously and
+  ;; cheaply.  We use this, for instance, in `c-parse-state'.
+  (c-put-char-property pos 'category 'c-<-as-paren-syntax))
 
 (defconst c->-as-paren-syntax '(5 . ?<))
+(put 'c->-as-paren-syntax 'syntax-table c->-as-paren-syntax)
 
 (defsubst c-mark->-as-paren (pos)
   ;; Mark the ">" character at POS as an sexp list closer using the
   ;; syntax-table property.
   ;;
-  ;; This function does a hidden buffer change.
-  (c-put-char-property pos 'syntax-table c->-as-paren-syntax))
-
+  ;; This function does a hidden buffer change.  Note that we use
+  ;; indirection through the `category' text property.  This allows us to
+  ;; toggle the property in all template brackets simultaneously and
+  ;; cheaply.  We use this, for instance, in `c-parse-state'.
+  (c-put-char-property pos 'category 'c->-as-paren-syntax))
+
+(defsubst c-unmark-<->-as-paren (pos)
+  ;; Unmark the "<" or "<" character at POS as an sexp list opener using
+  ;; the syntax-table property indirectly through the `category' text
+  ;; property.
+  ;;
+  ;; This function does a hidden buffer change.  Note that we use
+  ;; indirection through the `category' text property.  This allows us to
+  ;; toggle the property in all template brackets simultaneously and
+  ;; cheaply.  We use this, for instance, in `c-parse-state'.
+  (c-clear-char-property pos 'category))
+
+(defsubst c-suppress-<->-as-parens ()
+  ;; Suppress the syntactic effect of all marked < and > as parens.  Note
+  ;; that this effect is NOT buffer local.  You should probably not use
+  ;; this directly, but only through the macro
+  ;; `c-with-<->-as-parens-suppressed'
+  (put 'c-<-as-paren-syntax 'syntax-table nil)
+  (put 'c->-as-paren-syntax 'syntax-table nil))
+
+(defsubst c-restore-<->-as-parens ()
+  ;; Restore the syntactic effect of all marked <s and >s as parens.  This
+  ;; has no effect on unmarked <s and >s
+  (put 'c-<-as-paren-syntax 'syntax-table c-<-as-paren-syntax)
+  (put 'c->-as-paren-syntax 'syntax-table c->-as-paren-syntax))
+
+(defmacro c-with-<->-as-parens-suppressed (&rest forms)
+  ;; Like progn, except that the paren property is suppressed on all
+  ;; template brackets whilst they are running.  This macro does a hidden
+  ;; buffer change.
+  `(unwind-protect
+       (progn
+        (c-suppress-<->-as-parens)
+        ,@forms)
+     (c-restore-<->-as-parens)))
+
+;;;;;;;;;;;;;;;
+
+(defconst c-cpp-delimiter '(14)) ; generic comment syntax
+;; This is the value of the `category' text property placed on every #
+;; which introduces a CPP construct and every EOL (or EOB, or character
+;; preceding //, etc.) which terminates it.  We can instantly "comment
+;; out" all CPP constructs by giving `c-cpp-delimiter' a syntax-table
+;; propery '(14) (generic comment delimiter).
+(defmacro c-set-cpp-delimiters (beg end)
+  ;; This macro does a hidden buffer change.
+  `(progn
+     (c-put-char-property ,beg 'category 'c-cpp-delimiter)
+     (if (< ,end (point-max))
+        (c-put-char-property ,end 'category 'c-cpp-delimiter))))
+(defmacro c-clear-cpp-delimiters (beg end)
+  ;; This macro does a hidden buffer change.
+  `(progn
+     (c-clear-char-property ,beg 'category)
+     (if (< ,end (point-max))
+        (c-clear-char-property ,end 'category))))
+
+(defsubst c-comment-out-cpps ()
+  ;; Render all preprocessor constructs syntactically commented out.
+  (put 'c-cpp-delimiter 'syntax-table c-cpp-delimiter))
+(defsubst c-uncomment-out-cpps ()
+  ;; Restore the syntactic visibility of preprocessor constructs.
+  (put 'c-cpp-delimiter 'syntax-table nil))
+
+(defmacro c-with-cpps-commented-out (&rest forms)
+  ;; Execute FORMS... whilst the syntactic effect of all characters in
+  ;; all CPP regions is suppressed.  In particular, this is to suppress
+  ;; the syntactic significance of parens/braces/brackets to functions
+  ;; such as `scan-lists' and `parse-partial-sexp'.
+  `(unwind-protect
+       (c-save-buffer-state ()
+          (c-comment-out-cpps)
+          ,@forms)
+     (c-save-buffer-state ()
+       (c-uncomment-out-cpps))))
+
+(defmacro c-with-all-but-one-cpps-commented-out (beg end &rest forms)
+  ;; Execute FORMS... whilst the syntactic effect of all characters in
+  ;; every CPP region APART FROM THE ONE BETWEEN BEG and END is
+  ;; suppressed.
+  `(unwind-protect
+       (c-save-buffer-state ()
+        (c-clear-cpp-delimiters ,beg ,end)
+        ,`(c-with-cpps-commented-out ,@forms))
+     (c-save-buffer-state ()
+       (c-set-cpp-delimiters ,beg ,end))))
+\f
 (defsubst c-intersect-lists (list alist)
   ;; return the element of ALIST that matches the first element found
   ;; in LIST.  Uses assq.