]> code.delx.au - gnu-emacs/blobdiff - lisp/progmodes/cc-engine.el
Merge multi-tty branch
[gnu-emacs] / lisp / progmodes / cc-engine.el
index f69382c9d70a824c878896d81d7a08247e6af24a..d1a27d567fd219e4347127720cbee17f03228e5a 100644 (file)
@@ -18,7 +18,7 @@
 
 ;; 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)
+;; the Free Software Foundation; either version 3, or (at your option)
 ;; any later version.
 
 ;; GNU Emacs is distributed in the hope that it will be useful,
@@ -1912,6 +1912,25 @@ comment at the start of cc-engine.el for more info."
       )))
 
 \f
+;; Other whitespace tools
+(defun c-partial-ws-p (beg end)
+  ;; Is the region (beg end) WS, and is there WS (or BOB/EOB) next to the
+  ;; region?  This is a "heuristic" function.  .....
+  ;; 
+  ;; The motivation for the second bit is to check whether removing this
+  ;; region would coalesce two symbols.
+  ;;
+  ;; FIXME!!!  This function doesn't check virtual semicolons in any way.  Be
+  ;; careful about using this function for, e.g. AWK.  (2007/3/7)
+  (save-excursion
+    (let ((end+1 (min (1+ end) (point-max))))
+      (or (progn (goto-char (max (point-min) (1- beg)))
+                (c-skip-ws-forward end)
+                (eq (point) end))
+         (progn (goto-char beg)
+                (c-skip-ws-forward end+1)
+                (eq (point) end+1))))))
+\f
 ;; A system for finding noteworthy parens before the point.
 
 (defvar c-state-cache nil)
@@ -2491,24 +2510,25 @@ comment at the start of cc-engine.el for more info."
   ;; Move to the beginning of the current token.  Do not move if not
   ;; in the middle of one.  BACK-LIMIT may be used to bound the
   ;; backward search; if given it's assumed to be at the boundary
-  ;; between two tokens.
+  ;; between two tokens.  Return non-nil if the point is move, nil
+  ;; otherwise.
   ;;
   ;; This function might do hidden buffer changes.
-  (if (looking-at "\\w\\|\\s_")
-      (skip-syntax-backward "w_" back-limit)
     (let ((start (point)))
-      (when (< (skip-syntax-backward ".()" back-limit) 0)
-       (while (let ((pos (or (and (looking-at c-nonsymbol-token-regexp)
-                                  (match-end 0))
-                             ;; `c-nonsymbol-token-regexp' should always match
-                             ;; since we've skipped backward over punctuator
-                             ;; or paren syntax, but consume one char in case
-                             ;; it doesn't so that we don't leave point before
-                             ;; some earlier incorrect token.
-                             (1+ (point)))))
-                (if (<= pos start)
-                    (goto-char pos))
-                (< pos start)))))))
+      (if (looking-at "\\w\\|\\s_")
+         (skip-syntax-backward "w_" back-limit)
+       (when (< (skip-syntax-backward ".()" back-limit) 0)
+         (while (let ((pos (or (and (looking-at c-nonsymbol-token-regexp)
+                                    (match-end 0))
+                               ;; `c-nonsymbol-token-regexp' should always match
+                               ;; since we've skipped backward over punctuator
+                               ;; or paren syntax, but consume one char in case
+                               ;; it doesn't so that we don't leave point before
+                               ;; some earlier incorrect token.
+                               (1+ (point)))))
+                  (if (<= pos start)
+                      (goto-char pos))))))
+      (< (point) start)))
 
 (defun c-end-of-current-token (&optional back-limit)
   ;; Move to the end of the current token.  Do not move if not in the
@@ -3957,6 +3977,9 @@ comment at the start of cc-engine.el for more info."
 ;; file, and we only use this as a last resort in ambiguous cases (see
 ;; `c-forward-decl-or-cast-1').
 ;;
+;; Not every type need be in this cache.  However, things which have
+;; ceased to be types must be removed from it.
+;;
 ;; Template types in C++ are added here too but with the template
 ;; arglist replaced with "<>" in references or "<" for the one in the
 ;; primary type.  E.g. the type "Foo<A,B>::Bar<C>" is stored as
@@ -3990,6 +4013,10 @@ comment at the start of cc-engine.el for more info."
       (unintern (substring type 0 -1) c-found-types)
       (intern type c-found-types))))
 
+(defun c-unfind-type (name)
+  ;; Remove the "NAME" from c-found-types, if present.
+  (unintern name c-found-types))
+
 (defsubst c-check-type (from to)
   ;; Return non-nil if the given region contains a type in
   ;; `c-found-types'.
@@ -4008,6 +4035,47 @@ comment at the start of cc-engine.el for more info."
              c-found-types)
     (sort type-list 'string-lessp)))
 
+(defun c-trim-found-types (beg end old-len)
+  ;; An after change function which, in conjunction with the info in
+  ;; c-maybe-stale-found-type (set in c-before-change), removes a type
+  ;; from `c-found-types', should this type have become stale.  For
+  ;; example, this happens to "foo" when "foo \n bar();" becomes
+  ;; "foo(); \n bar();".  Such stale types, if not removed, foul up
+  ;; the fontification.
+  ;; 
+  ;; Have we, perhaps, added non-ws characters to the front/back of a found
+  ;; type?
+  (when (> end beg)
+    (save-excursion
+      (when (< end (point-max))
+       (goto-char end)
+       (if (and (c-beginning-of-current-token) ; only moves when we started in the middle
+                (progn (goto-char end)
+                       (c-end-of-current-token)))
+           (c-unfind-type (buffer-substring-no-properties
+                           end (point)))))
+      (when (> beg (point-min))
+       (goto-char beg)
+       (if (and (c-end-of-current-token) ; only moves when we started in the middle
+                (progn (goto-char beg)
+                       (c-beginning-of-current-token)))
+           (c-unfind-type (buffer-substring-no-properties
+                           (point) beg))))))
+           
+  (if c-maybe-stale-found-type ; e.g. (c-decl-id-start "foo" 97 107 " (* ooka) " "o")
+      (cond
+       ;; Changing the amount of (already existing) whitespace - don't do anything.
+       ((and (c-partial-ws-p beg end)
+            (or (= beg end)            ; removal of WS
+                (string-match "^[ \t\n\r\f\v]*$" (nth 5 c-maybe-stale-found-type)))))
+
+       ;; The syntactic relationship which defined a "found type" has been
+       ;; destroyed.
+       ((eq (car c-maybe-stale-found-type) 'c-decl-id-start)
+       (c-unfind-type (cadr c-maybe-stale-found-type)))
+;;        ((eq (car c-maybe-stale-found-type) 'c-decl-type-start)  FIXME!!!
+       )))
+
 \f
 ;; Handling of small scale constructs like types and names.
 
@@ -5047,7 +5115,7 @@ comment at the start of cc-engine.el for more info."
   ;;     Foo::Foo (int b) : Base (b) {}
   ;; car ^                ^ point
   ;;
-  ;;   The cdr of the return value is non-nil iff a
+  ;;   The cdr of the return value is non-nil if a
   ;;   `c-typedef-decl-kwds' specifier is found in the declaration,
   ;;   i.e. the declared identifier(s) are types.
   ;;
@@ -5302,7 +5370,7 @@ comment at the start of cc-engine.el for more info."
          ;; True if there's a prefix match outside the outermost
          ;; paren pair that surrounds the declarator.
          got-prefix-before-parens
-y        ;; True if there's a suffix match outside the outermost
+         ;; True if there's a suffix match outside the outermost
          ;; paren pair that surrounds the declarator.  The value is
          ;; the position of the first suffix match.
          got-suffix-after-parens
@@ -5808,19 +5876,23 @@ y         ;; True if there's a suffix match outside the outermost
 
 (defun c-forward-label (&optional assume-markup preceding-token-end limit)
   ;; Assuming that point is at the beginning of a token, check if it starts a
-  ;; label and if so move over it and return t, otherwise don't move and
-  ;; return nil.  "Label" here means "most things with a colon".
+  ;; label and if so move over it and return non-nil (t in default situations,
+  ;; specific symbols (see below) for interesting situations), otherwise don't
+  ;; move and return nil.  "Label" here means "most things with a colon".
   ;;
   ;; More precisely, a "label" is regarded as one of:
-  ;; (i) a goto target like "foo:";
-  ;; (ii) A case label - either the entire construct "case FOO:" or just the
-  ;;   bare "case", should the colon be missing;
-  ;; (iii) a keyword which needs a colon, like "default:" or "private:";
+  ;; (i) a goto target like "foo:" - returns the symbol `goto-target';
+  ;; (ii) A case label - either the entire construct "case FOO:", or just the
+  ;;   bare "case", should the colon be missing.  We return t;
+  ;; (iii) a keyword which needs a colon, like "default:" or "private:";  We
+  ;;   return t;
   ;; (iv) One of QT's "extended" C++ variants of
-  ;; "private:"/"protected:"/"public:"/"more:" looking like "public slots:".
-  ;; (v) One of the keywords matched by `c-opt-extra-label-key' (without any
+  ;;   "private:"/"protected:"/"public:"/"more:" looking like "public slots:".
+  ;;   Returns the symbol `qt-2kwds-colon'.
+  ;; (v) QT's construct "signals:".  Returns the symbol `qt-1kwd-colon'.
+  ;; (vi) One of the keywords matched by `c-opt-extra-label-key' (without any
   ;;   colon).  Currently (2006-03), this applies only to Objective C's
-  ;;   keywords "@private", "@protected", and "@public".
+  ;;   keywords "@private", "@protected", and "@public".  Returns t.
   ;;
   ;; One of the things which will NOT be recognised as a label is a bit-field
   ;; element of a struct, something like "int foo:5".
@@ -5849,8 +5921,10 @@ y          ;; True if there's a suffix match outside the outermost
   ;; This function might do hidden buffer changes.
 
   (let ((start (point))
+       label-end
        qt-symbol-idx
-       macro-start)                    ; if we're in one.
+       macro-start                     ; if we're in one.
+       label-type)
     (cond
      ;; "case" or "default" (Doesn't apply to AWK). 
      ((looking-at c-label-kwds-regexp)
@@ -5863,25 +5937,26 @@ y         ;; True if there's a suffix match outside the outermost
 
        ;; Find the label end.
        (goto-char kwd-end)
-       (if (and (c-syntactic-re-search-forward
-                 ;; Stop on chars that aren't allowed in expressions,
-                 ;; and on operator chars that would be meaningless
-                 ;; there.  FIXME: This doesn't cope with ?: operators.
-                 "[;{=,@]\\|\\(\\=\\|[^:]\\):\\([^:]\\|\\'\\)"
-                 limit t t nil 1)
-                (match-beginning 2))
-
-           (progn
-             (goto-char (match-beginning 2)) ; just after the :
-             (c-put-c-type-property (1- (point)) 'c-decl-end)
-             t)
-
-         ;; It's an unfinished label.  We consider the keyword enough
-         ;; to recognize it as a label, so that it gets fontified.
-         ;; Leave the point at the end of it, but don't put any
-         ;; `c-decl-end' marker.
-         (goto-char kwd-end)
-         t)))
+       (setq label-type
+             (if (and (c-syntactic-re-search-forward
+                       ;; Stop on chars that aren't allowed in expressions,
+                       ;; and on operator chars that would be meaningless
+                       ;; there.  FIXME: This doesn't cope with ?: operators.
+                       "[;{=,@]\\|\\(\\=\\|[^:]\\):\\([^:]\\|\\'\\)"
+                       limit t t nil 1)
+                      (match-beginning 2))
+
+                 (progn                ; there's a proper :
+                   (goto-char (match-beginning 2)) ; just after the :
+                   (c-put-c-type-property (1- (point)) 'c-decl-end)
+                   t)
+
+             ;; It's an unfinished label.  We consider the keyword enough
+             ;; to recognize it as a label, so that it gets fontified.
+             ;; Leave the point at the end of it, but don't put any
+             ;; `c-decl-end' marker.
+               (goto-char kwd-end)
+               t))))
 
      ;; @private, @protected, @public, in Objective C, or similar.
      ((and c-opt-extra-label-key
@@ -5893,7 +5968,7 @@ y   ;; True if there's a suffix match outside the outermost
       (when c-record-type-identifiers
        (c-record-ref-id (cons (match-beginning 1) (point))))
       (c-put-c-type-property (1- (point)) 'c-decl-end)
-      t)
+      (setq label-type t))
 
      ;; All other cases of labels.
      ((and c-recognize-colon-labels    ; nil for AWK and IDL, otherwise t.
@@ -5969,26 +6044,49 @@ y         ;; True if there's a suffix match outside the outermost
                         (c-forward-syntactic-ws)
                         (c-forward-label nil pte start))))))))))
 
+          ;; Point is still at the beginning of the possible label construct.
+          ;; 
           ;; Check that the next nonsymbol token is ":", or that we're in one
           ;; of QT's "slots" declarations.  Allow '(' for the sake of macro
           ;; arguments.  FIXME: Should build this regexp from the language
           ;; constants.
-          (when (c-syntactic-re-search-forward
-                 "[ \t[:?;{=*/%&|,<>!@+-]" limit t t) ; not at EOB
-            (backward-char)
-            (setq qt-symbol-idx
-                  (and (c-major-mode-is 'c++-mode)
-                       (string-match
-                        "\\(p\\(r\\(ivate\\|otected\\)\\|ublic\\)\\|more\\)\\>"
-                        (buffer-substring start (point)))))
-            (c-forward-syntactic-ws limit)
-            (when (or (looking-at ":\\([^:]\\|\\'\\)") ; A single colon.
-                      (and qt-symbol-idx
-                           (search-forward-regexp "\\=slots\\>" limit t)
-                           (progn (c-forward-syntactic-ws limit)
-                                  (looking-at ":\\([^:]\\|\\'\\)")))) ; A single colon
-              (forward-char)           ; to after the colon.
-              t)))
+          (cond
+           ;; public: protected: private:
+           ((and
+             (c-major-mode-is 'c++-mode)
+             (search-forward-regexp
+              "\\=p\\(r\\(ivate\\|otected\\)\\|ublic\\)\\>[^_]" nil t)
+             (progn (backward-char)
+                    (c-forward-syntactic-ws limit)
+                    (looking-at ":\\([^:]\\|\\'\\)"))) ; A single colon.
+            (forward-char)
+            (setq label-type t))
+           ;; QT double keyword like "protected slots:" or goto target.
+           ((progn (goto-char start) nil))
+           ((when (c-syntactic-re-search-forward
+                   "[ \t\n[:?;{=*/%&|,<>!@+-]" limit t t) ; not at EOB
+              (backward-char)
+              (setq label-end (point))
+              (setq qt-symbol-idx
+                    (and (c-major-mode-is 'c++-mode)
+                         (string-match
+                          "\\(p\\(r\\(ivate\\|otected\\)\\|ublic\\)\\|more\\)\\>"
+                          (buffer-substring start (point)))))  
+              (c-forward-syntactic-ws limit)
+              (cond
+               ((looking-at ":\\([^:]\\|\\'\\)") ; A single colon.
+                (forward-char)
+                (setq label-type
+                      (if (string= "signals" ; Special QT macro
+                                   (buffer-substring-no-properties start label-end))
+                          'qt-1kwd-colon
+                        'goto-target)))
+               ((and qt-symbol-idx
+                     (search-forward-regexp "\\=slots\\>" limit t)
+                     (progn (c-forward-syntactic-ws limit)
+                            (looking-at ":\\([^:]\\|\\'\\)"))) ; A single colon
+                (forward-char)
+                (setq label-type 'qt-2kwds-colon)))))))
 
       (save-restriction
        (narrow-to-region start (point))
@@ -5999,6 +6097,7 @@ y   ;; True if there's a suffix match outside the outermost
          (while (progn
                   (when (looking-at c-nonlabel-token-key)
                     (goto-char start)
+                    (setq label-type nil)
                     (throw 'check-label nil))
                   (and (c-safe (c-forward-sexp)
                                (c-forward-syntactic-ws)
@@ -6017,13 +6116,12 @@ y         ;; True if there's a suffix match outside the outermost
                                     (match-end 0)))))
 
          (c-put-c-type-property (1- (point-max)) 'c-decl-end)
-         (goto-char (point-max))
-         t)))
+         (goto-char (point-max)))))
 
      (t
       ;; Not a label.
-      (goto-char start)
-      nil))))
+      (goto-char start)))
+    label-type))
 
 (defun c-forward-objc-directive ()
   ;; Assuming the point is at the beginning of a token, try to move
@@ -7097,6 +7195,23 @@ comment at the start of cc-engine.el for more info."
 ;; auto newline analysis.
 (defvar c-auto-newline-analysis nil)
 
+(defun c-brace-anchor-point (bracepos)
+  ;; BRACEPOS is the position of a brace in a construct like "namespace
+  ;; Bar {".  Return the anchor point in this construct; this is the
+  ;; earliest symbol on the brace's line which isn't earlier than
+  ;; "namespace".
+  ;;
+  ;; Currently (2007-08-17), "like namespace" means "matches
+  ;; c-other-block-decl-kwds".  It doesn't work with "class" or "struct"
+  ;; or anything like that.
+  (save-excursion
+    (let ((boi (c-point 'boi bracepos)))
+      (goto-char bracepos)
+      (while (and (> (point) boi)
+                 (not (looking-at c-other-decl-block-key)))
+       (c-backward-token-2))
+      (if (> (point) boi) (point) boi))))
+
 (defsubst c-add-syntax (symbol &rest args)
   ;; A simple function to prepend a new syntax element to
   ;; `c-syntactic-context'.  Using `setq' on it is unsafe since it
@@ -7129,8 +7244,12 @@ comment at the start of cc-engine.el for more info."
   ;;
   ;; Point is assumed to be at the prospective anchor point for the
   ;; given SYNTAX-SYMBOL.  More syntax entries are added if we need to
-  ;; skip past open parens and containing statements.  All the added
-  ;; syntax elements will get the same anchor point.
+  ;; skip past open parens and containing statements.  Most of the added
+  ;; syntax elements will get the same anchor point - the exception is
+  ;; for an anchor in a construct like "namespace"[*] - this is as early
+  ;; as possible in the construct but on the same line as the {.
+  ;;
+  ;; [*] i.e. with a keyword matching c-other-block-decl-kwds.
   ;;
   ;; SYNTAX-EXTRA-ARGS are a list of the extra arguments for the
   ;; syntax symbol.  They are appended after the anchor point.
@@ -7155,7 +7274,11 @@ comment at the start of cc-engine.el for more info."
          ;; now at the start.
          on-label)
 
-      (apply 'c-add-syntax syntax-symbol nil syntax-extra-args)
+      ;; Use point as the anchor point for "namespace", "extern", etc.
+      (apply 'c-add-syntax syntax-symbol
+            (if (rassq syntax-symbol c-other-decl-block-key-in-symbols-alist)
+                (point) nil)
+            syntax-extra-args)
 
       ;; Loop while we have to back out of containing blocks.
       (while
@@ -7275,22 +7398,31 @@ comment at the start of cc-engine.el for more info."
                (setq step-type 'same
                      on-label nil))
 
+           ;; Stepped out of a brace block.
            (setq step-type (c-beginning-of-statement-1 containing-sexp)
                  on-label (eq step-type 'label))
 
            (if (and (eq step-type 'same)
                     (/= paren-pos (point)))
-               (save-excursion
-                 (goto-char paren-pos)
-                 (let ((inexpr (c-looking-at-inexpr-block
-                                (c-safe-position containing-sexp
-                                                 paren-state)
-                                containing-sexp)))
-                   (if (and inexpr
-                            (not (eq (car inexpr) 'inlambda)))
-                       (c-add-syntax 'statement-block-intro nil)
-                     (c-add-syntax 'defun-block-intro nil))))
-             (c-add-syntax 'statement-block-intro nil)))
+               (let (inexpr)
+                 (cond
+                  ((save-excursion
+                     (goto-char paren-pos)
+                     (setq inexpr (c-looking-at-inexpr-block
+                                   (c-safe-position containing-sexp paren-state)
+                                   containing-sexp)))
+                   (c-add-syntax (if (eq (car inexpr) 'inlambda)
+                                     'defun-block-intro
+                                   'statement-block-intro)
+                                 nil))
+                  ((looking-at c-other-decl-block-key)
+                   (c-add-syntax
+                    (cdr (assoc (match-string 1)
+                                c-other-decl-block-key-in-symbols-alist))
+                    (max (c-point 'boi paren-pos) (point))))
+                  (t (c-add-syntax 'defun-block-intro nil))))
+                            
+                (c-add-syntax 'statement-block-intro nil)))
 
          (if (= paren-pos boi)
              ;; Always done if the open brace was at boi.  The
@@ -7302,10 +7434,13 @@ comment at the start of cc-engine.el for more info."
 
       ;; Fill in the current point as the anchor for all the symbols
       ;; added above.
-      (let ((p c-syntactic-context))
+      (let ((p c-syntactic-context) q)
        (while (not (eq p syntax-last))
-         (if (cdr (car p))
-             (setcar (cdr (car p)) (point)))
+         (setq q (cdr (car p))) ; e.g. (nil 28) [from (arglist-cont-nonempty nil 28)]
+         (while q
+           (unless (car q)
+             (setcar q (point)))
+           (setq q (cdr q)))
          (setq p (cdr p))))
       )))
 
@@ -8260,9 +8395,7 @@ comment at the start of cc-engine.el for more info."
                (if (c-keyword-member containing-decl-kwd
                                      'c-other-block-decl-kwds)
                    (progn
-                     (goto-char containing-decl-open)
-                     (unless (= (point) (c-point 'boi))
-                       (goto-char containing-decl-start))
+                     (goto-char (c-brace-anchor-point containing-decl-open))
                      (c-add-stmt-syntax
                       (if (string-equal (symbol-name containing-decl-kwd)
                                         "extern")