changeset 20914:8f189ffad604

(c-forward-syntactic-ws, c-backward-syntactic-ws): 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.
author Richard M. Stallman <rms@gnu.org>
date Tue, 17 Feb 1998 07:08:44 +0000
parents c7ee864ae985
children c746c93c9c95
files lisp/progmodes/cc-engine.el
diffstat 1 files changed, 209 insertions(+), 79 deletions(-) [+]
line wrap: on
line diff
--- a/lisp/progmodes/cc-engine.el	Tue Feb 17 07:06:17 1998 +0000
+++ b/lisp/progmodes/cc-engine.el	Tue Feb 17 07:08:44 1998 +0000
@@ -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
@@ -231,36 +231,44 @@
 
 (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)))))
 
 
 ;; Return `c' if in a C-style comment, `c++' if in a C++ style
@@ -278,22 +286,118 @@
       (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))))
+
+
 
 ;; utilities for moving and querying around syntactic elements
 (defvar c-parsing-error nil)
@@ -312,7 +416,7 @@
 		  ;; 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)
@@ -472,11 +576,6 @@
     (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 [+-].
@@ -545,6 +644,8 @@
 	  (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)))
@@ -569,7 +670,9 @@
   (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))
@@ -687,7 +790,7 @@
 	(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
@@ -862,17 +965,27 @@
 				     (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
@@ -927,10 +1040,14 @@
 	  (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)))
@@ -941,19 +1058,25 @@
 	   ;; 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)
@@ -993,7 +1116,7 @@
 		       )))
 	      (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
@@ -1180,9 +1303,12 @@
 	    (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
@@ -1261,10 +1387,14 @@
 		    (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
@@ -1299,9 +1429,9 @@
 	   ;; 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)
@@ -1381,7 +1511,7 @@
 	    (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)
@@ -1516,17 +1646,17 @@
 	     ((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