summaryrefslogtreecommitdiff
path: root/lisp/progmodes/cc-menus.el
diff options
context:
space:
mode:
authorKarl Heuer <kwzh@gnu.org>1997-10-23 07:31:26 +0000
committerKarl Heuer <kwzh@gnu.org>1997-10-23 07:31:26 +0000
commitb2cf7e11669a646c851f008adcf32ce3ebad70a0 (patch)
tree450532e261541f91fb449e283ffb74d80b2cc004 /lisp/progmodes/cc-menus.el
parent2d1ac393335e5cf4103243cd41200e0474286b6d (diff)
downloademacs-b2cf7e11669a646c851f008adcf32ce3ebad70a0.tar.gz
(cc-imenu-c-prototype-macro-regexp): New var.
(cc-imenu-c++-generic-expression): Patches to better match C++ code. Given by jan.dubois@ibm.net (Jan Dubois) (cc-imenu-java-generic-expression): Removed test for declaration statements. Patch given by Ake Stenhoff <etxaksf@aom.ericsson.se>, as forwarded to me by RMS. Imenu support for Objective-C given by Masatake (jet) YAMATO.
Diffstat (limited to 'lisp/progmodes/cc-menus.el')
-rw-r--r--lisp/progmodes/cc-menus.el301
1 files changed, 261 insertions, 40 deletions
diff --git a/lisp/progmodes/cc-menus.el b/lisp/progmodes/cc-menus.el
index 20c7640b606..d758d0707f8 100644
--- a/lisp/progmodes/cc-menus.el
+++ b/lisp/progmodes/cc-menus.el
@@ -7,7 +7,7 @@
;; 1985 Richard M. Stallman
;; Maintainer: cc-mode-help@python.org
;; Created: 22-Apr-1997 (split from cc-mode.el)
-;; Version: 5.17
+;; Version: 5.18
;; Keywords: c languages oop
;; This file is part of GNU Emacs.
@@ -29,56 +29,97 @@
;; imenu integration
+(defvar cc-imenu-c-prototype-macro-regexp nil
+ "RE matching macro names used to conditionally specify function prototypes.
+
+For example:
+
+ #ifdef __STDC__
+ #define _P(x) x
+ #else
+ #define _P(x) /*nothing*/
+ #endif
+
+ int main _P( (int argc, char *argv[]) )
+
+A sample value might look like: `\\(_P\\|_PROTO\\)'.")
+
(defvar cc-imenu-c++-generic-expression
(`
- ((nil
+ (
+ ;; Try to match ::operator definitions first. Otherwise `X::operator new ()'
+ ;; will be incorrectly recognised as function `new ()' because the regexps
+ ;; work by backtracking from the end of the definition.
+ (nil
+ (,
+ (concat
+ "^\\<.*"
+ "[^a-zA-Z0-9_:<>~]" ; match any non-identifier char
+ ; (note: this can be `\n')
+ "\\("
+ "\\([a-zA-Z0-9_:<>~]*::\\)?" ; match an operator
+ "operator\\>[ \t]*"
+ "\\(()\\|[^(]*\\)" ; special case for `()' operator
+ "\\)"
+
+ "[ \t]*([^)]*)[ \t]*[^ \t;]" ; followed by ws, arg list,
+ ; require something other than
+ ; a `;' after the (...) to
+ ; avoid prototypes. Can't
+ ; catch cases with () inside
+ ; the parentheses surrounding
+ ; the parameters. e.g.:
+ ; `int foo(int a=bar()) {...}'
+ )) 1)
+ ;; Special case to match a line like `main() {}'
+ ;; e.g. no return type, not even on the previous line.
+ (nil
(,
(concat
- "^" ; beginning of line is required
- "\\(template[ \t]*<[^>]+>[ \t]*\\)?" ; there may be a "template <...>"
- "\\([a-zA-Z0-9_:]+[ \t]+\\)?" ; type specs; there can be no
- "\\([a-zA-Z0-9_:]+[ \t]+\\)?" ; more than 3 tokens, right?
-
- "\\(" ; last type spec including */&
- "[a-zA-Z0-9_:]+"
- "\\([ \t]*[*&]+[ \t]*\\|[ \t]+\\)" ; either ptr/ref sign or ws
- "\\)?" ; if there is a last type spec
- "\\(" ; name, take into the imenu entry
- "[a-zA-Z0-9_:~]+" ; member func, ctor or dtor...
- ; (may not contain * because then
- ; "a::operator char*" would
- ; become "char*"!)
- "\\|"
- "\\([a-zA-Z0-9_:~]*::\\)?operator"
- "[^a-zA-Z1-9_][^(]*" ; ...or operator
- " \\)"
- "[ \t]*([^)]*)[ \t\n]*[^ ;]" ; require something other than
- ; a `;' after the (...) to
- ; avoid prototypes. Can't
- ; catch cases with () inside
- ; the parentheses surrounding
- ; the parameters. e.g.:
- ; "int foo(int a=bar()) {...}"
-
- )) 6)
+ "^"
+ "\\([a-zA-Z_][a-zA-Z0-9_:<>~]*\\)" ; match function name
+ "[ \t]*([^)]*)[ \t]*[^ \t;]" ; see above
+ )) 1)
+ ;; Special case for definitions using phony prototype macros like:
+ ;; `int main _PROTO( (int argc,char *argv[]) )'.
+ ;; This case is only included if cc-imenu-c-prototype-macro-regexp is set.
+ ;; Only supported in c-code, so no `:<>~' chars in function name!
+ (,@ (if cc-imenu-c-prototype-macro-regexp
+ (` ((nil
+ (,
+ (concat
+ "^\\<.*" ; line MUST start with word char
+ "[^a-zA-Z0-9_]" ; match any non-identifier char
+ "\\([a-zA-Z_][a-zA-Z0-9_]*\\)" ; match function name
+ "[ \t]*" ; whitespace before macro name
+ cc-imenu-c-prototype-macro-regexp
+ "[ \t]*(" ; ws followed by first paren.
+ "[ \t]*([^)]*)[ \t]*[^ \t;]" ; see above
+ )) 1)))))
+ ;; General function name regexp
+ (nil
+ (,
+ (concat
+ "^\\<.*" ; line MUST start with word char
+ "[^a-zA-Z0-9_:<>~]" ; match any non-identifier char
+ "\\([a-zA-Z_][a-zA-Z0-9_:<>~]*\\)" ; match function name
+ "[ \t]*([^)]*)[ \t]*[^ \t;]" ; see above
+ )) 1)
+ ;; Class definitions
("Class"
(, (concat
- "^" ; beginning of line is required
- "\\(template[ \t]*<[^>]+>[ \t]*\\)?" ; there may be a "template <...>"
- "class[ \t]+"
- "\\([a-zA-Z0-9_]+\\)" ; the string we want to get
- "[ \t]*[:{]"
- )) 2)))
+ "^" ; beginning of line is required
+ "\\(template[ \t]*<[^>]+>[ \t]*\\)?" ; there may be a `template <...>'
+ "class[ \t]+"
+ "\\([a-zA-Z0-9_]+\\)" ; the string we want to get
+ "[ \t]*[:{]"
+ )) 2)))
"Imenu generic expression for C++ mode. See `imenu-generic-expression'.")
(defvar cc-imenu-c-generic-expression
cc-imenu-c++-generic-expression
"Imenu generic expression for C mode. See `imenu-generic-expression'.")
-;(defvar cc-imenu-objc-generic-expression
-; ())
-; Please contribute one!
-
(defvar cc-imenu-java-generic-expression
(`
((nil
@@ -93,11 +134,191 @@
"\\([ \t]*\\)+("
"\\([a-zA-Z,_1-9\n \t]*[[]?[]]?\\)*" ; arguments
")[ \t]*"
- "[^;(]"
+; "[^;(]"
"[,a-zA-Z_1-9\n \t]*{"
)) 6)))
"Imenu generic expression for Java mode. See `imenu-generic-expression'.")
+(defvar cc-imenu-objc-generic-expression
+ (concat
+ ;; For C
+ ;; Pick a token by (match-string 6)
+ (car (cdr (car cc-imenu-c++-generic-expression)))
+ ;; For Objective-C
+ ;; Pick a token by (match-string 8)
+ "\\|\\("
+ "^[-+][:a-zA-Z0-9()*_<>\n\t ]*[;{]" ; Methods
+ "\\|"
+ "^@interface[\t ]+[a-zA-Z0-9_]+[\t ]*:"
+ "\\|"
+ "^@interface[\t ]+[a-zA-Z0-9_]+[\t ]*([a-zA-Z0-9_]+)"
+ "\\|"
+ ;; For NSObject, NSProxy and Object... They don't have super class.
+ "^@interface[\t ]+[a-zA-Z0-9_]+[\t ]*.*$"
+ "\\|"
+ "^@implementation[\t ]+[a-zA-Z0-9_]+[\t ]*([a-zA-Z0-9_]+)"
+ "\\|"
+ "^@implementation[\t ]+[a-zA-Z0-9_]+"
+ "\\|"
+ "^@protocol[\t ]+[a-zA-Z0-9_]+" "\\)")
+ "Imenu generic expression for ObjC mode. See `imenu-generic-expression'.")
+
+
+;; Imenu support for objective-c uses functions.
+(defsubst cc-imenu-objc-method-to-selector (method)
+ "Return the objc selector style string of METHOD.
+Example:
+- perform: (SEL)aSelector withObject: object1 withObject: object2; /* METHOD */
+=>
+-perform:withObject:withObject:withObject: /* selector */"
+ (let ((return "") ; String to be returned
+ (p 0) ; Current scanning position in METHOD
+ (pmax (length method)) ;
+ char ; Current scanning target
+ (betweenparen 0) ; CHAR is in parentheses.
+ argreq ; An argument is required.
+ inargvar) ; position of CHAR is in an argument variable.
+ (while (< p pmax)
+ (setq char (aref method p)
+ p (1+ p))
+ (cond
+ ;; Is CHAR part of a objc token?
+ ((and (not inargvar) ; Ignore if CHAR is part of an argument variable.
+ (eq 0 betweenparen) ; Ignore if CHAR is in parentheses.
+ (or (and (<= ?a char) (<= char ?z))
+ (and (<= ?A char) (<= char ?Z))
+ (and (<= ?0 char) (<= char ?9))
+ (= ?_ char)))
+ (if argreq
+ (setq inargvar t
+ argreq nil)
+ (setq return (concat return (char-to-string char)))))
+ ;; Or a white space?
+ ((and inargvar (or (eq ?\ char) (eq ?\n char))
+ (setq inargvar nil)))
+ ;; Or a method separator?
+ ;; If a method separator, the next token will be an argument variable.
+ ((eq ?: char)
+ (setq argreq t
+ return (concat return (char-to-string char))))
+ ;; Or an open parentheses?
+ ((eq ?\( char)
+ (setq betweenparen (1+ betweenparen)))
+ ;; Or a close parentheses?
+ ((eq ?\) char)
+ (setq betweenparen (1- betweenparen)))))
+ return))
+
+(defun cc-imenu-objc-remove-white-space (str)
+ "Remove all spaces and tabs from STR."
+ (let ((return "")
+ (p 0)
+ (max (length str))
+ char)
+ (while (< p max)
+ (setq char (aref str p))
+ (setq p (1+ p))
+ (if (or (= char ?\ ) (= char ?\t))
+ ()
+ (setq return (concat return (char-to-string char)))))
+ return))
+
+(defun cc-imenu-objc-function ()
+ "imenu supports for objc-mode."
+ (let (methodlist
+ clist
+ (C 6)
+ (OBJC 8)
+ langnum
+ (classcount 0)
+ toplist
+ stupid
+ str
+ str2
+ (intflen (length "@interface"))
+ (implen (length "@implementation"))
+ (prtlen (length "@protocol"))
+ bufsubst-fun)
+ ;;
+ ;; Does this emacs has buffer-substring-no-properties?
+ ;;
+ (fset 'bufsubst-fun (if (fboundp 'buffer-substring-no-properties)
+ (symbol-function 'buffer-substring-no-properties)
+ (symbol-function 'buffer-substring)))
+ (goto-char (point-max))
+ (imenu-progress-message stupid 0)
+ ;;
+ (while (re-search-backward cc-imenu-objc-generic-expression nil t)
+ (imenu-progress-message stupid)
+ (setq langnum (if (match-beginning C) C OBJC))
+ (setq str (bufsubst-fun (match-beginning langnum) (match-end langnum)))
+ ;;
+ (cond
+ ;;
+ ;; C
+ ;;
+ ((eq langnum C)
+ (setq clist (cons (cons str (match-beginning langnum)) clist)))
+ ;;
+ ;; ObjC
+ ;;
+ ;; An instance Method
+ ((eq (aref str 0) ?-)
+ (setq str (concat "-" (cc-imenu-objc-method-to-selector str)))
+ (setq methodlist (cons (cons str
+ (match-beginning langnum))
+ methodlist)))
+ ;; A factory Method
+ ((eq (aref str 0) ?+)
+ (setq str (concat "+" (cc-imenu-objc-method-to-selector str)))
+ (setq methodlist (cons (cons str
+ (match-beginning langnum))
+ methodlist)))
+ ;; Interface or implementation or protocol
+ ((eq (aref str 0) ?@)
+ (setq classcount (1+ classcount))
+ (cond
+ ((and (> (length str) implen)
+ (string= (substring str 0 implen) "@implementation"))
+ (setq str (substring str implen)
+ str2 "@implementation"))
+ ((string= (substring str 0 intflen) "@interface")
+ (setq str (substring str intflen)
+ str2 "@interface"))
+ ((string= (substring str 0 prtlen) "@protocol")
+ (setq str (substring str prtlen)
+ str2 "@protocol")))
+ (setq str (cc-imenu-objc-remove-white-space str))
+ (setq methodlist (cons (cons str2
+ (match-beginning langnum))
+ methodlist))
+ (setq toplist (cons nil (cons (cons str
+ methodlist) toplist))
+ methodlist nil))))
+ ;;
+ (imenu-progress-message stupid 100)
+ (if (eq (car toplist) nil)
+ (setq toplist (cdr toplist)))
+
+ ;; In this buffer, there is only one or zero @{interface|implementation|protocol}.
+ (if (< classcount 2)
+ (let ((classname (car (car toplist)))
+ (p (cdr (car (cdr (car toplist)))))
+ last)
+ (setq toplist (cons (cons classname p) (cdr (cdr (car toplist)))))
+ ;; Add C lang token
+ (if clist
+ (progn
+ (setq last toplist)
+ (while (cdr last)
+ (setq last (cdr last)))
+ (setcdr last clist))))
+ ;; Add C lang tokens as a sub menu
+ (setq toplist (cons (cons "C" clist) toplist)))
+ ;;
+ toplist
+ ))
+
(provide 'cc-menus)
;;; cc-menus.el ends here