;;!emacs ;; ;; FILE: br-c++.el ;; SUMMARY: Support routines for C++ inheritance browsing. ;; USAGE: GNU Emacs Lisp Library ;; KEYWORDS: c, oop, tools ;; ;; AUTHOR: Bob Weiner ;; ORG: BeOpen.com ;; ;; ORIG-DATE: 7-Dec-89 ;; LAST-MOD: 9-Jun-99 at 18:03:29 by Bob Weiner ;; ;; Copyright (C) 1990-1999 BeOpen.com ;; See the file BR-COPY for license information. ;; ;; This file is part of the OO-Browser. ;; ;; DESCRIPTION: ;; DESCRIP-END. ;;; ************************************************************************ ;;; Other required Elisp libraries ;;; ************************************************************************ (mapcar 'require '(br-lib hypb br-c-ft)) ;;; ************************************************************************ ;;; User visible variables ;;; ************************************************************************ (defconst c++-class-name-modifier "\\([_a-zA-Z][_a-zA-Z0-9]*[ \t\n\r]+\\)?" "Regexp for an optional #define keyword preceding the name of a class within a class declaration. Some class libraries use this technique.") (defvar c++-class-keyword (concat "\\(class\\|struct\\|union\\)[ \t\n\r]+" c++-class-name-modifier) "*Keyword regexp preceding a C++ class declaration or definition.") (defvar c++-lib-search-dirs nil "List of directories below which C++ Library source files are found. Subdirectories of Library source are also searched. A Library is a stable group of classes.") (defvar c++-sys-search-dirs nil "List of directories below which C++ System source files are found. Subdirectories of System source are also searched. A System class is one that is not yet reusable and is likely to change before release.") (defconst c++-narrow-view-to-class nil "*Non-nil means narrow buffer to just the matching class definition when displayed.") ;;; ************************************************************************ ;;; Internal functions ;;; ************************************************************************ (defun c++-get-classes-from-source (filename &optional skip-tags skip-tags-cleanup) "Scans FILENAME and returns cons of class list with parents-class alist. Handles multiple inheritance. Assumes file existence and readability have already been checked. With optional SKIP-TAGS non-nil, does not compute and store lookup tags for member definitions. If SKIP-TAGS is nil, normally a cleanup function is called after scanning the members. SKIP-TAGS-CLEANUP non-nil suppresses this action." (let (class-name-end classes class has-parents open-brace-point parents parent-cons signatures) (funcall br-view-file-function filename) (setq buffer-read-only nil) (save-excursion (save-restriction (widen) (br-buffer-delete-c-comments) (goto-char (point-min)) (or skip-tags (progn (setq signatures (c++-scan-features)) (goto-char (point-min)))) (while (re-search-forward c++-class-def-regexp nil t) (setq has-parents (= ?: (char-after (match-beginning c++-class-def-derived-grpn))) class-name-end (match-end c++-class-def-name-grpn) ;; ;; Now since we've saved all the match expressions we need ;; from our last regexp match, we can call functions which ;; change the match data below here. class (c++-normalize-class-match t) parent-cons (cons (if has-parents ;; Return parents as a list. (c++-scan-parents)) class)) (setq classes (cons class classes) parents (cons parent-cons parents)) (or skip-tags ;; Scan members defined within class (progn (goto-char class-name-end) (if (search-forward "\{" nil t) (progn (setq open-brace-point (point)) (backward-char) ;; Move to class close brace but ignore ;; any error if braces are unbalanced. ;; Let the compiler tell the user about ;; this. (if (condition-case () (progn (forward-sexp) t) (error nil)) (setq signatures (append signatures (c++-scan-features-in-class class open-brace-point (point)))))))))))) (if skip-tags nil (c++-output-feature-tags filename signatures) (or skip-tags-cleanup (br-feature-build-htables))) (set-buffer-modified-p nil) (cons classes (delq nil parents)))) (defun c++-class-definition-regexp (class &optional regexp-flag) "Return regexp to uniquely match the definition of CLASS name. Optional REGEXP-FLAG non-nil means CLASS has already been quoted for use in a regular expression." (let ((template-args-regexp (c++-template-args-regexp class))) (concat "^[ \t]*" (if template-args-regexp ;; Only match to a class definition with the same number of ;; template parameters as since some modules use #ifdef ;; to define classes with the same name but a different number ;; of template parameters. (format "\\(template[ \t\n\r]*%s[ \t\n\r]*\\)" template-args-regexp)) c++-class-keyword c++-class-name-modifier (if regexp-flag (c++-class-non-template-name class) (regexp-quote (c++-class-non-template-name class))) c++-class-name-after))) (defun c++-template-args-regexp (class) "Return a regexp matching the number of template args in CLASS or nil when there are no such arguments." (if (string-match "\<[^!]+\>\\'" class) (let* ((param "[^,<>]+") (comma (concat "," param))) (format "<%s%s>" param (mapconcat (function (lambda (c) (if (= c ?\,) comma))) (substring class (1+ (match-beginning 0)) (1- (match-end 0))) ""))))) ;; Remove only *trailing* template identifiers when class name is looked up. (defun c++-class-non-template-name (class) "Return CLASS name sans any trailing