]> git.eshelyaron.com Git - emacs.git/commitdiff
(c-forward-syntactic-ws, c-backward-syntactic-ws):
authorRichard M. Stallman <rms@gnu.org>
Tue, 17 Feb 1998 07:08:44 +0000 (07:08 +0000)
committerRichard M. Stallman <rms@gnu.org>
Tue, 17 Feb 1998 07:08:44 +0000 (07:08 +0000)
Don't narrow, just make a simple check against the given limit.

(c-collect-line-comments): New function.

(c-literal-limits): New function that finds the start and end pos
of a comment or string surrounding point.

(c-literal-limits-fast): A faster variant of `c-literal-limits'
for newer Emacsen where the state returned from
`parse-partial-sexp' contains the starting pos of the last literal.

(c-parse-state): Use (c-point 'bod) instead of
beginning-of-defun directly.

(c-guess-basic-syntax): Fixed a few byte compiler warnings.

(c-backward-to-start-of-do): Break infloop for
invalid code, e.g. when someone types while (TRUE) { at the top of
a buffer, we shouldn't hang when the { is typed!

(c-backward-to-start-of-if): Ensure never
move forward, not even if point < lim.

(c-search-uplist-for-classkey): When searching up for a class key,
instead of hardcoding the extended search for "extern", use the new
variable c-extra-toplevel-key, which is language dependent.  For C++,
this variable includes the keyword "namespace" which will match C++
namespace introducing blocks.

(c-guess-basic-syntax): Support for recognizing C++ namespace
blocks, by elaborating on the mechanism used to find external
language blocks.  Searches which hardcoded "extern" now use
c-extra-toplevel-key, a language dependent variable.  Case clauses
that were modified: CASE 5A.1, CASE 5A.4, CASE 5F, CASE 5I, CASE
14A.

CASE 3: we can now determine whether we're at the beginning of a
  cpp macro definition, or inside the middle of one. Set syntax to
  'cpp-macro in the former case, 'cpp-macro-cont in the latter.  In
  both cases, the relpos is the beginning of the macro.

(c-forward-syntactic-ws): Added code that skips forward over
multi-line cpp macros.

(c-beginning-of-macro): Moved, and made into a defsubst.  This
function can now actually find the beginning of a multi-line C
preprocessor macro.

(c-backward-syntactic-ws): Use c-beginning-of-macro to skip backwards
over multi-line macro definitions.

(c-in-literal, c-fast-in-literal): Use c-beginning-of-macro to
find out whether we're in a multi-line macro definition.

(c-fast-in-literal): Function which should be faster than
c-in-literal.  In XEmacs, this uses buffer-syntactic-context.

lisp/progmodes/cc-engine.el

index 7d164f9e868d788e42feff9fb0816ece50e857a9..f4f37379a5b400a492519c27409d3b43e19d4573 100644 (file)
@@ -1,6 +1,6 @@
 ;;; cc-engine.el --- core syntax guessing engine for CC mode
 
-;; Copyright (C) 1985,87,92,93,94,95,96,97 Free Software Foundation, Inc.
+;; Copyright (C) 1985,87,92,93,94,95,96,97,98 Free Software Foundation, Inc.
 
 ;; Authors:    1992-1997 Barry A. Warsaw
 ;;             1987 Dave Detlefs and Stewart Clamen
 
 (defun c-forward-syntactic-ws (&optional lim)
   ;; Forward skip of syntactic whitespace for Emacs 19.
-  (save-restriction
-    (let* ((lim (or lim (point-max)))
-          (here lim)
-          (hugenum (point-max)))
-      (narrow-to-region lim (point))
-      (while (/= here (point))
-       (setq here (point))
-       (forward-comment hugenum)
-       ;; skip preprocessor directives
-       (if (and (eq (char-after) ?#)
+  (let* ((here (point-max))
+        (hugenum (point-max)))
+    (while (/= here (point))
+      (setq here (point))
+      (forward-comment hugenum)
+      ;; skip preprocessor directives
+      (when (and (eq (char-after) ?#)
                 (= (c-point 'boi) (point)))
-           (end-of-line)
-         )))))
+       (while (eq (char-before (c-point 'eol)) ?\\)
+         (forward-line 1))
+       (end-of-line))
+      )
+    (if lim (goto-char (min (point) lim)))))
+
+(defsubst c-beginning-of-macro (&optional lim)
+  ;; Go to the beginning of a cpp macro definition.  Leaves point at
+  ;; the beginning of the macro and returns t if in a cpp macro
+  ;; definition, otherwise returns nil and leaves point unchanged.
+  ;; `lim' is currently ignored, but the interface requires it.
+  (let ((here (point)))
+    (beginning-of-line)
+    (while (eq (char-before (1- (point))) ?\\)
+      (forward-line -1))
+    (back-to-indentation)
+    (if (eq (char-after) ?#)
+       t
+      (goto-char here)
+      nil)))
 
 (defun c-backward-syntactic-ws (&optional lim)
   ;; Backward skip over syntactic whitespace for Emacs 19.
-  (save-restriction
-    (let* ((lim (or lim (c-point 'bod)))
-          (here lim)
-          (hugenum (- (point-max))))
-      (if (< lim (point))
-         (progn
-           (narrow-to-region lim (point))
-           (while (/= here (point))
-             (setq here (point))
-             (forward-comment hugenum)
-             (if (eq (c-in-literal lim) 'pound)
-                 (beginning-of-line))
-             )))
-      )))
+  (let* ((here (point-min))
+        (hugenum (- (point-max))))
+    (while (/= here (point))
+      (setq here (point))
+      (forward-comment hugenum)
+      (c-beginning-of-macro))
+    (if lim (goto-char (max (point) lim)))))
 
 \f
 ;; Return `c' if in a C-style comment, `c++' if in a C++ style
       (aref c-in-literal-cache 1)
     (let ((rtn (save-excursion
                 (let* ((lim (or lim (c-point 'bod)))
-                       (here (point))
                        (state (parse-partial-sexp lim (point))))
                   (cond
                    ((nth 3 state) 'string)
                    ((nth 4 state) (if (nth 7 state) 'c++ 'c))
-                   ((progn
-                      (goto-char here)
-                      (beginning-of-line)
-                      (looking-at "[ \t]*#"))
-                    'pound)
+                   ((c-beginning-of-macro lim) 'pound)
                    (t nil))))))
       ;; cache this result if the cache is enabled
       (and (boundp 'c-in-literal-cache)
           (setq c-in-literal-cache (vector (point) rtn)))
       rtn)))
 
+;; XEmacs has a built-in function that should make this much quicker.
+;; I don't think we even need the cache, which makes our lives more
+;; complicated anyway.  In this case, lim is ignored.
+(defun c-fast-in-literal (&optional lim)
+  (let ((context (buffer-syntactic-context)))
+    (cond
+     ((eq context 'string) 'string)
+     ((eq context 'comment) 'c++)
+     ((eq context 'block-comment) 'c)
+     ((save-excursion (c-beginning-of-macro lim)) 'pound))))
+
+(if (fboundp 'buffer-syntactic-context)
+    (defalias 'c-in-literal 'c-fast-in-literal))
+
+(defun c-literal-limits (&optional lim)
+  ;; Returns a cons of the beginning and end positions of the comment
+  ;; or string surrounding point (including both delimiters), or nil
+  ;; if point isn't in one.  This is the Emacs 19 version.
+  (save-excursion
+    (let* ((lim (or lim (c-point 'bod)))
+          (state (parse-partial-sexp lim (point))))
+      (cond ((nth 3 state)
+            ;; String.  Search backward for the start.
+            (while (nth 3 state)
+              (search-backward (make-string 1 (nth 3 state)))
+              (setq state (parse-partial-sexp lim (point))))
+            (cons (point) (or (c-safe (forward-sexp 1) (point))
+                              (point-max))))
+           ((nth 7 state)
+            ;; C++ comment.  Search from bol for the comment starter.
+            (beginning-of-line)
+            (setq state (parse-partial-sexp lim (point))
+                  lim (point))
+            (while (not (nth 7 state))
+              (search-forward "//")    ; Should never fail.
+              (setq state (parse-partial-sexp
+                           lim (point) nil nil state)
+                    lim (point)))
+            (backward-char 2)
+            (cons (point) (progn (forward-comment 1) (point))))
+           ((nth 4 state)
+            ;; C comment.  Search backward for the comment starter.
+            (while (nth 4 state)
+              (search-backward "/*")   ; Should never fail.
+              (setq state (parse-partial-sexp lim (point))))
+            (cons (point) (progn (forward-comment 1) (point))))
+           ((c-safe (nth 4 (parse-partial-sexp ; Can't use prev state due
+                            lim (1+ (point))))) ; to bug in Emacs 19.34.
+            ;; We're standing in a comment starter.
+            (backward-char 2)
+            (cons (point) (progn (forward-comment 1) (point))))
+           ))))
+
+(defun c-literal-limits-fast (&optional lim)
+  ;; Returns a cons of the beginning and end positions of the comment
+  ;; or string surrounding point (including both delimiters), or nil
+  ;; if point isn't in one.  This is for emacsen whose
+  ;; `parse-partial-sexp' returns the pos of the comment start.
+  (save-excursion
+    (let ((state (parse-partial-sexp lim (point))))
+      (cond ((nth 3 state)             ; String.
+            (goto-char (nth 8 state))
+            (cons (point) (or (c-safe (forward-sexp 1) (point))
+                              (point-max))))
+           ((nth 4 state)              ; Comment.
+            (goto-char (nth 8 state))
+            (cons (point) (progn (forward-comment 1) (point))))
+           ((c-safe
+             (nth 4 (parse-partial-sexp ; Works?
+                     (point) (1+ (point)) nil nil state)))
+            ;; We're in a comment starter.
+            (backward-char 2)
+            (cons (point) (progn (forward-comment 1) (point))))
+           ))))
+
+(defun c-collect-line-comments (range)
+  ;; If the argument is a cons of two buffer positions (such as
+  ;; returned by c-literal-limits), and that range contains a C++
+  ;; style line comment, then an extended range is returned that
+  ;; contains all adjacent line comments (i.e. all comments with no
+  ;; empty lines or non-whitespace characters between them).
+  ;; Otherwise the argument is returned.
+  (save-excursion
+    (condition-case nil
+       (if (and (consp range) (progn
+                                (goto-char (car range))
+                                (looking-at "//")))
+           (let ((beg (point)))
+             (while (and (not (bobp))
+                         (forward-comment -1)
+                         (looking-at "//"))
+               (setq beg (point)))
+             (cons beg (progn
+                         (goto-char (cdr range))
+                         (while (looking-at "[ \t]*//")
+                           (forward-comment 1))
+                         (point))))
+         range)
+      (error range))))
+
+
 \f
 ;; utilities for moving and querying around syntactic elements
 (defvar c-parsing-error nil)
                  ;; in column zero)
                  (let ((cnt 2))
                    (while (not (or at-bob (zerop cnt)))
-                     (beginning-of-defun)
+                     (goto-char (c-point 'bod))
                      (if (eq (char-after) ?\{)
                          (setq cnt (1- cnt)))
                      (if (bobp)
     (goto-char placeholder)
     (skip-chars-forward "^:" (c-point 'eol))))
 
-(defun c-beginning-of-macro (&optional lim)
-  ;; Go to the beginning of the macro. Right now we don't support
-  ;; multi-line macros too well
-  (back-to-indentation))
-
 (defun c-in-method-def-p ()
   ;; Return nil if we aren't in a method definition, otherwise the
   ;; position of the initial [+-].
          (progn
            (backward-sexp 1)
            (cond
+            ;; break infloop for illegal C code
+            ((bobp) (setq do-level 0))
             ((memq (c-in-literal lim) '(c c++)))
             ((looking-at "while\\b[^_]")
              (setq do-level (1+ do-level)))
   (let ((if-level 1)
        (here (c-point 'bol))
        (case-fold-search nil)
-       (lim (or lim (c-point 'bod)))
+       (lim (or (and (>= (point) lim)
+                     lim)
+                (c-point 'bod)))
        (at-if (looking-at "if\\b[^_]")))
     (catch 'orphan-if
       (while (and (not (bobp))
        (save-excursion
          (save-restriction
            (goto-char search-start)
-           (let ((search-key (concat c-class-key "\\|extern[^_]"))
+           (let ((search-key (concat c-class-key "\\|" c-extra-toplevel-key))
                  foundp class match-end)
              (while (and (not foundp)
                          (progn
                                     (looking-at c-method-key)))
             literal containing-sexp char-before-ip char-after-ip lim
             syntax placeholder c-in-literal-cache inswitch-p
-            injava-inher
+            tmpsymbol keyword injava-inher
             ;; narrow out any enclosing class or extern "C" block
             (inclass-p (c-narrow-out-enclosing-class state indent-point))
-            (inextern-p (and inclass-p
-                             (save-excursion
-                               (save-restriction
-                                 (widen)
-                                 (goto-char (aref inclass-p 0))
-                                 (looking-at "extern[^_]")))))
-            )
-
+            inenclosing-p)
+       ;; check for meta top-level enclosing constructs, possible
+       ;; extern language definitions, possibly (in C++) namespace
+       ;; definitions.
+       (save-excursion
+         (save-restriction
+           (widen)
+           (if (and inclass-p
+                    (progn
+                      (goto-char (aref inclass-p 0))
+                      (looking-at c-extra-toplevel-key)))
+               (let ((enclosing (match-string 1)))
+                 (cond
+                  ((string-equal enclosing "extern")
+                   (setq inenclosing-p 'extern))
+                  ((string-equal enclosing "namespace")
+                   (setq inenclosing-p 'namespace))
+                  )))))
        ;; get the buffer position of the most nested opening brace,
        ;; if there is one, and it hasn't been narrowed out
        (save-excursion
          (while (and (zerop (forward-line -1))
                      (looking-at "^[ \t]*$")))
          (c-add-syntax literal (c-point 'boi)))
-        ;; CASE 3: in a cpp preprocessor
+        ;; CASE 3: in a cpp preprocessor macro
         ((eq literal 'pound)
-         (c-beginning-of-macro lim)
-         (c-add-syntax 'cpp-macro (c-point 'boi)))
+         (let ((boi (c-point 'boi))
+               (macrostart (progn (c-beginning-of-macro lim) (point))))
+           (setq tmpsymbol (if (= boi macrostart)
+                               'cpp-macro
+                             'cpp-macro-cont))
+           (c-add-syntax tmpsymbol macrostart)))
         ;; CASE 4: in an objective-c method intro
         (in-method-intro-p
          (c-add-syntax 'objc-method-intro (c-point 'boi)))
           ;; inline-inclass method opening brace
           ((eq char-after-ip ?{)
            (cond
-            ;; CASE 5A.1: extern declaration
+            ;; CASE 5A.1: extern language or namespace construct
             ((save-excursion
                (goto-char indent-point)
                (skip-chars-forward " \t")
                (and (c-safe (progn (backward-sexp 2) t))
-                    (looking-at "extern[^_]")
-                    (progn
-                      (setq placeholder (point))
-                      (forward-sexp 1)
-                      (c-forward-syntactic-ws)
-                      (eq (char-after) ?\"))))
+                    (looking-at c-extra-toplevel-key)
+                    (setq keyword (match-string 1)
+                          placeholder (point))
+                    (or (and (string-equal keyword "namespace")
+                             (setq tmpsymbol 'namespace-open))
+                        (and (string-equal keyword "extern")
+                             (progn
+                               (forward-sexp 1)
+                               (c-forward-syntactic-ws)
+                               (eq (char-after) ?\"))
+                             (setq tmpsymbol 'extern-lang-open)))
+                    ))
              (goto-char placeholder)
-             (c-add-syntax 'extern-lang-open (c-point 'boi)))
+             (c-add-syntax tmpsymbol (c-point 'boi)))
             ;; CASE 5A.2: we are looking at a class opening brace
             ((save-excursion
                (goto-char indent-point)
                       )))
              (c-add-syntax 'brace-list-open placeholder))
             ;; CASE 5A.4: inline defun open
-            ((and inclass-p (not inextern-p))
+            ((and inclass-p (not inenclosing-p))
              (c-add-syntax 'inline-open)
              (c-add-syntax 'inclass (aref inclass-p 0)))
             ;; CASE 5A.5: ordinary defun open
            (c-add-syntax 'access-label (c-point 'bonl))
            (c-add-syntax 'inclass (aref inclass-p 0)))
           ;; CASE 5F: extern-lang-close?
-          ((and inextern-p
+          ((and inenclosing-p
                 (eq char-after-ip ?}))
-           (c-add-syntax 'extern-lang-close (aref inclass-p 0)))
+           (setq tmpsymbol (if (eq inenclosing-p 'extern)
+                               'extern-lang-close
+                             'namespace-close))
+           (c-add-syntax tmpsymbol (aref inclass-p 0)))
           ;; CASE 5G: we are looking at the brace which closes the
           ;; enclosing nested class decl
           ((and inclass-p
                    (goto-char (aref inclass-p 1))
                    (or (= (point) (c-point 'boi))
                        (goto-char (aref inclass-p 0)))
-                   (if inextern-p
-                       (c-add-syntax 'inextern-lang)
-                     (c-add-syntax 'inclass (c-point 'boi)))))
-               ))
+                   (cond
+                    ((eq inenclosing-p 'extern)
+                     (c-add-syntax 'inextern-lang))
+                    ((eq inenclosing-p 'namespace)
+                     (c-add-syntax 'innamespace))
+                    (t (c-add-syntax 'inclass (c-point 'boi))))
+                   ))
+             ))
           ;; CASE 5J: we are at an ObjC or Java method definition
           ;; continuation line.
           ((and c-method-key
           ;; CASE 6C: we are inside a conditional test clause. treat
           ;; these things as statements
           ((save-excursion
-            (goto-char containing-sexp)
-            (and (c-safe (progn (forward-sexp -1) t))
-                 (looking-at "\\<for\\>[^_]")))
+             (goto-char containing-sexp)
+             (and (c-safe (progn (forward-sexp -1) t))
+                  (looking-at "\\<for\\>[^_]")))
            (goto-char (1+ containing-sexp))
            (c-forward-syntactic-ws indent-point)
            (c-beginning-of-statement-1 containing-sexp)
            (goto-char containing-sexp)
            (c-add-syntax 'brace-list-intro (c-point 'boi))
            )
-           ;;))                        ; end CASE 8B
+          ;;))                 ; end CASE 8B
           ;; CASE 8C: this is just a later brace-list-entry
           (t (goto-char (1+ containing-sexp))
              (c-forward-syntactic-ws indent-point)
             ((let ((inclass-p (progn
                                 (goto-char containing-sexp)
                                 (c-search-uplist-for-classkey state))))
-               ;; inextern-p in higher level let*
-               (setq inextern-p (and inclass-p
-                                     (progn
-                                       (goto-char (aref inclass-p 0))
-                                       (looking-at "extern[^_]"))))
-               (and inclass-p (not inextern-p)))
+               ;; inenclosing-p in higher level let*
+               (setq inenclosing-p (and inclass-p
+                                        (progn
+                                          (goto-char (aref inclass-p 0))
+                                          (looking-at c-extra-toplevel-key))))
+               (and inclass-p (not inenclosing-p)))
              (c-add-syntax 'inline-close relpos))
             ;; CASE 14B: if there an enclosing brace that hasn't
             ;; been narrowed out by a class, then this is a
             ;; block-close
-            ((and (not inextern-p)
+            ((and (not inenclosing-p)
                   (c-most-enclosing-brace state))
              (c-add-syntax 'block-close relpos))
             ;; CASE 14C: find out whether we're closing a top-level