4 ;; SUMMARY: C++ OO-Browser class and member functions.
5 ;; USAGE: GNU Emacs Lisp Library
6 ;; KEYWORDS: c, oop, tools
11 ;; ORIG-DATE: 03-Oct-90
12 ;; LAST-MOD: 10-May-01 at 03:02:42 by Bob Weiner
14 ;; Copyright (C) 1990-1999 BeOpen.com
15 ;; See the file BR-COPY for license information.
17 ;; This file is part of the OO-Browser.
22 ;;; ************************************************************************
23 ;;; Other required Elisp libraries
24 ;;; ************************************************************************
28 ;;; ************************************************************************
30 ;;; ************************************************************************
32 (defvar c++-cpp-include-dirs '("/usr/include/")
33 "*Ordered list of include directories by default searched by C preprocessor.
34 Each directory must end with a directory separator. See also
37 (defvar c++-include-dirs nil
38 "*Ordered list of directories to search for C++ include files.
39 Each directory must end with a directory separator. Directories normally
40 searched by the C++ pre-processor should be set instead in
41 `c++-cpp-include-dirs'.")
43 ;; Modified on 3/28/95 to handle C++ names with multiple template
44 ;; parameters, e.g. class<T1,T2,T3>. Unfortunately for our pattern matcher,
45 ;; we also have to allow spaces within the template parameters section. We
46 ;; consciously do not allow newlines within the parameters section to avoid
47 ;; grabbing too much of the expression that follows.
48 (defconst c++-return-type-identifier
49 (concat "[\[_\<a-zA-Z]"
50 "[\]" c++-template-identifier-chars "]*"
51 "[ \t\n\r]*\\(::[ \t\n\r]*[\]" c++-template-identifier-chars "]+\\)?"
52 "[ \t\n\r]*\<[" c++-return-type-chars " ,]+\>[ \t\n\r]*[*&]*"
53 "\\|[\[_\<a-zA-Z][\]" c++-return-type-chars "]*"
54 "\\([ \t\n\r]*::[ \t\n\r]*[\[\<a-zA-Z][\]" c++-return-type-chars "]+\\)?"
57 (defconst c++-type-identifier
58 (concat "\\([ \t\n\r]*::\\|[\[_\<a-zA-Z][\]"
59 c++-template-identifier-chars "]*"
60 "[ \t\n\r]*\<[^\>\;{}]+\>[ \t\n\r]*[*&]*[ \t\n\r]*::"
61 "\\|[\[_\<a-zA-Z][\]" c++-identifier-chars
62 "]*[ \t\n\r]*[*&]*[ \t\n\r]*::\\)"))
64 (defconst c++-type-tag-separator "@"
65 "String that separates a tag's type from its normalized definition form.
66 This should be a single character which is unchanged when quoted for use as a
67 literal in a regular expression.")
69 (defconst c++-tag-fields-regexp
70 ;; The \\\\? below is necessary because we sometimes use this expression to
71 ;; test against a string that has been regexp-quoted and some of the
72 ;; characters in br-feature-type-regexp will then be preceded by \\.
73 (format "^\\([^%s\n]+\\)%s\\\\?\\(%s \\)\\([^%s\n]+\\)%s"
74 c++-type-tag-separator c++-type-tag-separator br-feature-type-regexp
75 c++-type-tag-separator c++-type-tag-separator)
76 "Regexp matching the fields of a C++ feature tag line.
77 Group 1 is the class of the feature. Group 2 is the prefix preceding the
78 feature when displayed within a listing buffer. Group 3 is the feature name.
79 The feature definition signature begins at the end of the regexp match,
80 i.e. (match-end 0), and goes to the end of the string or line.")
82 ;;; ************************************************************************
84 ;;; ************************************************************************
86 (defconst c++-code-file-regexp "\\.\\(cxx\\|[cC][cC]?P?\\)$"
87 "Regular expression matching a unique part of C++ source (non-header) file name and no others.")
89 (defconst c++-include-regexp
90 "[ \t/*]*#[ \t]*include[ \t]+\\([\"\<]\\)\\([^\"\>]+\\)[\"\>]"
91 "Regexp to match to C++ include file lines. File name is grouping 2. Type
92 of include, user-specified via double quote, or system-related starting with
93 `\<' is given by grouping 1.")
95 (defvar c++-tmp-buffer-name (concat br-buffer-prefix-info "Tmp*")
96 "Name of the buffer for short-term OO-Browser scratch work.")
98 (defconst c++-type-def-modifier
99 "\\(auto\\|const\\|inline\\|mutable\\|register\\|static\\|typedef\\|unsigned\\)")
101 (defconst c++-type-modifier-keyword
102 (concat "\\(\\(auto\\|const\\|explicit\\|extern[ \t\n\r]+\"[^\"]+\"\\|"
103 "extern\\|friend\\|inline\\|mutable\\|overload\\|"
104 "register\\|static\\|typedef\\|typename\\|unsigned\\|virtual\\)"
107 (defconst c++-routine-modifier-keyword
109 "\\(\\)" ;; placeholder to align with c++-attribute-modifier-keyword
110 "\\(\\([ \t\n\r]+const\\|[ \t\n\r]+mutable\\|[ \t\n\r]+restrict\\)?"
111 "\\([ \t\n\r]*:[^\;\{]+\\|[ \t\n\r]*=[ \t]*0\\)?\\)"))
113 (defconst c++-type-identifier-group
114 ;; It is critical that the final part of this expression, [*& \t\n\r]+,
115 ;; stay exactly as it is or certain feature definitions may be missed or
116 ;; segmented improperly.
117 ;; If you remove the `*&', "Int &operator=(int j) {}", will not be found
118 ;; because the & will be missed. If you change the `+' to a `*', "main()"
119 ;; will show up as "- n" in listing buffers.
120 (concat "\\(\\(" c++-return-type-identifier "\\)[*& \t\n\r]+\\)"))
122 ;; Final optional expression is to handle new C++ array operators, e.g.
123 ;; void operator delete [] (void*);
124 (defconst c++-operator-identifier "operator[ \t\n\r]*[^ \t\n\r\f:\;.,?~{}]+\\([ \t\n\r]*\\[\\]\\)?"
125 "Regular expression matching a C++ or G++ operator name.")
127 (defconst c++-feature-decl-or-def
128 (concat c++-template-prefix
129 "\\(\\(" c++-type-modifier-keyword "*\\)"
130 c++-type-identifier-group "\\)?"
131 "\\(" c++-type-identifier "[ \t\n\r]*\\)?"
132 "\\(" c++-operator-identifier "\\|" c++-function-identifier "\\|"
133 "[*&]?" c++-identifier "\\)" "[ \t\n\r]*")
134 "Regexp matching the first part of a C++ method declaration or definition.")
136 (defconst c++-attribute-modifier-keyword
138 ;; Allow for array brackets, [...]
139 "\\(\\[[\]\[_:~<>a-zA-Z0-9]*\\][ \t\n\r]*\\)*"
140 "\\(\\([ \t\n\r]+const\\|[ \t\n\r]+mutable\\|[ \t\n\r]+restrict\\)?"
141 "[ \t\n\r]*\\(=[^\;\{]+\\)?\\)"))
143 ;; Empty groupings are for group numbering compatibility with
144 ;; `c++-at-feature-regexp'.
145 (defconst c++-attribute-tag-regexp
146 (concat "^[ \t]*" c++-template-prefix
147 "\\(\\(" c++-type-modifier-keyword "*\\)"
148 c++-type-identifier-group "\\)?"
150 "\\(\\(\\)[*&]?" c++-identifier "\\)"
153 "\\(" c++-attribute-modifier-keyword "?\\)"
154 "\\(\\)" ;; placeholder to align with `c++-comment-regexp' in
155 ;; `c++-at-feature-regexp'
158 (defconst c++-routine-def-terminator-regexp
161 (defconst c++-feature-decl-terminator-regexp
164 (defconst c++-feature-def-terminator-regexp
167 (defconst c++-attribute-decl
168 ;; Must use `c++-feature-def-terminator-regexp' here since need to match to
169 ;; constructs like: enum ENUM_NAME {} ENUM_VAR;
170 (concat c++-attribute-tag-regexp c++-feature-def-terminator-regexp)
171 "Regexp matching a C++ attribute declaration within a class declaration.
172 Member modifier keywords are grouped expression `c++-feature-mod-grpn'.
173 Member type is grouped expression `c++-feature-type-grpn', unless scoping
174 type name, grouped expression `c++-feature-scope-grpn' is non-nil, in which
175 case, grouping `c++-feature-scope-grpn' is the type plus \"::\".
176 Member name is group `c++-feature-name-grpn'. Any text following the
177 attribute name but preceding the terminating semicolon is group
178 `c++-feature-post-args-grpn'. Optional modifier keyword following the arguments
179 is group `c++-feature-post-modifier-grpn'. Group `c++-feature-defaults-grpn'
180 optionally matches the default value of the attribute (including the preceding
183 (defconst c++-feature-mod-grpn 3)
184 (defconst c++-feature-type-grpn 6)
185 (defconst c++-feature-scope-grpn 11)
186 (defconst c++-feature-name-grpn 12)
187 (defconst c++-feature-parens-grpn 16)
188 (defconst c++-feature-post-args-grpn 17)
189 ;; Optional array square brackets is group 18.
190 (defconst c++-feature-post-modifier-grpn 19)
191 (defconst c++-feature-defaults-grpn 20)
193 ;; Match the attribute value including the leading =.
194 (defconst c++-attribute-value-grpn 21)
195 ;; Match the `c++-routine-in-class' or
196 ;; `c++-routine-def-in-class' terminating semicolon, opening brace or
197 ;; = 0 for pure virtual functions.
198 (defconst c++-feature-terminator-grpn 21)
200 (defconst c++-at-feature-regexp
201 (concat c++-feature-decl-or-def
202 ;; This old version of the next line matched to things such as:
203 ;; enum name {};. Since such matches improperly end up in the
204 ;; [function] default class, we only accept matches with () in
206 ;; "[ \t\n\r]*\\(\\[[^\{\;]+\\|([^:\{\;]*)"
207 "\\(\\(([^-+!:{}\;]*)\\|([^-+!(){}\;]*)\\)"
208 c++-routine-modifier-keyword "?\\)"
210 "Regexp matching a C++ method declaration or definition.
211 Member modifier keywords are grouped expression `c++-feature-mod-grpn'.
212 Member type is grouped expression `c++-feature-type-grpn', unless scoping
213 type name, grouped expression `c++-feature-scope-grpn' is non-nil, in which
214 case, grouping `c++-feature-scope-grpn' is the type plus \"::\".
215 Member name is group `c++-feature-name-grpn'. Function argument parentheses,
216 if any, are group `c++-feature-parens-grpn'. All text following the argument
217 parentheses but preceding the opening brace is group
218 `c++-feature-post-args-grpn'. Optional modifier keyword following the arguments
219 is group `c++-feature-post-modifier-grpn'. Group
220 `c++-feature-defaults-grpn' optionally matches one of the three following
222 1. base class constructor defaults (including the preceding colon);
223 2. tail part of a pure virtual function (abstract method) declaration (= 0);
224 3. the default value of an attribute (including the preceding equal sign).")
226 (defconst c++-feature-decl
227 (concat c++-at-feature-regexp c++-feature-decl-terminator-regexp)
228 "See documentation of `c++-at-feature-regexp' for grouping expressions.")
230 (defconst c++-friend-in-class
231 (concat "^[ \t]*friend[ \t\n\r]+" c++-at-feature-regexp c++-feature-def-terminator-regexp)
232 "See documentation of `c++-at-feature-regexp' for grouping expressions.
233 See `c++-friend-regexp' for that.")
235 (defconst c++-friend-class-regexp "^[ \t]*friend[ \t\n\r]+class[ \t\n\r]"
236 "Regexp matching a C++ friend class declaration at the start of a line or the start of a string.")
238 (defconst c++-friend-regexp "^[ \t]*friend[ \t\n\r]"
239 "Regexp matching a C++ friend declaration at the start of a line or the start of a string.")
241 (defconst c++-routine-def
242 (concat "^" c++-at-feature-regexp c++-routine-def-terminator-regexp)
243 "See documentation of `c++-at-feature-regexp' for grouping expressions.")
245 (defconst c++-routine-prefix-in-class
246 (concat "^[ \t]*" c++-feature-decl-or-def
247 "\\(\\(([^:{}\;]*\\|([^(){}\;]*))\\)"
248 "\\([ \t\n\r]+const\\|[ \t\n\r]+mutable\\|[ \t\n\r]+restrict\\)?"
250 "\\(\\(:[^\;\{]+\\)?" c++-comment-regexp))
252 (defconst c++-routine-in-class
253 (concat c++-routine-prefix-in-class
254 "\\([\{\;]\\|=[ \t]*0[ \t]*\;\\)\\)\\)")
255 "See documentation of `c++-at-feature-regexp' for grouping expressions.")
257 (defconst c++-routine-def-in-class
258 (concat c++-routine-prefix-in-class
259 "\\(\{\\|=[ \t]*0[ \t]*\;\\)\\)\\)")
260 "See documentation of `c++-at-feature-regexp' for grouping expressions.")
262 (defconst c++-feature-def
263 (concat "^" c++-at-feature-regexp c++-feature-def-terminator-regexp)
264 "See documentation of `c++-at-feature-regexp' for grouping expressions.")
266 (defconst c++-class-modifier-keyword
267 "\\(\\(friend\\|public\\|protected\\)[ \t\n\r]+\\)")
269 (defconst c++-class-decl
270 (concat c++-class-modifier-keyword "?"
272 c++-class-keyword c++-identifier "[ \t]*[\;,]")
273 "Regexp matching a C++ class declaration.
274 Template match, if any, is grouping `c++-decl-template-grpn'.
275 Class name is grouping `c++-class-name-grpn'.")
277 (defconst c++-decl-template-grpn 3)
278 (defconst c++-class-name-grpn 5)
280 (defconst c++-arg-identifier
281 (concat "[_a-zA-Z][" c++-identifier-chars "]*")
282 "Regular expression matching a C++ or G++ function argument identifier.")
284 (defconst c++-pure-virtual-function-regexp "\)[^=]*=[ \t]*0[ \t]*\;\\'"
285 "Regexp matching the trailing part of a C++ pure virtual function signature.")
287 (defconst c++-c-type-htable
288 (hash-make '(("enum" . "[enumeration]")
289 ("struct" . "[structure]")
290 ("typedef" . "[type]")
291 ("union" . "[union]"))
293 "Hash table of complex C type keywords and associated default class names.")
295 (defconst c-identifier-chars "_a-zA-Z0-9"
296 "String of chars and char ranges that may be used within a standard C++ template identifier.
297 This excludes the template arguments.")
299 (defconst c-identifier
300 (concat "[\[_a-zA-Z]" "[\]" c-identifier-chars "]*"))
302 (defconst c-type-identifier
303 (concat "[\[_a-zA-Z]" "[\]" c-identifier-chars "]*[ \t\n\r]*[*&]*"))
305 (defconst c-type-identifier-group
306 ;; It is critical that the final part of this expression, [*& \t\n\r]+,
307 ;; stay exactly as it is or certain feature definitions may be missed or
308 ;; segmented improperly.
309 ;; If you remove the `*&', "Int &operator=(int j) {}", will not be found
310 ;; because the & will be missed. If you change the `+' to a `*', "main()"
311 ;; will show up as "- n" in listing buffers.
312 (concat "\\(\\(" c-type-identifier "\\)[*& \t\n\r]+\\)"))
314 (defconst c-feature-decl-or-def
315 (concat "\\(\\(" c++-type-modifier-keyword "*\\)"
316 c-type-identifier-group "\\)?"
317 "\\(" c-type-identifier "[ \t\n\r]*\\)?"
318 "[*&]?" c-identifier "[ \t\n\r]*")
319 "Regexp matching the first part of a C feature declaration or definition.")
321 (defconst c-at-function-regexp
322 (concat c-feature-decl-or-def
323 "\\(\\(([^-+!:{}\;]*)\\|([^-+!(){}\;]*)\\)"
324 c++-routine-modifier-keyword "?\\)"
326 "Regexp matching a C function declaration or definition.")
328 (defconst c-function-def-terminator-regexp
331 (defconst c-function-def
332 (concat "^" c-at-function-regexp c-function-def-terminator-regexp))
334 ;;; ************************************************************************
336 ;;; ************************************************************************
338 (defun c++-add-default-classes ()
339 (if br-c-tags-flag (c-add-default-classes)))
341 (defun c++-member-p ()
342 "Prints whether entity at point is a C++ member definition or declaration."
348 "Is " (if (c++-feature-def-p)
350 (br-buffer-substring (match-beginning
351 c++-feature-name-grpn)
353 c++-feature-name-grpn)))
357 "Is " (if (and (c++-skip-to-statement) (c++-feature-decl))
359 (br-buffer-substring (match-beginning
360 c++-feature-name-grpn)
362 c++-feature-name-grpn)))
366 (if name (concat " Name = " name)))))))
368 (defun c++-feature-class-name ()
369 "Return the class name for the function defined at point or nil if none.
370 If point is not within the brace delimited body of the function or class
371 declaration of a member function, then nil is returned."
372 (let* ((opoint (point)))
376 ;; Case 1: Within a method whose definition includes its class name
377 ;; which is also not within a class declaration.
379 (re-search-backward c++-routine-def nil t)
381 ;; Case 2: Within a method whose definition does include a class
382 ;; name and which also is defined within a class declaration.
383 ;; Case 3: Within a function whose definition does not include a class
384 ;; name and which is also not within a class declaration.
385 ;; Case 4: Within a method whose definition does not include a class
386 ;; name but which is defined within a class declaration.
388 (re-search-backward c++-routine-def-in-class nil t))
389 (let ((class (if (match-beginning c++-feature-scope-grpn)
391 (match-beginning c++-feature-scope-grpn)
392 (- (match-end c++-feature-scope-grpn) 2)))))
395 (progn (goto-char (1- (match-end 0)))
396 (if (eq (following-char) ?\{)
398 (progn (forward-list)
399 (if (> (point) opoint)
400 (c++-normalize-template-arguments
401 (br-delete-space class))))
404 (c++-normalize-template-arguments
405 (c++-get-class-name-from-source))))))))
407 (defun c++-feature-implementors (name)
408 "Return unsorted list of C++ feature tags which implement feature NAME.
409 This includes classes which define the interface for NAME as a pure virtual
411 (c++-feature-matches (concat "^" (regexp-quote name) "$")))
413 (defun c++-feature-edit-declaration (class-and-feature)
414 "Edit in the other window (or the OO-Browser viewer window) the declaration source for CLASS-AND-FEATURE or for the listing entry at point.
416 If point is within the signature of a feature definition within a source code
417 buffer and a nil value for CLASS-AND-FEATURE is given, the feature's
418 declaration is displayed for editing.
420 With a prefix argument or outside of an OO-Browser listing buffer, prompt
421 with completion for CLASS-AND-FEATURE. Point is left in the viewer window.
422 Signal an error if the declaration is not found."
423 (interactive (list (if (or current-prefix-arg (not (br-browser-buffer-p)))
424 (let ((default (br-feature-default))
426 (br-feature-complete 'must-match
427 "Edit feature declaration:")))
428 (if (and (equal default class-and-feature)
429 (save-excursion (c++-feature-def-p)))
430 ;; feature definitions are handled specially
432 class-and-feature)))))
433 (c++-feature-view-declaration class-and-feature t))
435 (defun c++-feature-view-declaration (&optional class-and-feature edit-flag)
436 "View in the other window (or OO-Browser viewer window) the declaration source for optional CLASS-AND-FEATURE or for the listing entry at point.
438 If point is within the signature of a feature definition within a source code
439 buffer and a nil value for CLASS-AND-FEATURE is given, the feature's
440 declaration is displayed for viewing..
442 With a prefix argument or outside of an OO-Browser listing buffer, prompt
443 with completion for CLASS-AND-FEATURE.
445 Point is left in the original window unless the optional second argument
446 EDIT-FLAG is non-nil. Signal an error if the declaration is not found."
447 (interactive (list (if (or current-prefix-arg (not (br-browser-buffer-p)))
448 (let ((default (br-feature-default))
450 (br-feature-complete 'must-match
451 "View feature declaration:")))
452 (if (and (equal default class-and-feature)
453 (save-excursion (c++-feature-def-p)))
454 ;; feature definitions are handled specially
459 ;; Pseudo-code (may be out dated):
460 ;; Move to class def of given feature or feature at point.
461 ;; Use the sig associated with feature listing to compute
462 ;; a regexp that matches to its declaration or definition
464 ;; Search forward for a match.
465 ;; If no match, then go to the first entry with the same name
468 (let ((oo-browser-listing (and (br-browser-buffer-p) (br-listing-window-p)))
471 (cond (class-and-feature)
472 ;; If on an OO-Browser feature listing entry or within C++ source
473 ;; code on a feature definition signature, then leave
474 ;; class-and-feature as nil for now.
475 ((or (and oo-browser-listing (br-at-feature-p))
476 (save-excursion (c++-feature-def-p))))
477 ;; Otherwise, look for a default value around point.
478 (t (setq class-and-feature (br-feature-default))))
480 (setq ftr-class (and (stringp class-and-feature)
481 (not (string-match "::" class-and-feature))
486 (and (not class-and-feature)
488 (not (br-at-feature-p))))
489 ;; Assume is a class entry to display.
490 (or (br-view nil edit-flag ftr-class)
491 (error "(OO-Browser): `%s' declaration not found"
494 ;; Show definitions of [default class] features rather than giving an
495 ;; error since a user may invoke this command on them thinking he can
497 ((and oo-browser-listing
498 (stringp class-and-feature) (eq (aref class-and-feature 0) ?\[))
502 ;; Above calls will either signal an error or return t or nil
503 ;; depending on whether the entry definition was found.
504 (message "(OO-Browser): found definition of `%s'"
507 (t (let ((owind (selected-window))
508 (oframe (selected-frame))
509 (wconfig (current-window-configuration))
514 (case-fold-search) ;; case-sensitive matching
515 class-end match ftr-sig)
517 (if (and (null class-and-feature)
520 (setq ftr-tag (br-feature-get-tag)
521 ftr-sig (and ftr-tag (br-feature-tag-signature ftr-tag)))
523 ((save-excursion (c++-feature-def-p))
524 ;; Within a feature definition signature
525 (setq ftr-sig (buffer-substring
526 (match-beginning 0) (match-end 0)))
528 (setq class-and-feature (br-feature-signature-to-name ftr-sig t)
529 match (string-match "::" class-and-feature)
530 ftr-class (if match (substring
531 class-and-feature 0 match))
532 ftr-name (if match (substring class-and-feature (match-end 0))
535 (if (stringp class-and-feature)
536 (setq match (string-match "::" class-and-feature)
537 ftr-class (if match (substring class-and-feature 0 match)
539 ftr-name (if match (substring class-and-feature (match-end 0))
541 ftr-tag (car (br-feature-tag-and-file class-and-feature))))
542 (setq ftr-tag (or ftr-tag (br-feature-get-tag))
543 ftr-class (or ftr-class (and ftr-tag
544 (br-feature-tag-class ftr-tag)))
545 ftr-name (or ftr-name (and ftr-tag
546 (br-feature-tag-name ftr-tag)))
547 ftr-sig (and ftr-tag (br-feature-tag-signature ftr-tag))
548 class-and-feature (or class-and-feature
549 (and ftr-class ftr-name
550 (concat ftr-class "::" ftr-name)))))
553 (cond ((and (not ftr-sig) ftr-class ftr-name)
554 (cond ((not (br-class-defined-p ftr-class))
556 (format "(OO-Browser): %s's class `%s' not defined within the Environment"
557 ftr-name ftr-class)))
558 ;; Try as a method and then as an attribute since
559 ;; it is not in the tags table.
560 ((or (c++-feature-method-display ftr-class ftr-name
562 (c++-feature-attribute-display ftr-class ftr-name
565 "(OO-Browser): found declaration of `%s'"
568 "(OO-Browser): `%s' declaration not found"
569 class-and-feature)))))
571 ((not (and ftr-sig ftr-class ftr-name))
573 "(OO-Browser): `%s' not declared within the Environment"
576 (t (if (br-in-browser) (br-to-view-window))
577 (setq viewer-obuf (current-buffer))
578 (if (and (br-find-class ftr-class nil)
579 (search-forward "\{" nil t)
582 ;; Move to class close brace but ignore
583 ;; any error if braces are unbalanced.
584 ;; Let the compiler tell the user about
587 (progn (forward-sexp)
588 (setq class-end (point)))
590 (let ((case-fold-search)) ;; case-sensitive matching
594 (c++-feature-declaration-regexp
596 (if (re-search-forward ftr-regexp class-end t)
597 (progn (br-display-code
600 "(OO-Browser): found declaration of `%s'"
602 ;; Try a simpler match without args
605 (c++-feature-declaration-regexp
607 (if (re-search-forward ftr-regexp class-end t)
608 (progn (br-display-code
610 (message "(OO-Browser): Matched declaration by name only; failed to match arguments"))
612 (format "(OO-Browser): `%s' declaration not found"
613 class-and-feature)))))
616 (setq buffer-read-only
619 buffer-file-name))))))
621 "(OO-Browser): %s's class `%s' not defined within the Environment"
622 ftr-name ftr-class)))))
626 (if (not edit-flag) (select-window owind))
627 (if (eq (selected-frame) oframe)
628 (set-window-configuration wconfig))
631 ;; Kill previous viewer buffer if unmodified and
632 ;; `br-keep-viewed-classes' is nil.
633 (if (and (buffer-live-p viewer-obuf)
634 (not (eq (current-buffer) viewer-obuf)))
636 (set-buffer viewer-obuf)
637 (if (and (not br-keep-viewed-classes) buffer-read-only
638 (null (buffer-modified-p)))
639 (kill-buffer viewer-obuf))))
640 (if (not edit-flag) (select-window owind)))))))))
642 (defun c++-feature-locate-p (feature-tag &optional regexp-flag)
643 "Leave point at the start of FEATURE-TAG's definition in the current buffer.
644 Assume caller has moved point to the beginning of the buffer or to the point
645 of desired search start.
646 Optional REGEXP-FLAG means FEATURE-TAG is a regular expression."
647 ;; Match to function definitions, not declarations, except for pure virtual
648 ;; functions and friends which are declared, not defined, and so end with a
650 (let ((found t) (start) (case-fold-search)
651 feature-sig feature-regexp class)
652 (if (br-feature-tag-p feature-tag)
653 (setq feature-sig (br-feature-tag-signature feature-tag)
654 class (br-feature-tag-class feature-tag))
655 (setq feature-sig feature-tag
658 (if (stringp feature-tag)
659 (setq feature-regexp feature-tag)
660 (error "(c++-feature-locate-p): Not a regexp, %s" feature-tag)))
662 ;; First move to the proper class implementation if feature-sig does not
663 ;; include a <class>:: part and this is not a [default-class], so that if
664 ;; two classes in the same file have the same feature signature, we still
665 ;; end up at the right one.
667 (if (or (string-match "\\`\\[" class)
668 (and feature-sig (string-match "::" feature-sig)))
670 (setq found (re-search-forward
671 (c++-class-definition-regexp class nil) nil t))))
672 ((string-match c++-tag-fields-regexp feature-sig)
673 (setq class (substring feature-sig
674 (match-beginning 1) (match-end 1))
675 feature-sig (substring feature-sig (match-end 0)))
676 (if (or (and regexp-flag
677 (not (string-match "\\`\\\\\\[\\|::" feature-regexp)))
679 (string-match "\\`\\[\\|::" feature-tag))))
682 (c++-class-definition-regexp class regexp-flag)
685 ;; If class was searched for and not found, return nil.
688 ;; Otherwise, look for feature expression.
690 (or regexp-flag (setq feature-regexp
691 (c++-feature-signature-to-regexp feature-sig nil)))
692 (while (and (or (re-search-forward feature-regexp nil t)
693 (and (not regexp-flag)
694 ;; Allow for comments between parameters.
696 (c++-feature-signature-to-regexp feature-sig t)
698 (setq start (match-beginning 0))
699 (not (setq found (not
700 (if (c-within-comment-p)
701 (progn (search-forward "*/" nil t)
705 (message "(OO-Browser): found definition of `%s'"
706 (c++-feature-signature-to-name feature-sig t nil))
707 (br-display-code start))))))
709 (defun c++-feature-name-to-regexp (name)
710 "Converts feature NAME into a regular expression matching the feature's name tag."
711 (concat "\\<" (c++-feature-signature-to-regexp name) "\\>"))
713 (defun c++-feature-args-regexp (func-args)
716 (obuf (current-buffer))
717 (tmp-buf (get-buffer-create c++-tmp-buffer-name)))
718 (or tmp-buf (error "(OO-Browser): (c++-feature-args-regexp) - Can't create tmp-buf"))
720 (setq buffer-read-only nil)
722 ;; Fill tmp-buffer with all func-args, including parens.
723 (insert (br-regexp-quote func-args))
725 (goto-char (point-min))
726 (if (looking-at "(\\s-*)")
727 (replace-match "(\\s-*)" t t)
729 ;; Replace all "\( +" with "\(" temporarily
730 (br-buffer-replace "\\(^\\|[^\\]\\)\([ \t\n\r]+" "\\1\(")
732 ;; Replace all "+ \)" with "\)" temporarily
733 (br-buffer-replace "[ \t\n\r]+\)" "\)")
735 ;; Replace all "...\)" with "@@@" temporarily
736 (br-buffer-replace "\\\\\\.\\\\\\.\\\\\\.\)" "@@@")
738 ;; If an arg consists of 2 or more words and does not end with [*&>],
739 ;; replace the last word with <identifier>.
740 ;; Do this in two steps to avoid paren conflict with future replaces.
742 "\\([\(,][^=,\)]*[^ \t\n\r=,\)]+[ \t\n\r\\*&]+\\)[^ \t\n\r*&<>=,\)]+\\([ \t\n\r]*[,=\)]\\)"
745 ;; If an arg consists of only 1 word and does not end with [*&>], add an
746 ;; <identifier> following it.
747 ;; Do this in two steps to avoid paren conflict with future replaces.
749 "\\([\(,][ \t\n\r]*\\)\\([^ \t\n\r*&<>=,\)]+\\)\\([ \t\n\r]*[,=\)]\\)"
752 ;; If an arg ends with [*&>], add an <identifier> following it.
753 ;; Do this in two steps to avoid paren conflict with future replaces.
755 "\\([\(,][ \t\n\r]*\\)\\([^=,\)]+\\([\\]*[*&>]+\\)+\\)\\([ \t\n\r]*[,=\)]\\)"
758 ;; Optionalize right hand side of argument defaults.
759 ;; Do this after literal variable names have been changed to regexps or
760 ;; variable names preceding the parentheses that this inserts will not
761 ;; be changed to regexps.
762 (br-buffer-replace "\\([^=,\( \t\n\r]+\\)\\([ \t\n\r]*=[^,\)]+\\)"
765 ;; Replace all " *, *" with "<comment>,<comment>"
766 (br-buffer-replace "[ \t\n\r]*,[ \t\n\r]*" (concat comment "," comment))
768 ;; Replace all " +" with "<spc>"
769 (br-buffer-replace "[ \t\n\r]+" space)
771 ;; Replace all "\(" with "\(<comment>"
772 (br-buffer-replace "\\(^\\|[^\\]\\)\(" (concat "\\1\(" comment))
774 ;; Replace all "\)" with "<comment>\)"
775 (br-buffer-replace "\\([^\\]\\)\)" (concat "\\1" comment "\)"))
777 ;; Replace all & and quoted \\* with "<spc>[*&]+<spc>"
778 (br-buffer-replace "\\(\\(&\\|\\\\\\*\\)+\\)" (concat space "\\1" space))
780 ;; Replace all "<spc>" with "[ \t\n\r]*"
781 (br-buffer-replace space "[ \t\n\r]*" t)
783 ;; Replace all "<comment>" with a comment regexp
784 (br-buffer-replace comment c++-comment-regexp t)
786 ;; Replace all "@@@" with any # of args
787 (br-buffer-replace "@@@" "[^\)]*\)" t)
789 (br-buffer-replace "###" (concat "\\\\(" c++-arg-identifier
790 "\\\\)?\\\\([ \t\n\r]*=[^,\)]+\\\\)?"))
793 ;; Return final buffer as a string.
794 (prog1 (buffer-substring (point-min) (point-max))
795 (set-buffer-modified-p nil)
798 (defun c++-feature-signature-to-name (feature-sig-or-tag &optional with-class for-display)
799 "Extracts the feature name from FEATURE-SIG-OR-TAG.
800 The feature's class name is dropped from FEATURE-SIG-OR-TAG unless optional
801 WITH-CLASS is non-nil. If optional FOR-DISPLAY is non-nil, a feature type
802 character is prepended to the name for display in a browser listing."
803 (if (br-feature-tag-p feature-sig-or-tag)
804 (br-feature-tag-name feature-sig-or-tag with-class for-display)
808 ((string-match c++-tag-fields-regexp feature-sig-or-tag)
809 (setq name (substring feature-sig-or-tag
810 (match-beginning (if for-display 2 3))
814 (substring feature-sig-or-tag
815 (match-beginning 1) (match-end 1))
817 ;; Remove any trailing whitespace.
818 (br-delete-space name))
820 ((or (string-match c++-at-feature-regexp feature-sig-or-tag)
821 (string-match c++-attribute-tag-regexp feature-sig-or-tag))
822 (setq name (substring feature-sig-or-tag
823 (match-beginning c++-feature-name-grpn)
824 (match-end c++-feature-name-grpn)))
826 (if (match-beginning c++-feature-scope-grpn)
828 (substring feature-sig-or-tag
829 (match-beginning c++-feature-scope-grpn)
830 (match-end c++-feature-scope-grpn))
832 (if (br-class-in-table-p name)
834 (setq name (concat name "::" name)))))
835 (if for-display (c++-feature-add-prefix
836 name "" feature-sig-or-tag) name))
839 (t;; Remove any trailing whitespace and add display prefix.
840 (setq name (br-delete-space feature-sig-or-tag))
841 (if (and with-class (br-class-in-table-p name))
843 (setq name (concat name "::" name)))
844 (if for-display (c++-feature-add-prefix
845 name "" feature-sig-or-tag) name))))))
847 (defun c++-feature-signature-to-regexp (signature &optional comments-flag)
848 "Given a C++ SIGNATURE, return regexp used to match to its definition."
849 (setq signature (br-regexp-quote signature))
850 (let ((prefix-info) (class))
851 (if (string-match c++-tag-fields-regexp signature)
852 (setq prefix-info (substring signature (match-beginning 0) (match-end 0))
853 class (substring signature (match-beginning 1) (match-end 1))
854 signature (substring signature (match-end 0))))
855 ;; Add () to [function] tags whose signatures need them.
856 (if (and (equal class "[function]")
857 (not (string-match "\(" signature)))
858 (setq signature (concat signature " ( )")))
859 (if (string-match "[^<>*& \t]+\\(\<[^\>]+\>\\)[ \t\n\r]*::" signature)
860 ;; Method from a template class. Match to a method with the same
861 ;; number of template parameters, regardless of parameter names.
862 (let ((pre (substring signature 0 (match-beginning 1)))
863 (mid (substring signature (match-beginning 1) (match-end 1)))
864 (post (substring signature (match-end 1))))
865 (setq signature (concat pre (c++-template-args-regexp mid) post))))
868 (c++-feature-signature-commented-regexp signature))
869 (concat prefix-info (c++-feature-signature-whitespace-regexp
872 (defun c++-feature-signature-commented-regexp (signature-regexp)
875 (obuf (current-buffer))
876 (tmp-buf (get-buffer-create c++-tmp-buffer-name)))
877 (or tmp-buf (error "(OO-Browser): (c++-feature-args-regexp) - Can't create tmp-buf"))
879 (setq buffer-read-only nil)
881 ;; Fill tmp-buffer with all of signature-regexp.
882 (insert signature-regexp)
884 (goto-char (point-min))
886 ;; Replace all " *, *" with "<comment>,<comment>"
887 ;; Avoid commas separating template parameters which have already
888 ;; been substituted for with "[^,<>]+".
889 (br-buffer-replace "\\([^^,]\\)[ \t\n\r]*,[ \t\n\r]*"
890 (concat "\\1" comment "," comment))
892 ;; Replace all "\(" with "<comment>\(<comment>"
893 (br-buffer-replace "\\(^\\|[^\\]\\)\(" (concat "\\1" comment "\(" comment))
895 ;; Replace all "\)" with "<comment>\)<comment>"
896 (br-buffer-replace "\\([^\\]\\)\)" (concat "\\1" comment "\)" comment))
898 ;; Replace all " +" with "<spc>"
899 (br-buffer-replace "[ \t\n\r]+" space)
901 ;; Replace any "<comment><comment>" with one "<comment>"
902 (br-buffer-replace (concat comment comment) comment t)
904 ;; Replace all "<comment>" with a comment regexp
905 (br-buffer-replace (concat "\\(" space "\\)?" comment
907 c++-comment-regexp t)
909 ;; Replace all "<spc>" with "[ \t\n\r]*"
910 (br-buffer-replace space "[ \t\n\r]*" t)
912 ;; Return final buffer as a string.
913 (prog1 (buffer-substring (point-min) (point-max))
914 (set-buffer-modified-p nil)
917 (defun c++-feature-signature-whitespace-regexp (signature-regexp)
918 (let* ((obuf (current-buffer))
919 (tmp-buf (get-buffer-create c++-tmp-buffer-name)))
920 (or tmp-buf (error "(OO-Browser): (c++-feature-args-regexp) - Can't create tmp-buf"))
922 (setq buffer-read-only nil)
924 ;; Fill tmp-buffer with all of signature-regexp.
925 (insert signature-regexp)
926 (goto-char (point-min))
927 (br-buffer-replace "[ \t\n\r]+" "[ \t\n\r]*" t)
928 ;; Return final buffer as a string.
929 (prog1 (buffer-substring (point-min) (point-max))
930 (set-buffer-modified-p nil)
933 (defun c++-feature-to-end ()
934 ;; Move point to precede feature opening brace or declaration semicolon.
936 (if (eq (following-char) ?\{)
938 ;; Move to end of feature but ignore any error if braces are
939 ;; unbalanced. Let the compiler tell the user about this.
943 (defun c++-scan-features ()
944 "Return reverse ordered list of C++ routine definitions in current buffer.
945 Assume point is at the beginning of widened buffer and that all comments have
946 been removed by the caller.
947 This processes only those routines defined outside of the declaration of a
948 class; see `c++-scan-features-in-class' for the code that processes routines
949 and attributes defined within class declarations. It doesn't process global
950 variables since those are handled by separate code that deals with C constructs."
952 (c-remove-functions) ;; Prevent any mis-scans within C function bodies.
953 (let ((routines) class type name rout)
954 (while (re-search-forward c++-routine-def nil t)
956 name (br-buffer-substring
957 (match-beginning c++-feature-name-grpn)
958 (match-end c++-feature-name-grpn))
959 type (if (match-beginning c++-feature-type-grpn)
961 (match-beginning c++-feature-type-grpn)
962 (match-end c++-feature-type-grpn))
965 ;; This code is very subtle but it does the right thing so don't
966 ;; change it unless you know exactly what you are doing.
967 (if (not (match-beginning c++-feature-scope-grpn))
968 ;; This is a non-class function since we did not find a ::
970 ;; (setq class "[function]")
971 ;; Ignore global functions since these are found by a call to the
974 (setq rout (br-buffer-substring (match-beginning 0) (match-end 0)))
976 ;; Is a member function, but this may set class = "" since prior
977 ;; regexp grouping may have grabbed the type. Be careful to
979 (setq class (br-delete-space
981 (match-beginning c++-feature-scope-grpn)
982 (- (match-end c++-feature-scope-grpn) 2))))
983 (if (string-equal class "")
987 ;; Ignore matches to class constructs and ::function references.
988 (if (or (string-equal class "")
989 (string-match c++-class-name-before rout))
991 (setq rout (c++-feature-normalize rout class name)
992 routines (cons rout routines)))))
995 (defun c++-to-definition (&optional other-win)
996 "Jumps to the definition of a selected C++ construct.
997 With OTHER-WIN non-nil, show it in another window.
999 It assumes that its caller has already checked that the key was pressed in an
1000 appropriate buffer and has moved the cursor to the selected buffer.
1003 (1) on a `#include' statement, the include file is displayed;
1004 Look for include file in directory lists `smart-c-cpp-include-dirs'
1005 and `smart-c-include-dirs'.
1006 (2) within a method definition before the opening brace, its declaration is
1008 (3) within a method declaration, its definition is displayed;
1009 (4) on a class name, the class definition is shown;
1010 (5) on a member reference (past any :: scoping operator), the member
1011 definition or a listing of possible definitions or a matching
1012 declaration (if no definitions exist within the Environment) is shown;
1013 (6) on a global variable or function identifier, its definition is shown.
1015 (2-5) require that an OO-Browser Environment has been loaded with
1016 the {M-x br-env-load RET} command."
1018 (let ((obuf (current-buffer))
1021 ((c++-include-file other-win))
1022 ((c++-feature other-win))
1023 ((and (goto-char opoint)
1024 ;; If point is after a :: scoping operator or in front of a method
1025 ;; call opening paren, then don't treat it as a class or search
1026 ;; backward for the class name preceding ::.
1028 (skip-chars-forward "^\(\):\;,.?{}")
1029 (not (looking-at "\(")))
1030 (br-check-for-class (c++-find-class-name) other-win)))
1031 ((br-check-for-class (save-excursion (c++-class-decl-p)) other-win))
1032 ;; Look it up as a member reference.
1033 ((and (goto-char opoint) (c++-feature-reference-definition)))
1034 ;; Look it up as a regular tag to find global variable and function definitions.
1038 (smart-c++-tag))))))
1040 ;;; ************************************************************************
1041 ;;; Private functions
1042 ;;; ************************************************************************
1044 (defun c++-class-decl-p ()
1045 "Return nil unless point is within a class declaration, referenced by another
1046 class. Commented declarations also return nil. When value is non-nil, it is
1047 the class name from the declaration. Leave point at start of statement for
1049 (c++-skip-to-statement)
1052 (and (looking-at c++-class-decl)
1053 (setq class (buffer-substring
1054 (match-beginning c++-class-name-grpn)
1055 (match-end c++-class-name-grpn)))
1056 (if (match-beginning c++-decl-template-grpn)
1059 class (buffer-substring
1060 (match-beginning c++-decl-template-grpn)
1061 (match-end c++-decl-template-grpn))
1064 (not (c-within-comment-p))
1065 (progn (beginning-of-line)
1066 (not (looking-at "[ \t]*//")))
1069 (defun c++-feature (&optional other-win)
1070 "Move point to the definition/declaration of a method given by the declaration/definition at point.
1071 This will immediately return nil if point is not within the signature, prior
1072 to any arguments and any brace-delimited body."
1074 (let ((feature-def) (ftr) (class) (ftr-pat)
1076 (c++-skip-to-statement)
1077 (if (and (= (point) (save-excursion (back-to-indentation) (point)))
1078 (not (c-within-comment-p))
1079 (save-excursion (beginning-of-line)
1080 (not (looking-at "[ \t]*//")))
1081 (not (looking-at c++-class-decl))
1082 (looking-at (concat c++-at-feature-regexp "[\{\;,]")))
1083 (cond ((c++-feature-def-p)
1084 ;; Within a feature definition
1085 (if (c++-get-class-name-from-source)
1086 ;; Definition is within a class, so it serves as its own
1089 (message "(OO-Browser): Method declaration/definition is one and the same.")
1092 (progn (c++-feature-edit-declaration nil)
1094 ((c++-view-friend other-win t))
1095 ;; Now look for feature definition in code (non-header) files.
1096 ((progn (setq feature-def (c++-feature-def-pat)
1097 ftr (car (cdr (cdr feature-def)))
1098 class (car (cdr feature-def))
1099 ftr-pat (car feature-def))
1100 (c++-locate-feature ftr class ftr-pat other-win)))
1101 ((progn (goto-char opoint)
1102 ;; Only match to declarations if within a class
1103 ;; declaration. Otherwise, unqualified method calls will
1104 ;; improperly match as declarations, assuming non-ANSI C
1105 ;; code may be used, e.g. method ();.
1106 (if (c++-get-class-name-from-source)
1108 (and (c++-skip-to-statement)
1109 (c++-feature-decl)))))
1111 (message "(OO-Browser): `%s' feature definition not found" ftr)
1116 (defun c++-feature-add-prefix (feature-name class signature &optional friend-flag)
1117 "Add a browser listing display prefix to FEATURE-NAME from CLASS based on feature's SIGNATURE."
1119 ;; friend declaration
1121 ;; pure virtual function (abstract method)
1122 ((string-match c++-pure-virtual-function-regexp signature)
1125 ((or (memq (aref signature (1- (length signature))) '(?\; ?=))
1126 (and (not (string-match "\(" signature))
1127 ;; Don't match to complex C types like enumerations.
1128 (not (br-default-class-p class))))
1129 (if (string-match "\\<static\\>" signature)
1130 "& " ;; attribute shared by all instances
1131 ;; regular attribute
1133 ;; constructor or destructor
1134 ((or (eq ?~ (aref feature-name 0))
1135 (equal feature-name (c++-class-non-template-name class))
1136 (br-member feature-name
1137 '("operator new" "operator delete")))
1140 ;; Type declaration: enum, struct, union or typedef
1141 ((and (string-match "\\`\\(struct\\|enum\\|union\\|typedef\\) " signature)
1142 (not (string-match "\(" signature)))
1145 ;; Don't use the next clause since method declarations may contain
1146 ;; a `static' when the definition does not and method declarations
1148 ;; ((string-match "\\<static\\>" signature) "1 ")
1154 (defun c++-feature-at-reference-p ()
1155 "Return C++ member reference name that point is within, else nil.
1156 The return value is a list of:
1157 \(variable member-reference-prefix class-name scoping-operator member-name method-flag)
1158 where member-reference-prefix if non-nil is either \".\" or \"->\",
1159 scoping-operator if non-nil is \"::\" and class-name may also be nil.
1160 Method-flag is non-nil if this is a method reference."
1161 (let* ((identifier-chars "_:~<>a-zA-Z0-9")
1163 (concat "\\(\\([_a-zA-Z][" identifier-chars "]*\\)"
1164 ;; Allow for array references
1165 "\\(\\s-*\\[[\]\[" identifier-chars "]*\\]\\)?\\)?"
1166 ;; Match to . or -> and after
1167 "\\(\\(\\(\\.\\|->\\)[_~:\<a-zA-Z][" identifier-chars "]*\\)?"
1168 "\\([ \t]*\\([^\]\) \t:\;.,?~{}]\\)[^\[\( \t:\;.,~^!|?{}]?[=*]?\\)?\\)"))
1169 variable op-identifier identifier class-name method-flag)
1171 (skip-chars-backward identifier-chars)
1172 (skip-chars-backward "-.>")
1173 ;; Move back over any array [] indexes
1174 (while (not (zerop (skip-chars-backward "\]")))
1175 (skip-chars-backward identifier-chars)
1176 (skip-chars-backward " \["))
1177 ;; Skip back over variable name itself
1178 (skip-chars-backward identifier-chars)
1179 (if (looking-at member-ref-regexp)
1180 ;; Don't flash button here since it was already flashed before
1182 (progn (setq variable
1183 (if (match-beginning 2)
1184 (buffer-substring (match-beginning 2) (match-end 2)))
1186 (buffer-substring (match-beginning 4) (match-end 4))
1187 identifier (if (match-beginning 5)
1189 (match-beginning 5) (match-end 5)))
1190 method-flag (if (match-beginning 8)
1191 (equal "\(" (buffer-substring
1194 (if (and variable (not identifier))
1195 ;; e.g. unqualified_method();
1196 (setq identifier variable
1198 ;; Have to allow for identifiers such as, `operator () (int, int)'
1199 ;; yet not include the opening parenthesis in `min ()'.
1200 (if (string-match "\\<operator\\>" op-identifier)
1201 (setq identifier op-identifier))
1204 "\\`\\(\\.\\|->\\)?\\([_<>a-zA-Z0-9]+[ \t\n\r]*::\\|[ \t\n\r]*::\\)?\\(.+\\)\\'"
1207 ;; name of variable to which reference refers,
1208 ;; this is nil if a more complicated expression is the
1211 ;; . or -> variable-based reference
1212 (if (match-beginning 1)
1213 (substring identifier (match-beginning 1) (match-end 1)))
1215 (or (and (match-beginning 2)
1216 (> (length (setq class-name
1217 (substring identifier
1219 (- (match-end 2) 2))))
1222 (c++-normalize-template-arguments class-name)))
1224 (save-match-data (c++-feature-variable-class
1226 ;; scoping operator, ::
1227 (if (match-beginning 2) "::")
1229 (if (match-beginning 3)
1230 (substring identifier (match-beginning 3) (match-end 3)))
1231 ;; t if this is a method and not an attribute reference
1234 (defun c++-feature-attribute-display (class-name member-name reference-name message-flag)
1235 "Display CLASS-NAME's MEMBER-NAME attribute derived from REFERENCE-NAME.
1236 MESSAGE-FLAG non-nil means display messages explaining whether the attribute was
1237 found or not. Return t if found and nil otherwise."
1238 (if (br-edit nil class-name)
1239 (let ((case-fold-search)) ;; case-sensitive matching
1241 (if (save-excursion (c++-feature-to-variable-declaration member-name))
1242 (progn (br-display-code (match-beginning 5))
1245 "(OO-Browser): `%s' declaration found within class `%s'"
1246 member-name class-name))
1249 (progn (message "(OO-Browser): `%s' not declared within class `%s'"
1250 member-name class-name)
1255 "(OO-Browser): %s's class `%s' not defined within the Environment"
1256 reference-name member-name class-name)
1260 (defun c++-feature-decl ()
1261 (and (not (looking-at
1262 "\\(if\\|else if\\|else\\|for\\|while\\|switch\\)\\s-*\("))
1263 (not (looking-at c++-class-decl))
1264 (looking-at c++-feature-decl)))
1266 (defun c++-feature-declaration-regexp (def-sig &optional args-flag)
1267 "Return a regular expression that matches to the declaration of DEF-SIG.
1268 If DEF-SIG is not a valid C++ declaration or definition, return nil.
1269 Optional ARGS-FLAG non-nil means include argument matches in the regexp to
1270 handle overloading."
1271 (and (not (string-match "\\<\\(if\\|else if\\|else\\|for\\|while\\|switch\\)\\s-*\("
1273 (string-match c++-at-feature-regexp def-sig)
1274 ;; Don't regexp-quote member-name yet.
1275 (let* ((member-name (substring def-sig
1276 ;; Work around regexp bug that can drop
1277 ;; leading [*&] char when there is no
1278 ;; class:: preceding member-name.
1279 (if (and (match-end c++-feature-type-grpn)
1280 (= (match-end c++-feature-type-grpn)
1281 (1- (match-beginning
1282 c++-feature-name-grpn))))
1283 (match-end c++-feature-type-grpn)
1284 (match-beginning c++-feature-name-grpn))
1285 (match-end c++-feature-name-grpn)))
1286 (member-modifiers (if (match-end c++-feature-mod-grpn)
1290 (match-beginning c++-feature-mod-grpn)
1291 (match-end c++-feature-mod-grpn)))))
1292 ;; Don't regexp-quote member-type yet.
1293 (member-type (and (match-end c++-feature-type-grpn)
1294 ;; member-type must be followed by whitespace
1295 ;; or end with a [*&] character or we don't
1299 c++-feature-type-grpn)))
1300 '(?\ ?\n ?\t ?\r ?* ?&))
1301 ;; Handle possible regexp bugs
1303 (match-beginning c++-feature-type-grpn)
1304 (match-beginning c++-feature-name-grpn)))
1307 (match-beginning c++-feature-type-grpn)
1308 (match-end c++-feature-type-grpn))))
1309 (func-args (if (and args-flag (match-end c++-feature-parens-grpn))
1310 (br-feature-delete-c-comments
1313 (match-beginning c++-feature-parens-grpn)
1314 (match-end c++-feature-parens-grpn)))))
1317 ;; Eliminate any leading or trailing whitespace in some matches.
1318 (and member-type (string-match "[ \t\n\r]+\\'" member-type)
1319 (setq member-type (substring member-type 0
1320 (match-beginning 0))))
1321 (and member-name (string-match "\\`[ \t\n\r]+" member-name)
1322 (setq member-name (substring member-name (match-end 0))))
1324 ;; Move any [*&] preceding member-name to member-type.
1325 (if (string-match "\\`[*&]+" member-name)
1326 (setq member-type (concat member-type
1327 (substring member-name 0
1329 member-name (substring member-name (match-end 0))))
1331 (setq member-type (br-regexp-quote member-type))
1333 ;; Allow for different whitespace between declaration and definition
1334 ;; when * or & is part of name and/or type, e.g. "char* id" and "char
1336 (if (and (stringp member-type)
1337 (string-match "[\\*&]+\\'" member-type))
1339 (concat (substring member-type 0 (match-beginning 0))
1340 "[ \t\n\r]*" (substring member-type
1341 (match-beginning 0)))))
1342 ;; Allow for trailing whitespace.
1343 (and (stringp member-type)
1344 (not (string-equal member-type ""))
1345 (setq member-type (concat member-type "[ \t\n\r]*")))
1350 "\\(\\(auto\\|inline\\|overload\\|static\\|virtual\\)[ \t\n\r]+\\)?"
1351 (if member-modifiers
1352 (let ((def-mods "") (mod))
1353 (while (string-match "\\([a-z]+\\)[ \t\n\r]+"
1355 (setq mod (substring member-modifiers
1358 member-modifiers (substring member-modifiers
1361 (setq friend (string-equal mod "friend")))
1362 (if (equal (string-match
1363 c++-type-def-modifier mod) 0)
1364 (setq def-mods (concat def-mods "\\(" mod
1365 "[ \t\n\r]+\\)?"))))
1367 (if (and member-type (equal (string-match "virtual" member-type) 0))
1369 (br-regexp-quote member-name)
1371 (if func-args (c++-feature-args-regexp func-args))))))
1373 (defun c++-feature-def-p ()
1374 "Return nil unless point is within the first line of the signature of a member definition or pure virtual function.
1375 The definition must be the first thing on the line and must not be commented
1376 and point must be prior to any arguments or nil is returned. Leaves point at
1377 the start of the definition for visual clarity if t is returned."
1378 (let ((opoint (point)))
1379 (c++-skip-to-statement)
1380 (if (and (= (point) (save-excursion (back-to-indentation) (point)))
1381 (not (c-within-comment-p))
1382 (save-excursion (beginning-of-line)
1383 (not (looking-at "[ \t]*//")))
1384 (not (looking-at c++-class-decl))
1386 "\\(if\\|else if\\|else\\|for\\|while\\|switch\\)\\s-*\("))
1387 (looking-at (concat c++-at-feature-regexp "[\{\;,]"))
1389 (or (eq ?\{ (setq end-punct (char-after (1- (match-end 0)))))
1390 ;; If ends with a `[;,]' then must not have func parens
1391 ;; nor simply be a scoped name in order to be a def.
1392 ;; If it begins with `virtual', ends with "= 0" and has
1393 ;; parens, then is a deferred virtual function declaration.
1394 (if (match-end c++-feature-parens-grpn)
1396 (narrow-to-region (match-beginning 0) (match-end 0))
1398 "\\s *\\<virtual\\>[^\;{}]+=[ \t]*0[ \t]*[,\;]")
1399 (progn (message "(OO-Browser): Pure virtual function, definition deferred to descendants")
1401 (or (null (match-end c++-feature-scope-grpn))
1404 (match-beginning c++-feature-scope-grpn)
1405 (match-end c++-feature-name-grpn))
1406 (char-to-string end-punct))
1407 (buffer-substring (match-beginning 0)
1408 (match-end 0)))))))))
1413 (defun c++-feature-def-pat ()
1414 "Return (list <feature-def-pat> <feature-class> <feature-name>) associated with declaration at point.
1415 A call of: (funcall <feature-def-pat> <feature-class>) will generate a regexp
1416 which will match to the signature component of the feature's OO-Browser tag entry."
1417 (and (c++-skip-to-statement)
1419 ;; Don't regexp-quote member-name yet.
1420 (let* ((member-name (buffer-substring
1421 ;; Work around regexp bug that can drop
1422 ;; leading [*&] char when there is no class::
1423 ;; preceding member-name.
1424 (if (and (match-end c++-feature-type-grpn)
1425 (= (match-end c++-feature-type-grpn)
1426 (1- (match-beginning
1427 c++-feature-name-grpn))))
1428 (match-end c++-feature-type-grpn)
1429 (match-beginning c++-feature-name-grpn))
1430 (match-end c++-feature-name-grpn)))
1431 (member-modifiers (if (match-end c++-feature-mod-grpn)
1432 (br-quote-match c++-feature-mod-grpn)))
1433 (class (if (match-end c++-feature-scope-grpn)
1435 (match-beginning c++-feature-scope-grpn)
1436 (- (match-end c++-feature-scope-grpn) 2))))
1437 (scoped-name (match-end c++-feature-scope-grpn))
1438 ;; Don't regexp-quote member-type yet.
1439 (member-type (and (match-end c++-feature-type-grpn)
1440 ;; Handle possible regexp bug
1443 (match-beginning c++-feature-type-grpn)
1444 (match-beginning c++-feature-name-grpn)))
1446 (match-beginning c++-feature-type-grpn)
1447 (match-end c++-feature-type-grpn))))
1448 (func-args (if (match-end c++-feature-parens-grpn)
1449 (br-feature-delete-c-comments
1451 (match-beginning c++-feature-parens-grpn)
1452 (match-end c++-feature-parens-grpn)))))
1456 (if (equal class "") (setq class nil))
1458 ;; Eliminate any leading or trailing whitespace in some matches.
1459 (and member-type (string-match "[ \t]+$" member-type)
1460 (setq member-type (substring member-type 0
1461 (match-beginning 0))))
1462 (and member-name (string-match "^[ \t]+" member-name)
1463 (setq member-name (substring member-name (match-end 0))))
1465 ;; Set class if need be.
1471 (string-match c++-identifier member-type))
1472 (if class (setq class (substring
1475 ;; Class name is not part of declaration
1476 ;; nor a `friend' declaration, so look
1477 ;; for declaration within a class
1478 ;; definition and locate the class name.
1479 ;; If not within a class, assume
1480 ;; declaration is global.
1481 (t (setq class (c++-get-class-name-from-source))))
1483 ;; Move any [*&] preceding member-name to member-type.
1484 (if (string-match "^[*&]+" member-name)
1485 (setq member-type (concat member-type
1486 (substring member-name 0
1488 member-name (substring member-name (match-end 0))))
1490 (setq member-type (br-regexp-quote member-type))
1492 ;; Allow for different whitespace between declaration and definition
1493 ;; when * or & is part of name and/or type, e.g. "char* id" and "char
1495 (if (and (stringp member-type)
1496 (string-match "[ \t\n\r]*\\([\\*&]+\\)\\'" member-type))
1498 (concat (substring member-type 0 (match-beginning 0))
1499 "[ \t\n\r]*" (substring member-type
1500 (match-beginning 1)))))
1501 ;; Allow for trailing whitespace.
1502 (and (stringp member-type)
1503 (not (string-equal member-type ""))
1504 (setq member-type (concat member-type "[ \t\n\r]*")))
1506 (let ((pre-member-regexp
1509 "\\(\\(auto\\|inline\\|overload\\|static\\|virtual\\)[ \t\n\r]+\\)?"
1510 (if member-modifiers
1511 (let ((def-mods "") (mod))
1512 (while (string-match "\\([a-z]+\\)[ \t\n\r]+"
1514 (setq mod (substring member-modifiers
1517 member-modifiers (substring member-modifiers
1520 (setq friend (string-equal mod "friend")))
1521 (if (equal (string-match
1522 c++-type-def-modifier mod) 0)
1523 (setq def-mods (concat def-mods "\\(" mod
1524 "[ \t\n\r]+\\)?"))))
1526 (if (and (stringp member-type)
1527 (equal (string-match "virtual" member-type) 0))
1531 ;; Point at beginning of line may imply a non-member func.
1532 (if (or scoped-name (not (bolp))) "[ \t\n\r]*::[ \t\n\r]*")
1533 (br-regexp-quote member-name)
1536 (concat "\\(" (c++-func-args-regexp func-args)
1537 "\\|" (c++-func-args-string func-args)
1539 ;; If is a constructor member function, then can have some
1540 ;; default values for base class constructors after a `:'
1541 ;; but preceding the `{'.
1544 (equal member-name class)
1546 c++-comment-regexp)))
1549 (concat "\\`" (, pre-member-regexp)
1550 (if (not (eq (aref class 0) ?\[))
1551 (br-regexp-quote class))
1552 (, post-member-regexp))))
1553 class member-name)))))
1555 (defun c++-feature-map-tags (function regexp)
1556 "Apply FUNCTION to all current feature tags that match REGEXP and return a list of the results."
1557 (let ((identifier-chars (concat "[" c++-identifier-chars "]*"))
1559 ;; Ensure handle "^" and "$" meta-chars.
1561 (concat (format "\\`%s " br-feature-type-regexp)
1562 (if (equal (substring regexp 0 1) "^")
1563 (progn (setq regexp (substring regexp 1)) nil)
1565 (if (equal (substring regexp -1) "$")
1566 (substring regexp 0 -1)
1567 (concat regexp identifier-chars))
1569 (br-feature-map-tags function regexp)))
1571 (defun c++-feature-matches (regexp)
1572 "Return an unsorted list of feature tags whose names match in part or whole to REGEXP.
1573 ^ and $ characters may be used to match to the beginning and end of a feature name,
1575 (c++-feature-map-tags 'identity regexp))
1577 (defun c++-feature-method-declaration (class-and-method-name)
1578 "Return a regexp matching the declaration of CLASS-AND-METHOD-NAME.
1579 \(The class:: part is optional). Grouping 0 starts the class name if given.
1580 Grouping 1 matches the method name within the declaration."
1582 (if (string-match "::" class-and-method-name)
1583 (setq class (substring class-and-method-name 0 (match-beginning 0))
1584 method (substring class-and-method-name (match-end 0)))
1586 method class-and-method-name))
1588 (format "\\<%s\\s-*::\\s-*\\(\\<%s\\>\\)\\s-*\("
1589 (regexp-quote class) (regexp-quote method))
1590 (format "\\(\\<%s\\>\\)\\s-*\(" (regexp-quote method)))))
1592 (defun c++-feature-method-display (class-name method-name reference-name message-flag)
1593 "Display CLASS-NAME's METHOD-NAME method derived from REFERENCE-NAME.
1594 MESSAGE-FLAG non-nil means display messages explaining whether the attribute was
1595 found or not. Return t if found and nil otherwise."
1596 (if (br-edit nil class-name)
1597 (let ((case-fold-search)) ;; case-sensitive matching
1601 (c++-feature-method-declaration method-name)
1603 (progn (br-display-code (match-beginning 0))
1606 "(OO-Browser): `%s' found within class `%s'"
1607 method-name class-name))
1610 (progn (message "(OO-Browser): `%s' not declared within class `%s'"
1611 method-name class-name)
1616 "(OO-Browser): %s's class `%s' not defined within the Environment"
1617 reference-name method-name class-name)
1621 (defun c++-feature-normalize (feature class name &optional friend-flag)
1622 "Return a feature tag based on FEATURE, CLASS, NAME and optional FRIEND-FLAG."
1623 (setq class (br-delete-space class)
1624 name (c++-feature-add-prefix name class feature friend-flag))
1625 (concat class c++-type-tag-separator
1626 name c++-type-tag-separator
1627 (br-feature-delete-c-comments feature)))
1629 (defun c++-feature-reference-definition ()
1630 "Jumps to the definition of or lists possible definitions of a C++ member reference.
1631 If no definitions are found and there is a . or -> reference prefix, then it
1632 attempts to display the declaration for the reference.
1633 Returns t if a member (non-global) definition or declaration is found,
1634 otherwise returns nil."
1635 (let* ((member-elts (c++-feature-at-reference-p))
1636 (variable (nth 0 member-elts))
1637 (member-reference-prefix (nth 1 member-elts))
1638 (class-name (nth 2 member-elts))
1639 (scoping-operator (nth 3 member-elts))
1640 (member-name (nth 4 member-elts))
1641 (method-flag (nth 5 member-elts))
1646 (if (and member-elts (fboundp 'br-feature-display-implementors))
1649 (message "Looking for `%s'..." member-name)
1652 ;; 1. ::global_function(...) or ::variable
1653 ;; * Ignore, global functions and variables are
1654 ;; handled by another function.
1655 ((and (null class-name) scoping-operator)
1660 ;; 2. class::scoped_method(...) or class::scoped_attribute
1661 ((and class-name scoping-operator)
1662 ;; * Look up scoped_member in class.
1663 ;; * Look up scoped_member in each
1664 ;; ancestor until find a match.
1666 ;; Refine this procedure in the future
1667 ;; by accepting only those methods with the same
1668 ;; number of arguments as the call.
1670 ;; Also refine by looking for declarations through
1671 ;; all ancestors of class if no definitions are
1674 ;; Also refine to handle class::construct->member()
1675 ;; situations where the class is known.
1679 (if (zerop (br-feature-ancestor-implementors
1680 class-name member-name method-flag))
1684 "(OO-Browser): `%s::%s' definition not found"
1685 class-name member-name))
1688 ;; attribute - goto class def and then search for it
1689 (c++-feature-attribute-display
1690 class-name member-name member-name t)))
1693 ;; 3. variable.method(...) or variable.attribute
1694 ;; variable-ptr->method(...) or variable-ptr->attribute
1695 (member-reference-prefix
1697 ;; * Determine the static class of the variable.
1698 ;; If it is declared within the current file:
1699 ;; follow the steps in #2 except list all
1700 ;; ancestral matches rather than just the
1701 ;; first to account for dynamic binding.
1702 ;; Else if no variable type can be determined,
1703 ;; list all known implementors of the method or
1704 ;; display the definition if there is only one
1711 (c++-feature-variable-class
1714 (if (zerop (br-feature-ancestor-implementors
1715 class-name member-name method-flag))
1719 "(OO-Browser): `%s::%s' definition not found"
1720 class-name member-name))
1723 ;; attribute - goto class def and then
1725 (c++-feature-attribute-display
1726 class-name member-name
1727 (concat variable member-reference-prefix
1730 (if (br-feature-display-implementors member-name)
1731 (progn (message "") t)))))
1736 ((and (null class-name) (null scoping-operator))
1738 ;; * Get the class of the method/function
1739 ;; in which the call is made. If this
1740 ;; enclosing context is not a global function,
1741 ;; follow the steps in #3.
1742 ;; * If not found yet, ignore it and it will be
1743 ;; looked up as a global function by another
1746 (if (setq class-name (c++-feature-class-name))
1747 (setq found (not (zerop (br-feature-ancestor-implementors
1748 class-name member-name
1753 (t (setq err "(OO-Browser): (c++-feature-reference-definition) - unrecognized context")
1757 (if (and (not found) member-reference-prefix class-name member-name)
1758 ;; This will signal an error if no declaration is found; return t
1759 ;; in case it does not.
1760 (progn (c++-feature-view-declaration
1761 (concat class-name "::" member-name) t)
1764 (progn (message err) (beep)))
1767 (defun c++-feature-variable-class (variable)
1768 "Search backward from point looking for a type declaration of VARIABLE.
1769 Return the class of the variable which may differ from its type (due to * and & operators)."
1770 ;; Pseudo-variable `this' refers to the current class.
1771 (if (string-equal variable "this")
1772 (c++-feature-class-name)
1775 (while (and (c++-feature-to-item-declaration variable)
1776 (setq class (buffer-substring
1777 (match-beginning 3) (match-end 3)))
1778 (br-member class '("delete" "new")))
1780 (if class (c++-normalize-template-arguments class))))))
1782 (defvar c++-feature-item-regexp1
1783 "\\(^\\|[\;\(]\\)\\s-*\\(\\(%s\\)[*& \t\n\r]+\\)\\([_a-zA-Z][^\;,\(\)]*,\\)*\\s-*\\(\\<%s\\>\\)\\s-*"
1784 "Grouping 2 matches the item's type, possibly with trailing whitespace.
1785 Grouping 3 matches its class (dropping any * or & characters). Grouping 5
1786 matches the item name within the declaration.")
1788 (defvar c++-feature-item-regexp2
1789 "\\(,\\)\\s-*\\(\\(%s\\)[*& \t\n\r]+\\)\\(\\)\\s-*\\(\\<%s\\>\\)\\s-*"
1790 "Grouping 2 matches the item's type, possibly with trailing whitespace.
1791 Grouping 3 matches its class (dropping any * or & characters). Grouping 5
1792 matches the item name within the declaration.")
1794 (defun c++-feature-to-item-declaration (item)
1795 "Search backwards to a match for the declaration of ITEM name and return point or nil if no match.
1796 See the documentation string for `c++-feature-item-regexp' for a description
1797 of matched groupings."
1798 (or (re-search-backward
1799 (format (concat c++-feature-item-regexp1 "[\[\(=\;,*&\)]")
1800 c++-identifier (regexp-quote item)) nil t)
1802 (format (concat c++-feature-item-regexp2 "[\[\(=\;,*&\)]")
1803 c++-identifier (regexp-quote item)) nil t)))
1805 (defun c++-feature-to-variable-declaration (variable)
1806 "Search backwards to a match for the declaration of VARIABLE name and return point or nil if no match.
1807 See the documentation string for `c++-feature-item-regexp' for a description
1808 of matched groupings."
1809 (or (re-search-backward
1810 (format (concat c++-feature-item-regexp1 "[\[=\;,*&\)]")
1811 c++-identifier (regexp-quote variable)) nil t)
1813 (format (concat c++-feature-item-regexp2 "[\[=\;,*&\)]")
1814 c++-identifier (regexp-quote variable)) nil t)))
1816 (defun c++-files-with-source (class)
1817 "Use CLASS to compute set of files that match to a C++ source file regexp.
1819 (let ((file (if class (br-class-path class) buffer-file-name)))
1821 (let* ((src-file-regexp (concat "^" (br-filename-head file)
1822 c++-code-file-regexp))
1823 (dir (file-name-directory file))
1824 (files (directory-files dir nil src-file-regexp)))
1825 (mapcar (function (lambda (f) (expand-file-name f dir)))
1828 (defun c++-find-ancestors-feature (class-list ftr-pat &optional other-win)
1829 "Scan ancestors of CLASS-LIST and show feature definition matching FTR-PAT.
1830 Optional OTHER-WIN means display the result in another window."
1831 ;; If no class, search for non-member function.
1832 (or class-list (setq class-list '(nil)))
1833 (br-feature-display class-list ftr-pat other-win))
1835 (defun c++-find-class-name ()
1836 "Return current word as a potential class name."
1839 (ignore "-\]\[& \t\n\r\;,.\(\){}*")
1840 (pat (concat "^" ignore)))
1842 (skip-chars-backward ignore)
1843 (skip-chars-backward pat)
1844 (setq start (point))
1845 (skip-chars-forward (concat pat ":"))
1846 (buffer-substring start (point)))))
1848 (defun c++-func-args-regexp (func-args)
1849 (let* ((space "%%%")
1850 (obuf (current-buffer))
1851 (tmp-buf (get-buffer-create c++-tmp-buffer-name)))
1852 (or tmp-buf (error "(OO-Browser): (c++-func-args-regexp) - Can't create tmp-buf"))
1853 (set-buffer tmp-buf)
1854 (setq buffer-read-only nil)
1856 ;; Fill tmp-buffer with all func-args, including parens.
1857 (insert (br-regexp-quote func-args))
1859 (goto-char (point-min))
1860 (if (looking-at "(\\s-*)")
1861 (replace-match "(\\s-*)" t t)
1863 ;; Replace all "\( +" with "\(" temporarily
1864 (br-buffer-replace "\\(^\\|[^\\]\\)\([ \t\n\r]+" "\\1\(")
1866 ;; Replace all "+ \)" with "\)" temporarily
1867 (br-buffer-replace "[ \t\n\r]+\)" "\)")
1869 ;; Replace all "...\)" with "@@@" temporarily
1870 (br-buffer-replace "\\\\\\.\\\\\\.\\\\\\.\)" "@@@")
1872 ;; Optionalize right hand side of argument defaults.
1873 (br-buffer-replace "\\([^=,\( \t\n\r]+\\)\\([ \t\n\r]*=[^,\)]+\\)"
1876 "\\\\)? \\\\(\\2\\\\)?"))
1878 ;; Replace all "\)" with "optional <c++-identifier> \)"
1880 ;; Yes, all this complexity really is necessary.
1881 "\\([\\\(,][^=\)]*[^\\=\)]+\\)\\(\\\\*\)\\)"
1882 (concat "\\1\\\\( " c++-arg-identifier
1885 ;; Replace all "," with "optional <c++-identifier>,"
1887 "\\([\(,][^=,]+\\),"
1888 (concat "\\1\\\\( " c++-arg-identifier "\\\\)?,"))
1890 ;; Replace all " *, *" with "<space>,<space>"
1891 (br-buffer-replace "[ \t\n\r]*,[ \t\n\r]*" (concat space "," space))
1893 ;; Replace all " +" with "<spc>"
1894 (br-buffer-replace "[ \t\n\r]+" space)
1896 ;; Replace all "\(" with "\(<space>"
1897 (br-buffer-replace "\\(^\\|[^\\]\\)\(" (concat "\\1\(" space))
1899 ;; Replace all "\)" with "<space>\)"
1900 (br-buffer-replace "\\([^\\]\\)\)" (concat "\\1" space "\)"))
1902 ;; Replace all & and quoted \\* with "<spc>[*&]+<spc>"
1903 (br-buffer-replace "\\(\\(&\\|\\\\\\*\\)+\\)" (concat space "\\1" space))
1905 ;; Replace all "<spc>"
1906 (br-buffer-replace space " *" t)
1908 ;; Replace all "@@@" with any # of args
1909 (br-buffer-replace "@@@" "[^\)]*\)" t)
1912 ;; Return final buffer as a string.
1913 (prog1 (buffer-substring (point-min) (point-max))
1914 (set-buffer-modified-p nil)
1915 (set-buffer obuf))))
1917 (defun c++-func-args-string (func-args)
1918 (let* ((space "%%%")
1919 (obuf (current-buffer))
1920 (tmp-buf (get-buffer-create c++-tmp-buffer-name)))
1921 (or tmp-buf (error "(OO-Browser): (c++-func-args-string) - Can't create tmp-buf"))
1922 (set-buffer tmp-buf)
1923 (setq buffer-read-only nil)
1925 ;; Fill tmp-buffer with all func-args, including parens.
1926 (insert (br-regexp-quote func-args))
1928 (goto-char (point-min))
1929 (if (looking-at "(\\s-*)")
1930 (replace-match "(\\s-*)" t t)
1932 ;; Replace all "\( +" with "\(" temporarily
1933 (br-buffer-replace "\\(^\\|[^\\]\\)\([ \t\n\r]+" "\\1\(")
1935 ;; Replace all "+ \)" with "\)" temporarily
1936 (br-buffer-replace "[ \t\n\r]+\)" "\)")
1938 ;; Replace all "...\)" with "@@@" temporarily
1939 (br-buffer-replace "\\\\\\.\\\\\\.\\\\\\.\)" "@@@")
1941 ;; If an arg consists of 2 or more words and does not end with [*&>],
1942 ;; replace the last word with <identifier>.
1944 "\\([\(,][^=,\)]*[^ \t\n\r=,\)]+[ \t\n\r\\*&]+\\)[^ \t\n\r*&<>=,\)]+\\([ \t\n\r]*[,=\)]\\)"
1945 (concat "\\1" c++-arg-identifier "\\2"))
1947 ;; If an arg consists of only 1 word and does not end with [*&>], add an
1948 ;; <identifier> following it.
1950 "\\([\(,][ \t\n\r]*\\)\\([^ \t\n\r*&<>=,\)]+\\)\\([ \t\n\r]*[,=\)]\\)"
1951 (concat "\\1\\2 " c++-arg-identifier "\\3"))
1953 ;; If an arg ends with [*&>], add an <identifier> following it.
1955 "\\([\(,][ \t\n\r]*\\)\\([^=,\)]+\\([\\]*[*&>]+\\)+\\)\\([ \t\n\r]*[,=\)]\\)"
1956 (concat "\\1\\2 " c++-arg-identifier "\\4"))
1958 ;; Optionalize right hand side of argument defaults.
1959 ;; Do this after literal variable names have been changed to regexps or
1960 ;; variable names preceding the parentheses that this inserts will not
1961 ;; be changed to regexps.
1962 (br-buffer-replace "\\([^=,\( \t\n\r]+\\)\\([ \t\n\r]*=[^,\)]+\\)"
1963 "\\1\\\\(\\2\\\\)?")
1965 ;; Replace all " *, *" with "<space>,<space>"
1966 (br-buffer-replace "[ \t\n\r]*,[ \t\n\r]*" (concat space "," space))
1968 ;; Replace all " +" with "<spc>"
1969 (br-buffer-replace "[ \t\n\r]+" space)
1971 ;; Replace all "\(" with "\(<space>"
1972 (br-buffer-replace "\\(^\\|[^\\]\\)\(" (concat "\\1\(" space))
1974 ;; Replace all "\)" with "<space>\)"
1975 (br-buffer-replace "\\([^\\]\\)\)" (concat "\\1" space "\)"))
1977 ;; Replace all & and quoted \\* with "<spc>[*&]+<spc>"
1978 (br-buffer-replace "\\(\\(&\\|\\\\\\*\\)+\\)" (concat space "\\1" space))
1980 ;; Replace all "<spc>"
1981 (br-buffer-replace space " *" t)
1983 ;; Replace all "@@@" with any # of args
1984 (br-buffer-replace "@@@" "[^\)]*\)" t)
1987 ;; Return final buffer as a string.
1988 (prog1 (buffer-substring (point-min) (point-max))
1989 (set-buffer-modified-p nil)
1990 (set-buffer obuf))))
1992 (defun c++-get-class-name-from-source ()
1993 "Return class name from the class definition that encloses point or nil."
1994 (let ((opoint (point))
1997 (if (re-search-backward c++-class-def-regexp nil t)
1998 (progn (goto-char (match-beginning c++-class-def-derived-grpn))
1999 (setq class (c++-normalize-class-match nil))
2000 ;; Ensure that declaration occurs within class definition.
2002 (progn (forward-list)
2003 (if (> (point) opoint)
2006 (error "(OO-Browser): (c++-get-class-name-from-source) - Mismatched class definition braces"))))))))
2008 (defun c++-output-feature-tags (feature-file feature-tags-list)
2009 "Write C++ FEATURE-FILE's FEATURE-TAGS-LIST into `br-feature-tags-file'.
2010 Assume `br-feature-tags-init' has been called."
2013 (br-feature-set-tags-buffer)
2015 ;; Delete any prior feature tags associated with feature-file.
2017 ;; There may be more than one set of entries for each file name.
2018 (while (search-forward feature-file nil 'end)
2020 (setq start (point))
2021 (search-forward "\^L" nil 'end 2)
2023 (delete-region start (point))))
2024 (if feature-tags-list
2025 (progn (insert "\^L\n")
2026 ;; Quote pathname to avoid read errors on MS OSes.
2027 (prin1 feature-file (current-buffer))
2029 (mapcar (function (lambda (tag) (insert tag "\n")))
2030 feature-tags-list)))))
2032 (defun c++-include-file (&optional other-win)
2033 "If point is on an include file line, try to display file.
2034 Return non-nil iff an include file line, even if file is not found.
2035 Look for include file in `c++-cpp-include-dirs' and in directory list
2036 `c++-include-dirs'."
2037 (let ((opoint (point)))
2039 (if (looking-at c++-include-regexp)
2040 (let ((incl-type (string-to-char
2041 (buffer-substring (match-beginning 1)
2042 (1+ (match-beginning 1)))))
2043 (file (buffer-substring (match-beginning 2) (match-end 2)))
2045 (dir-list c++-include-dirs)
2048 (setq dir-list (if (eq incl-type ?\<)
2049 (append dir-list c++-cpp-include-dirs)
2050 (cons (file-name-directory buffer-file-name)
2053 (setq path (concat (car dir-list) file)
2054 dir-list (if (setq found (file-exists-p path))
2058 ;; If not found in normal include dirs, check all Env paths also.
2061 (let ((paths (delq nil (hash-map 'cdr br-paths-htable))))
2063 (setq path (car paths))
2064 (if (string-equal (file-name-nondirectory path) file)
2065 (setq found t paths nil)
2066 (setq paths (cdr paths))))))
2068 ;; If found, display file
2071 (if (file-readable-p path)
2073 (funcall br-edit-file-function path other-win)
2074 (if (not (fboundp 'br-lang-mode))
2078 (message "(OO-Browser): Include file `%s' unreadable" path))
2080 (message "(OO-Browser): Include file `%s' not found" file))
2085 (defun c++-locate-feature (ftr class ftr-pat &optional other-win)
2086 ;; `class' may = nil, implying non-member function
2087 (or class (setq class "[function]"))
2091 (c++-find-ancestors-feature (list class)
2092 ftr-pat other-win)))
2093 (progn (if (and class (not (equal class def-class)))
2095 "Member `%s' of class `%s' inherited from class `%s'."
2096 ftr class def-class))
2099 (defun c++-scan-ancestors-feature (class-list ftr-pat &optional other-win)
2100 "Display feature definition derived from CLASS-LIST, matching FTR-PAT.
2101 Scan files with same base name as class file."
2102 (let ((classes class-list)
2108 (if (null class-list)
2110 (while (and (not found-ftr) classes)
2111 (setq class (car classes)
2112 code-def-files (c++-files-with-source class)
2113 ftr-sig-regexp (funcall ftr-pat class))
2114 (while (and (setq file (car code-def-files))
2115 (not (setq found-ftr
2116 (br-feature-found-p file ftr-sig-regexp
2118 (setq code-def-files (cdr code-def-files)))
2119 (setq classes (if found-ftr nil (cdr classes))))
2122 (c++-scan-ancestors-feature
2123 (apply 'append (mapcar (function (lambda (cl) (br-get-parents cl)))
2127 (defun c++-scan-features-in-class (class start end)
2128 "Return reverse ordered list of C++ feature (attribute and method) definitions within CLASS declaration.
2129 START and END give buffer region to search.
2130 Assume that all comments have been removed by the caller.
2131 This scans only those features defined within the declaration of a class;
2132 see `c++-scan-features' for the code that processes features defined elsewhere."
2133 (setq class (br-delete-space class))
2136 (narrow-to-region start end)
2138 (let ((features) signature name type type-modifiers)
2140 ;; Get friend routine declarations.
2142 (while (re-search-forward c++-friend-in-class nil t)
2143 (setq start (match-beginning 0)
2144 name (br-buffer-substring
2145 (match-beginning c++-feature-name-grpn)
2146 (match-end c++-feature-name-grpn))
2147 type (if (match-beginning c++-feature-type-grpn)
2148 (br-buffer-substring
2149 (match-beginning c++-feature-type-grpn)
2150 (match-end c++-feature-type-grpn)))
2151 signature (br-buffer-substring (match-beginning 0)
2153 ;; Do this after done getting groupings from the search.
2154 type (if type (br-delete-space type)))
2155 ;; Get rid of this friend so it doesn't slow down later scanning.
2156 (delete-region start (point))
2157 ;; Handle type conversion ops: operator int() { return i; }
2158 (if (equal type "operator") (setq name (concat type " " name)
2160 (setq signature (c++-feature-normalize signature class name t)
2161 features (cons signature features)))
2163 ;; Get method definitions and pure virtual declarations.
2165 (goto-char (point-min))
2166 (while (re-search-forward c++-routine-in-class nil t)
2167 (setq start (match-beginning 0)
2168 name (br-buffer-substring
2169 (match-beginning c++-feature-name-grpn)
2170 (match-end c++-feature-name-grpn))
2171 type (if (match-beginning c++-feature-type-grpn)
2172 (br-buffer-substring
2173 (match-beginning c++-feature-type-grpn)
2174 (match-end c++-feature-type-grpn)))
2175 signature (br-buffer-substring
2176 (match-beginning 0) (match-end 0)))
2177 (if (and (string-equal
2178 "\;" (buffer-substring (match-beginning
2179 c++-feature-terminator-grpn)
2180 (1+ (match-beginning
2181 c++-feature-terminator-grpn))))
2182 (not (string-match c++-pure-virtual-function-regexp signature)))
2183 ;; Routine declaration only, ignore and delete
2184 ;; this declaration so that it doesn't slow down later
2186 (progn (forward-line 1)
2187 (delete-region start (point)))
2188 ;; Do this after all other needed groupings are extracted from the
2189 ;; initial regexp match.
2190 (setq type (if type (br-delete-space type)))
2191 ;; Move point to precede signature opening brace or declaration
2194 (if (eq (following-char) ?\{)
2196 ;; Move to end of feature but ignore any error if braces
2197 ;; are unbalanced. Let the compiler tell the user about
2199 (progn (forward-sexp)
2201 ;; Get rid of this method so it doesn't slow down
2203 (delete-region start (point)))
2205 ;; Handle type conversion ops: operator int() { return i; }
2206 (if (equal type "operator") (setq name (concat type " " name)
2208 (setq signature (c++-feature-normalize signature class name)
2209 features (cons signature features))))
2211 ;; Get attributes and `friend class' declarations.
2213 (goto-char (point-min))
2214 (while (re-search-forward c++-attribute-decl nil t)
2215 (setq start (match-beginning 0)
2216 name (br-buffer-substring
2217 (match-beginning c++-feature-name-grpn)
2218 (match-end c++-feature-name-grpn))
2220 (if (match-beginning c++-feature-mod-grpn)
2221 (br-buffer-substring
2222 (match-beginning c++-feature-mod-grpn)
2223 (match-end c++-feature-mod-grpn)))
2224 type (if (match-beginning c++-feature-type-grpn)
2225 (br-buffer-substring
2226 (match-beginning c++-feature-type-grpn)
2227 (match-end c++-feature-type-grpn)))
2228 signature (br-buffer-substring
2230 (if (match-beginning c++-attribute-value-grpn)
2231 ;; include the = preceding a value
2232 (1+ (match-beginning c++-attribute-value-grpn))
2234 ;; Do this after done getting groupings from the search.
2235 type (if type (br-delete-space type)))
2236 ;; Move point to precede declaration opening brace (enum, struct,
2237 ;; union or typedef) or declaration semicolon.
2239 (if (eq (following-char) ?\{)
2241 ;; Move to end of feature but ignore any error if braces
2242 ;; are unbalanced. Let the compiler tell the user about
2248 "\\(\\`\\|[ \t\n\r]\\)\\(enum\\|struct\\|union\\|typedef\\)\\(\\'\\|[ \t\n\r]\\)"
2250 (if (and type-modifiers
2252 "\\(\\`\\|[ \t\n\r]\\)\\(enum\\|struct\\|union\\|typedef\\)\\(\\'\\|[ \t\n\r]\\)"
2254 (if (equal (substring type-modifiers
2255 (match-beginning 2) (match-end 2))
2257 (progn (setq type "typedef")
2259 ;; This is a type declaration which may be followed
2260 ;; by one or more attribute names of the type. Add
2261 ;; a feature entry for each attribute.
2262 (progn (while (and (not (eq (preceding-char) ?\;))
2264 (concat "\\s-*" c++-identifier "\\s-*[,;]")))
2265 (goto-char (match-end 0))
2266 (if (equal type "typedef")
2268 (cons (c++-feature-normalize
2270 (hash-get type c++-c-type-htable)
2272 (br-buffer-substring
2277 (setq features (cons (c++-feature-normalize
2279 (br-buffer-substring
2283 ;; If the previously found type declaration has its
2284 ;; own name, then add a feature attribute for it.
2285 (if (and type (hash-get type c++-c-type-htable))
2286 (setq signature (c++-feature-normalize
2288 (hash-get type c++-c-type-htable)
2289 (concat class "::" name)
2291 features (cons signature features)))
2293 ;; Ignore false matches to operator= () and the like triggered by
2295 (or (string-match "\\<operator\\>[^=\n\r]*=" signature)
2297 (c++-feature-normalize
2298 signature class name
2300 c++-friend-class-regexp signature) t))
2301 features (cons signature features)))))
2304 (defun c++-skip-to-statement ()
2305 (if (re-search-backward "\\(^\\|[\;{}()]\\)[ \t]*" nil t)
2306 (progn (goto-char (match-end 0))
2307 (skip-chars-forward " \t")
2310 (defun c++-view-friend (&optional other-win sig-at-point-flag)
2311 "With point on a friend listing entry or friend signature (prior to any arguments) in a source code buffer, view its source code definition.
2312 With optional OTHER-WIN non-nil, display in another window.
2313 With optional SIG-AT-POINT-FLAG non-nil, assume point is within a
2314 signature in a source buffer."
2316 (let ((opoint (point))
2318 (if (not sig-at-point-flag)
2319 (br-feature-get-tag)
2320 (c++-skip-to-statement)
2321 ;; Must be the first thing on the line.
2322 (and (= (point) (save-excursion (back-to-indentation) (point)))
2323 (progn (beginning-of-line)
2324 (looking-at c++-friend-regexp))
2325 (looking-at c++-friend-in-class)
2326 (let ((friend (buffer-substring (match-beginning 0)
2328 (class (c++-get-class-name-from-source)))
2329 (c++-feature-normalize
2331 (c++-feature-signature-to-name friend) t))))))
2332 (cond ((or (null tag)
2333 ;; Not a friend entry.
2334 (not (eq ?% (aref (c++-feature-signature-to-name tag nil t) 0))))
2337 ((eq ?\{ (aref tag (1- (length tag))))
2338 ;; Friend is defined where declared.
2339 (br-feature 'view tag)
2341 ((string-match (format " class \\(%s\\) ?;$"
2342 c++-return-type-identifier) tag)
2345 (c++-normalize-template-arguments
2346 (substring tag (match-beginning 1) (match-end 1))))
2349 (if sig-at-point-flag
2350 nil ;; Other feature location code will handle this.
2351 (br-feature t tag) ;; Move point to friend declaration.
2352 (c++-feature other-win))))))
2354 (defun c-remove-functions ()
2355 "Delete any C function definitions from the buffer.
2356 These are handled by the ootags program for the OO-Browser and leaving
2357 them in could cause invalid scans within their bodies. Assume point is at
2358 the beginning of widened buffer and that all comments have been removed by
2359 the caller. This processes only those functions defined outside of class
2362 (goto-char (point-min))
2364 (while (re-search-forward c-function-def nil t)
2365 (delete-region (match-end 0)
2366 (progn (c++-feature-to-end) (point))))
2369 (provide 'br-c++-ft)