1;;; cc-menus.el --- imenu support for CC Mode 2 3;; Copyright (C) 1985, 1987, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 4;; 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 5;; Free Software Foundation, Inc. 6 7;; Authors: 1998- Martin Stjernholm 8;; 1992-1999 Barry A. Warsaw 9;; 1987 Dave Detlefs and Stewart Clamen 10;; 1985 Richard M. Stallman 11;; Maintainer: bug-cc-mode@gnu.org 12;; Created: 22-Apr-1997 (split from cc-mode.el) 13;; Version: See cc-mode.el 14;; Keywords: c languages oop 15 16;; This file is part of GNU Emacs. 17 18;; GNU Emacs is free software; you can redistribute it and/or modify 19;; it under the terms of the GNU General Public License as published by 20;; the Free Software Foundation; either version 2, or (at your option) 21;; any later version. 22 23;; GNU Emacs is distributed in the hope that it will be useful, 24;; but WITHOUT ANY WARRANTY; without even the implied warranty of 25;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 26;; GNU General Public License for more details. 27 28;; You should have received a copy of the GNU General Public License 29;; along with this program; see the file COPYING. If not, write to 30;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 31;; Boston, MA 02110-1301, USA. 32 33;;; Commentary: 34 35;;; Code: 36 37(eval-when-compile 38 (let ((load-path 39 (if (and (boundp 'byte-compile-dest-file) 40 (stringp byte-compile-dest-file)) 41 (cons (file-name-directory byte-compile-dest-file) load-path) 42 load-path))) 43 (load "cc-bytecomp" nil t))) 44 45(cc-require 'cc-defs) 46 47;; The things referenced in imenu, which we don't require. 48(cc-bytecomp-defvar imenu-case-fold-search) 49(cc-bytecomp-defvar imenu-generic-expression) 50(cc-bytecomp-defvar imenu-create-index-function) 51(cc-bytecomp-defun imenu-progress-message) 52 53 54;; imenu integration 55(defvar cc-imenu-c-prototype-macro-regexp nil 56 "RE matching macro names used to conditionally specify function prototypes. 57 58For example: 59 60 #ifdef __STDC__ 61 #define _P(x) x 62 #else 63 #define _P(x) /*nothing*/ 64 #endif 65 66 int main _P( (int argc, char *argv[]) ) 67 68A sample value might look like: `\\(_P\\|_PROTO\\)'.") 69 70(defvar cc-imenu-c++-generic-expression 71 `( 72 ;; Try to match ::operator definitions first. Otherwise `X::operator new ()' 73 ;; will be incorrectly recognised as function `new ()' because the regexps 74 ;; work by backtracking from the end of the definition. 75 (nil 76 ,(concat 77 "^\\<.*" 78 "[^" c-alnum "_:<>~]" ; match any non-identifier char 79 ; (note: this can be `\n') 80 "\\(" 81 "\\([" c-alnum "_:<>~]*::\\)?" ; match an operator 82 "operator\\>[ \t]*" 83 "\\(()\\|[^(]*\\)" ; special case for `()' operator 84 "\\)" 85 86 "[ \t]*([^)]*)[ \t]*[^ \t;]" ; followed by ws, arg list, 87 ; require something other than 88 ; a `;' after the (...) to 89 ; avoid prototypes. Can't 90 ; catch cases with () inside 91 ; the parentheses surrounding 92 ; the parameters. e.g.: 93 ; `int foo(int a=bar()) {...}' 94 ) 1) 95 ;; Special case to match a line like `main() {}' 96 ;; e.g. no return type, not even on the previous line. 97 (nil 98 ,(concat 99 "^" 100 "\\([" c-alpha "_][" c-alnum "_:<>~]*\\)" ; match function name 101 "[ \t]*(" ; see above, BUT 102 "[ \t]*\\([^ \t(*][^)]*\\)?)" ; the arg list must not start 103 "[ \t]*[^ \t;(]" ; with an asterisk or parentheses 104 ) 1) 105 ;; General function name regexp 106 (nil 107 ,(concat 108 "^\\<" ; line MUST start with word char 109 "[^()]*" ; no parentheses before 110 "[^" c-alnum "_:<>~]" ; match any non-identifier char 111 "\\([" c-alpha "_][" c-alnum "_:<>~]*\\)" ; match function name 112 "\\([ \t\n]\\|\\\\\n\\)*(" ; see above, BUT the arg list 113 "\\([ \t\n]\\|\\\\\n\\)*\\([^ \t\n(*][^)]*\\)?)" ; must not start 114 "\\([ \t\n]\\|\\\\\n\\)*[^ \t\n;(]" ; with an asterisk or parentheses 115 ) 1) 116 ;; Special case for definitions using phony prototype macros like: 117 ;; `int main _PROTO( (int argc,char *argv[]) )'. 118 ;; This case is only included if cc-imenu-c-prototype-macro-regexp is set. 119 ;; Only supported in c-code, so no `:<>~' chars in function name! 120 ,@(if cc-imenu-c-prototype-macro-regexp 121 `((nil 122 ,(concat 123 "^\\<.*" ; line MUST start with word char 124 "[^" c-alnum "_]" ; match any non-identifier char 125 "\\([" c-alpha "_][" c-alnum "_]*\\)" ; match function name 126 "[ \t]*" ; whitespace before macro name 127 cc-imenu-c-prototype-macro-regexp 128 "[ \t]*(" ; ws followed by first paren. 129 "[ \t]*([^)]*)[ \t]*)[ \t]*[^ \t;]" ; see above 130 ) 1))) 131 ;; Class definitions 132 ("Class" 133 ,(concat 134 "^" ; beginning of line is required 135 "\\(template[ \t]*<[^>]+>[ \t]*\\)?" ; there may be a `template <...>' 136 "\\(class\\|struct\\)[ \t]+" 137 "\\(" ; the string we want to get 138 "[" c-alnum "_]+" ; class name 139 "\\(<[^>]+>\\)?" ; possibly explicitly specialized 140 "\\)" 141 "\\([ \t\n]\\|\\\\\n\\)*[:{]" 142 ) 3)) 143 "Imenu generic expression for C++ mode. See `imenu-generic-expression'.") 144 145(defvar cc-imenu-c-generic-expression 146 cc-imenu-c++-generic-expression 147 "Imenu generic expression for C mode. See `imenu-generic-expression'.") 148 149(defvar cc-imenu-java-generic-expression 150 `((nil 151 ,(concat 152 "[" c-alpha "_][\]\[." c-alnum "_]+[ \t\n\r]+" ; type spec 153 "\\([" c-alpha "_][" c-alnum "_]+\\)" ; method name 154 "[ \t\n\r]*" 155 ;; An argument list that is either empty or contains at least 156 ;; two identifiers with only space between them. This avoids 157 ;; matching e.g. "else if (foo)". 158 (concat "([ \t\n\r]*" 159 "\\([\]\[.," c-alnum "_]+" 160 "[ \t\n\r]+" 161 "[\]\[.," c-alnum "_]" 162 "[\]\[.," c-alnum "_ \t\n\r]*" 163 "\\)?)") 164 "[.," c-alnum "_ \t\n\r]*" 165 "{" 166 ) 1)) 167 "Imenu generic expression for Java mode. See `imenu-generic-expression'.") 168 169;; *Warning for cc-mode developers* 170;; 171;; `cc-imenu-objc-generic-expression' elements depend on 172;; `cc-imenu-c++-generic-expression'. So if you change this 173;; expression, you need to change following variables, 174;; `cc-imenu-objc-generic-expression-*-index', 175;; too. `cc-imenu-objc-function' uses these *-index variables, in 176;; order to know where the each regexp *group \\(foobar\\)* elements 177;; are started. 178;; 179;; *-index variables are initialized during `cc-imenu-objc-generic-expression' 180;; being initialized. 181;; 182 183;; Internal variables 184(defvar cc-imenu-objc-generic-expression-noreturn-index nil) 185(defvar cc-imenu-objc-generic-expression-general-func-index nil) 186(defvar cc-imenu-objc-generic-expression-proto-index nil) 187(defvar cc-imenu-objc-generic-expression-objc-base-index nil) 188 189(defvar cc-imenu-objc-generic-expression 190 (concat 191 ;; 192 ;; For C 193 ;; 194 ;; > Special case to match a line like `main() {}' 195 ;; > e.g. no return type, not even on the previous line. 196 ;; Pick a token by (match-string 1) 197 (car (cdr (nth 1 cc-imenu-c++-generic-expression))) ; -> index += 2 198 (prog2 (setq cc-imenu-objc-generic-expression-noreturn-index 1) "") 199 "\\|" 200 ;; > General function name regexp 201 ;; Pick a token by (match-string 3) 202 (car (cdr (nth 2 cc-imenu-c++-generic-expression))) ; -> index += 5 203 (prog2 (setq cc-imenu-objc-generic-expression-general-func-index 3) "") 204 ;; > Special case for definitions using phony prototype macros like: 205 ;; > `int main _PROTO( (int argc,char *argv[]) )'. 206 ;; Pick a token by (match-string 8) 207 (if cc-imenu-c-prototype-macro-regexp 208 (concat 209 "\\|" 210 (car (cdr (nth 3 cc-imenu-c++-generic-expression))) ; -> index += 1 211 (prog2 (setq cc-imenu-objc-generic-expression-objc-base-index 9) "") 212 ) 213 (prog2 (setq cc-imenu-objc-generic-expression-objc-base-index 8) "") 214 "") ; -> index += 0 215 (prog2 (setq cc-imenu-objc-generic-expression-proto-index 8) "") 216 ;; 217 ;; For Objective-C 218 ;; Pick a token by (match-string 8 or 9) 219 ;; 220 "\\|\\(" 221 "^[-+][:" c-alnum "()*_<>\n\t ]*[;{]" ; Methods 222 "\\|" 223 "^@interface[\t ]+[" c-alnum "_]+[\t ]*:" 224 "\\|" 225 "^@interface[\t ]+[" c-alnum "_]+[\t ]*([" c-alnum "_]+)" 226 "\\|" 227 ;; For NSObject, NSProxy and Object... They don't have super class. 228 "^@interface[\t ]+[" c-alnum "_]+[\t ]*.*$" 229 "\\|" 230 "^@implementation[\t ]+[" c-alnum "_]+[\t ]*([" c-alnum "_]+)" 231 "\\|" 232 "^@implementation[\t ]+[" c-alnum "_]+" 233 "\\|" 234 "^@protocol[\t ]+[" c-alnum "_]+" "\\)") 235 "Imenu generic expression for ObjC mode. See `imenu-generic-expression'.") 236 237 238;; Imenu support for objective-c uses functions. 239(defsubst cc-imenu-objc-method-to-selector (method) 240 "Return the objc selector style string of METHOD. 241Example: 242- perform: (SEL)aSelector withObject: object1 withObject: object2; /* METHOD */ 243=> 244-perform:withObject:withObject:withObject: /* selector */" 245 (let ((return "") ; String to be returned 246 (p 0) ; Current scanning position in METHOD 247 (pmax (length method)) ; 248 char ; Current scanning target 249 (betweenparen 0) ; CHAR is in parentheses. 250 argreq ; An argument is required. 251 inargvar) ; position of CHAR is in an argument variable. 252 (while (< p pmax) 253 (setq char (aref method p) 254 p (1+ p)) 255 (cond 256 ;; Is CHAR part of a objc token? 257 ((and (not inargvar) ; Ignore if CHAR is part of an argument variable. 258 (eq 0 betweenparen) ; Ignore if CHAR is in parentheses. 259 (or (and (<= ?a char) (<= char ?z)) 260 (and (<= ?A char) (<= char ?Z)) 261 (and (<= ?0 char) (<= char ?9)) 262 (= ?_ char))) 263 (if argreq 264 (setq inargvar t 265 argreq nil) 266 (setq return (concat return (char-to-string char))))) 267 ;; Or a white space? 268 ((and inargvar (or (eq ?\ char) (eq ?\n char)) 269 (setq inargvar nil))) 270 ;; Or a method separator? 271 ;; If a method separator, the next token will be an argument variable. 272 ((eq ?: char) 273 (setq argreq t 274 return (concat return (char-to-string char)))) 275 ;; Or an open parentheses? 276 ((eq ?\( char) 277 (setq betweenparen (1+ betweenparen))) 278 ;; Or a close parentheses? 279 ((eq ?\) char) 280 (setq betweenparen (1- betweenparen))))) 281 return)) 282 283(defun cc-imenu-objc-remove-white-space (str) 284 "Remove all spaces and tabs from STR." 285 (let ((return "") 286 (p 0) 287 (max (length str)) 288 char) 289 (while (< p max) 290 (setq char (aref str p)) 291 (setq p (1+ p)) 292 (if (or (= char ?\ ) (= char ?\t)) 293 () 294 (setq return (concat return (char-to-string char))))) 295 return)) 296 297(defun cc-imenu-objc-function () 298 "imenu supports for objc-mode." 299 (let (methodlist 300 clist 301 ;; 302 ;; OBJC, Cnoreturn, Cgeneralfunc, Cproto are constants. 303 ;; 304 ;; *Warning for developers* 305 ;; These constants depend on `cc-imenu-c++-generic-expression'. 306 ;; 307 (OBJC cc-imenu-objc-generic-expression-objc-base-index) 308 ;; Special case to match a line like `main() {}' 309 (Cnoreturn cc-imenu-objc-generic-expression-noreturn-index) 310 ;; General function name regexp 311 (Cgeneralfunc cc-imenu-objc-generic-expression-general-func-index) 312 ;; Special case for definitions using phony prototype macros like: 313 (Cproto cc-imenu-objc-generic-expression-proto-index) 314 langnum 315 ;; 316 (classcount 0) 317 toplist 318 stupid 319 str 320 str2 321 (intflen (length "@interface")) 322 (implen (length "@implementation")) 323 (prtlen (length "@protocol")) 324 (func 325 ;; 326 ;; Does this emacs has buffer-substring-no-properties? 327 ;; 328 (if (fboundp 'buffer-substring-no-properties) 329 'buffer-substring-no-properties 330 'buffer-substring))) 331 (goto-char (point-max)) 332 (imenu-progress-message stupid 0) 333 ;; 334 (while (re-search-backward cc-imenu-objc-generic-expression nil t) 335 (imenu-progress-message stupid) 336 (setq langnum (if (match-beginning OBJC) 337 OBJC 338 (cond 339 ((match-beginning Cproto) Cproto) 340 ((match-beginning Cgeneralfunc) Cgeneralfunc) 341 ((match-beginning Cnoreturn) Cnoreturn)))) 342 (setq str (funcall func (match-beginning langnum) (match-end langnum))) 343 ;; 344 (cond 345 ;; 346 ;; C 347 ;; 348 ((not (eq langnum OBJC)) 349 (setq clist (cons (cons str (match-beginning langnum)) clist))) 350 ;; 351 ;; ObjC 352 ;; 353 ;; An instance Method 354 ((eq (aref str 0) ?-) 355 (setq str (concat "-" (cc-imenu-objc-method-to-selector str))) 356 (setq methodlist (cons (cons str 357 (match-beginning langnum)) 358 methodlist))) 359 ;; A factory Method 360 ((eq (aref str 0) ?+) 361 (setq str (concat "+" (cc-imenu-objc-method-to-selector str))) 362 (setq methodlist (cons (cons str 363 (match-beginning langnum)) 364 methodlist))) 365 ;; Interface or implementation or protocol 366 ((eq (aref str 0) ?@) 367 (setq classcount (1+ classcount)) 368 (cond 369 ((and (> (length str) implen) 370 (string= (substring str 0 implen) "@implementation")) 371 (setq str (substring str implen) 372 str2 "@implementation")) 373 ((string= (substring str 0 intflen) "@interface") 374 (setq str (substring str intflen) 375 str2 "@interface")) 376 ((string= (substring str 0 prtlen) "@protocol") 377 (setq str (substring str prtlen) 378 str2 "@protocol"))) 379 (setq str (cc-imenu-objc-remove-white-space str)) 380 (setq methodlist (cons (cons str2 381 (match-beginning langnum)) 382 methodlist)) 383 (setq toplist (cons nil (cons (cons str 384 methodlist) toplist)) 385 methodlist nil)))) 386 ;; 387 (imenu-progress-message stupid 100) 388 (if (eq (car toplist) nil) 389 (setq toplist (cdr toplist))) 390 391 ;; In this buffer, there is only one or zero @{interface|implementation|protocol}. 392 (if (< classcount 2) 393 (let ((classname (car (car toplist))) 394 (p (cdr (car (cdr (car toplist))))) 395 last) 396 (setq toplist (cons (cons classname p) (cdr (cdr (car toplist))))) 397 ;; Add C lang token 398 (if clist 399 (progn 400 (setq last toplist) 401 (while (cdr last) 402 (setq last (cdr last))) 403 (setcdr last clist)))) 404 ;; Add C lang tokens as a sub menu 405 (if clist 406 (setq toplist (cons (cons "C" clist) toplist)))) 407 ;; 408 toplist 409 )) 410 411;(defvar cc-imenu-pike-generic-expression 412; ()) 413; FIXME: Please contribute one! 414 415(defun cc-imenu-init (mode-generic-expression 416 &optional mode-create-index-function) 417 (setq imenu-generic-expression mode-generic-expression 418 imenu-case-fold-search nil) 419 (when mode-create-index-function 420 (setq imenu-create-index-function mode-create-index-function))) 421 422 423(cc-provide 'cc-menus) 424 425;;; arch-tag: f6b60933-91f0-4145-ab44-70ca6d1b919b 426;;; cc-menus.el ends here 427