diff lisp/progmodes/cc-engine.el @ 83554:b8d9a391daf3

Merged from emacs@sv.gnu.org Patches applied: * emacs@sv.gnu.org/emacs--devo--0--patch-599 Merge from erc--main--0 * emacs@sv.gnu.org/emacs--devo--0--patch-600 Merge from erc--main--0 * emacs@sv.gnu.org/emacs--devo--0--patch-601 Update from CVS * emacs@sv.gnu.org/emacs--devo--0--patch-602 Update from CVS * emacs@sv.gnu.org/emacs--devo--0--patch-603 Update from CVS * emacs@sv.gnu.org/emacs--devo--0--patch-604 Merge from gnus--rel--5.10 * emacs@sv.gnu.org/emacs--devo--0--patch-605 Update from CVS * emacs@sv.gnu.org/emacs--devo--0--patch-606 Merge from gnus--rel--5.10 * emacs@sv.gnu.org/emacs--devo--0--patch-607 Update from CVS * emacs@sv.gnu.org/emacs--devo--0--patch-608 Update from CVS * emacs@sv.gnu.org/emacs--devo--0--patch-609 Update from CVS * emacs@sv.gnu.org/emacs--devo--0--patch-610 Update from CVS * emacs@sv.gnu.org/emacs--devo--0--patch-611 Update from CVS * emacs@sv.gnu.org/emacs--devo--0--patch-612 Merge from gnus--rel--5.10 * emacs@sv.gnu.org/emacs--devo--0--patch-613 Update from CVS * emacs@sv.gnu.org/emacs--devo--0--patch-614 Make byte compiler correctly write circular constants * emacs@sv.gnu.org/emacs--devo--0--patch-615 Update from CVS * emacs@sv.gnu.org/emacs--devo--0--patch-616 Update from CVS * emacs@sv.gnu.org/emacs--devo--0--patch-617 Update from CVS * emacs@sv.gnu.org/emacs--devo--0--patch-618 Update from CVS * emacs@sv.gnu.org/gnus--rel--5.10--patch-192 Merge from emacs--devo--0 * emacs@sv.gnu.org/gnus--rel--5.10--patch-193 Update from CVS * emacs@sv.gnu.org/gnus--rel--5.10--patch-194 Merge from emacs--devo--0 * emacs@sv.gnu.org/gnus--rel--5.10--patch-195 Update from CVS * emacs@sv.gnu.org/gnus--rel--5.10--patch-196 Update from CVS git-archimport-id: lorentey@elte.hu--2004/emacs--multi-tty--0--patch-594
author Karoly Lorentey <lorentey@elte.hu>
date Mon, 29 Jan 2007 22:21:19 +0000
parents e3694f1cb928
children 33cf1027eb42 95d0cdf160ea
line wrap: on
line diff
--- a/lisp/progmodes/cc-engine.el	Sat Jan 13 22:59:28 2007 +0000
+++ b/lisp/progmodes/cc-engine.el	Mon Jan 29 22:21:19 2007 +0000
@@ -1,10 +1,11 @@
 ;;; cc-engine.el --- core syntax guessing engine for CC mode
 
 ;; Copyright (C) 1985, 1987, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-;;   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006  Free Software
-;;   Foundation, Inc.
-
-;; Authors:    1998- Martin Stjernholm
+;;   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+;;   Free Software Foundation, Inc.
+
+;; Authors:    2001- Alan Mackenzie
+;;             1998- Martin Stjernholm
 ;;             1992-1999 Barry A. Warsaw
 ;;             1987 Dave Detlefs and Stewart Clamen
 ;;             1985 Richard M. Stallman
@@ -6220,65 +6221,101 @@
   ;; `c-recognize-knr-p' is not checked.  If LIM is non-nil, it's a
   ;; position that bounds the backward search for the argument list.
   ;;
-  ;; Note: A declaration level context is assumed; the test can return
-  ;; false positives for statements.
+  ;; Point must be within a possible K&R region, e.g. just before a top-level
+  ;; "{".  It must be outside of parens and brackets.  The test can return
+  ;; false positives otherwise.
   ;;
   ;; This function might do hidden buffer changes.
 
   (save-excursion
     (save-restriction
-
-      ;; Go back to the closest preceding normal parenthesis sexp.  We
-      ;; take that as the argument list in the function header.  Then
-      ;; check that it's followed by some symbol before the next ';'
-      ;; or '{'.  If it does, it's the header of the K&R argdecl we're
-      ;; in.
-      (if lim (narrow-to-region lim (c-point 'eol)))
-      (let ((outside-macro (not (c-query-macro-start)))
-	    paren-end)
-
-	(catch 'done
-	  (while (if (and (setq paren-end (c-down-list-backward (point)))
-			  (eq (char-after paren-end) ?\)))
-		     (progn
-		       (goto-char (1+ paren-end))
-		       (if outside-macro
-			   (c-beginning-of-macro)))
-		   (throw 'done nil))))
-
-	(and (progn
-	       (c-forward-syntactic-ws)
-	       (looking-at "\\w\\|\\s_"))
-
-	     (save-excursion
-	       ;; The function header in a K&R declaration should only
-	       ;; contain identifiers separated by comma.  It should
-	       ;; also contain at least one identifier since there
-	       ;; wouldn't be anything to declare in the K&R region
-	       ;; otherwise.
-	       (when (c-go-up-list-backward paren-end)
-		 (forward-char)
-		 (catch 'knr-ok
-		   (while t
-		     (c-forward-syntactic-ws)
-		     (if (or (looking-at c-known-type-key)
-			     (looking-at c-keywords-regexp))
-			 (throw 'knr-ok nil))
-		     (c-forward-token-2)
-		     (if (eq (char-after) ?,)
-			 (forward-char)
-		       (throw 'knr-ok (and (eq (char-after) ?\))
-					   (= (point) paren-end))))))))
-
-	     (save-excursion
-	       ;; If it's a K&R declaration then we're now at the
-	       ;; beginning of the function arglist.  Check that there
-	       ;; isn't a '=' before it in this statement since that
-	       ;; means it some kind of initialization instead.
-	       (c-syntactic-skip-backward "^;=}{")
-	       (not (eq (char-before) ?=)))
-
-	     (point))))))
+      ;; If we're in a macro, our search range is restricted to it.  Narrow to
+      ;; the searchable range.
+      (let* ((macro-start (c-query-macro-start))
+	     (lim (max (or lim (point-min)) (or macro-start (point-min))))
+	     before-lparen after-rparen)
+	(narrow-to-region lim (c-point 'eol))
+
+	;; Search backwards for the defun's argument list.  We give up if we
+	;; encounter a "}" (end of a previous defun) or BOB.
+	;;
+	;; The criterion for a paren structure being the arg list is:
+	;; o - there is non-WS stuff after it but before any "{"; AND
+	;; o - the token after it isn't a ";" AND
+	;; o - it is preceded by either an identifier (the function name) or
+	;;   a macro expansion like "DEFUN (...)"; AND
+	;; o - its content is a non-empty comma-separated list of identifiers
+	;;   (an empty arg list won't have a knr region).
+	;;
+	;; The following snippet illustrates these rules:
+	;; int foo (bar, baz, yuk)
+	;;     int bar [] ;
+	;;     int (*baz) (my_type) ;
+	;;     int (*) (void) (*yuk) (void) ;
+	;; {
+
+	(catch 'knr
+	  (while t ; go round one paren/bracket construct each time round.
+	    (or (c-syntactic-skip-backward "^)]}")
+		(throw 'knr nil))	; no more bpb pairs left.
+	    (cond ((eq (char-before) ?\))
+		   (setq after-rparen (point)))
+		  ((eq (char-before) ?\})
+		   (throw 'knr nil))
+		  (t (setq after-rparen nil))) ; "]"
+
+	    (if after-rparen
+	    ;; We're inside a paren.  Could it be our argument list....?
+	      (if
+		  (and
+		   (progn
+		     (goto-char after-rparen)
+		     (unless (c-go-list-backward) (throw 'knr nil)) ;
+		;; FIXME!!!  What about macros between the parens?  2007/01/20
+		     (setq before-lparen (point)))
+
+		   ;; It can't be the arg list if next token is ; or {
+		   (progn (goto-char after-rparen)
+			  (c-forward-syntactic-ws)
+			  (not (memq (char-after) '(?\; ?\{))))
+
+		   ;; Is the thing preceding the list an identifier (the
+		   ;; function name), or a macro expansion?
+		   (progn
+		     (goto-char before-lparen)
+		     (eq (c-backward-token-2) 0)
+		     (or (c-on-identifier)
+			 (and (eq (char-after) ?\))
+			      (c-go-up-list-backward)
+			      (eq (c-backward-token-2) 0)
+			      (c-on-identifier))))
+
+		   ;; Have we got a non-empty list of comma-separated
+		   ;; identifiers?
+		   (progn
+		     (goto-char before-lparen)
+		     (c-forward-token-2) ; to first token inside parens
+		     (and
+		      (c-on-identifier)
+		      (c-forward-token-2)
+		      (catch 'id-list
+			(while (eq (char-after) ?\,)
+			  (c-forward-token-2)
+			  (unless (c-on-identifier) (throw 'id-list nil))
+			  (c-forward-token-2))
+			(eq (char-after) ?\))))))
+
+		  ;; ...Yes.  We've identified the function's argument list.
+		  (throw 'knr
+		       (progn (goto-char after-rparen)
+			      (c-forward-syntactic-ws)
+			      (point)))
+
+		;; ...No.  The current parens aren't the function's arg list.
+		(goto-char before-lparen))
+
+	      (or (c-go-list-backward)	; backwards over [ .... ]
+		  (throw 'knr nil)))))))))
 
 (defun c-skip-conditional ()
   ;; skip forward over conditional at point, including any predicate