diff lisp/cedet/semantic/db-ebrowse.el @ 104420:2e15afd37998

cedet/semantic/adebug.el, cedet/semantic/chart.el, cedet/semantic/db-debug.el, cedet/semantic/db-ebrowse.el, cedet/semantic/db-el.el, cedet/semantic/db-file.el, cedet/semantic/db-javascript.el, cedet/semantic/db-search.el, cedet/semantic/db-typecache.el, cedet/semantic/dep.el, cedet/semantic/ia.el, cedet/semantic/tag-file.el, cedet/semantic/tag-ls.el: New files.
author Chong Yidong <cyd@stupidchicken.com>
date Sat, 29 Aug 2009 19:32:33 +0000
parents
children 36f56620b2ae
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/cedet/semantic/db-ebrowse.el	Sat Aug 29 19:32:33 2009 +0000
@@ -0,0 +1,706 @@
+;;; db-ebrowse.el --- Semanticdb backend using ebrowse.
+
+;;; Copyright (C) 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+
+;; Authors: Eric M. Ludlam <zappo@gnu.org>, Joakim Verona
+;; Keywords: tags
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+;;
+;; This program was started by Eric Ludlam, and Joakim Verona finished
+;; the implementation by adding searches and fixing bugs.
+;;
+;; Read in custom-created ebrowse BROWSE files into a semanticdb back
+;; end.
+;;
+;; Add these databases to the 'system' search.
+;; Possibly use ebrowse for local parsing too.
+;;
+;; When real details are needed out of the tag system from ebrowse,
+;; we will need to delve into the originating source and parse those
+;; files the usual way.
+;;
+;; COMMANDS:
+;; `semanticdb-create-ebrowse-database' - Call EBROWSE to create a
+;;       system database for some directory.  In general, use this for
+;;       system libraries, such as /usr/include, or include directories
+;;       large software projects.
+;;       Customize `semanticdb-ebrowse-file-match' to make sure the correct
+;;       file extensions are matched.
+;;
+;; `semanticdb-load-ebrowse-caches' - Load all the EBROWSE caches from
+;;       your semanticdb system database directory.  Once they are
+;;       loaded, they become searchable as omnipotent databases for
+;;       all C++ files.  This is called automatically by semantic-load.
+;;       Call it a second time to refresh the Emacs DB with the file.
+;;
+
+(eval-when-compile
+  ;; For generic function searching.
+  (require 'eieio)
+  (require 'eieio-opt)
+  )
+(require 'semantic/db-file)
+
+(eval-and-compile
+  ;; Hopefully, this will allow semanticdb-ebrowse to compile under
+  ;; XEmacs, it just won't run if a user attempts to use it.
+  (condition-case nil
+      (require 'ebrowse)
+    (error nil)))
+
+;;; Code:
+(defvar semanticdb-ebrowse-default-file-name "BROWSE"
+  "The EBROWSE file name used for system caches.")
+
+(defcustom semanticdb-ebrowse-file-match "\\.\\(hh?\\|HH?\\|hpp\\)"
+  "Regular expression matching file names for ebrowse to parse.
+This expression should exclude C++ headers that have no extension.
+By default, include only headers since the semantic use of EBrowse
+is only for searching via semanticdb, and thus only headers would
+be searched."
+  :group 'semanticdb
+  :type 'string)
+
+(defun semanticdb-ebrowse-C-file-p (file)
+  "Is FILE a C or C++ file?"
+  (or (string-match semanticdb-ebrowse-file-match file)
+      (and (string-match "/\\w+$" file)
+	   (not (file-directory-p file))
+	   (let ((tmp (get-buffer-create "*semanticdb-ebrowse-tmp*")))
+	     (save-excursion
+	       (set-buffer tmp)
+	       (condition-case nil
+		   (insert-file-contents file nil 0 100 t)
+		 (error (insert-file-contents file nil nil nil t)))
+	       (goto-char (point-min))
+	       (looking-at "\\s-*/\\(\\*\\|/\\)")
+	       ))
+	   )))
+
+(defun semanticdb-create-ebrowse-database (dir)
+  "Create an EBROSE database for directory DIR.
+The database file is stored in ~/.semanticdb, or whichever directory
+is specified by `semanticdb-default-save-directory'."
+  (interactive "DDirectory: ")
+  (setq dir (file-name-as-directory dir)) ;; for / on end
+  (let* ((savein (semanticdb-ebrowse-file-for-directory dir))
+	 (filebuff (get-buffer-create "*SEMANTICDB EBROWSE TMP*"))
+	 (files (directory-files (expand-file-name dir) t))
+	 (mma auto-mode-alist)
+	 (regexp nil)
+	 )
+    ;; Create the input to the ebrowse command
+    (save-excursion
+      (set-buffer filebuff)
+      (buffer-disable-undo filebuff)
+      (setq default-directory (expand-file-name dir))
+
+      ;;; @TODO - convert to use semanticdb-collect-matching-filenames
+      ;; to get the file names.
+
+
+      (mapcar (lambda (f)
+		(when (semanticdb-ebrowse-C-file-p f)
+		  (insert f)
+		  (insert "\n")))
+	      files)
+      ;; Cleanup the ebrowse output buffer.
+      (save-excursion
+	(set-buffer (get-buffer-create "*EBROWSE OUTPUT*"))
+	(erase-buffer))
+      ;; Call the EBROWSE command.
+      (message "Creating ebrowse file: %s ..." savein)
+      (call-process-region (point-min) (point-max)
+			   "ebrowse" nil "*EBROWSE OUTPUT*" nil
+			   (concat "--output-file=" savein)
+			   "--very-verbose")
+      )
+    ;; Create a short LOADER program for loading in this database.
+    (let* ((lfn (concat savein "-load.el"))
+	   (lf (find-file-noselect lfn)))
+      (save-excursion
+	(set-buffer lf)
+	(erase-buffer)
+	(insert "(semanticdb-ebrowse-load-helper \""
+		(expand-file-name dir)
+		"\")\n")
+	(save-buffer)
+	(kill-buffer (current-buffer)))
+      (message "Creating ebrowse file: %s ... done" savein)
+      ;; Reload that database
+      (load lfn nil t)
+      )))
+
+(defun semanticdb-load-ebrowse-caches ()
+  "Load all semanticdb controlled EBROWSE caches."
+  (interactive)
+  (let ((f (directory-files semanticdb-default-save-directory
+			    t (concat semanticdb-ebrowse-default-file-name "-load.el$") t)))
+    (while f
+      (load (car f) nil t)
+      (setq f (cdr f)))
+    ))
+
+(defun semanticdb-ebrowse-load-helper (directory)
+  "Create the semanticdb database via ebrowse for directory.
+If DIRECTORY is found to be defunct, it won't load the DB, and will
+warn instead."
+  (if (file-directory-p directory)
+      (semanticdb-create-database semanticdb-project-database-ebrowse
+				  directory)
+    (let* ((BF (semanticdb-ebrowse-file-for-directory directory))
+	   (BFL (concat BF "-load.el"))
+	   (BFLB (concat BF "-load.el~")))
+      (save-window-excursion
+	(with-output-to-temp-buffer "*FILES TO DELETE*"
+	  (princ "The following BROWSE files are obsolete.\n\n")
+	  (princ BF)
+	  (princ "\n")
+	  (princ BFL)
+	  (princ "\n")
+	  (when (file-exists-p BFLB)
+	    (princ BFLB)
+	    (princ "\n"))
+	  )
+	(when (y-or-n-p (format
+			 "Warning: Obsolete BROWSE file for: %s\nDelete? "
+			 directory))
+	  (delete-file BF)
+	  (delete-file BFL)
+	  (when (file-exists-p BFLB)
+	    (delete-file BFLB))
+	  )))))
+
+;;; SEMANTIC Database related Code
+;;; Classes:
+(defclass semanticdb-table-ebrowse (semanticdb-table)
+  ((major-mode :initform c++-mode)
+   (ebrowse-tree :initform nil
+		 :initarg :ebrowse-tree
+		 :documentation
+		 "The raw ebrowse tree for this file."
+		 )
+   (global-extract :initform nil
+		   :initarg :global-extract
+		   :documentation
+		   "Table of ebrowse tags specific to this file.
+This table is compisited from the ebrowse *Globals* section.")
+   )
+  "A table for returning search results from ebrowse.")
+
+(defclass semanticdb-project-database-ebrowse
+  (semanticdb-project-database)
+  ((new-table-class :initform semanticdb-table-ebrowse
+		    :type class
+		    :documentation
+		    "New tables created for this database are of this class.")
+   (system-include-p :initform nil
+		     :initarg :system-include
+		     :documentation
+		     "Flag indicating this database represents a system include directory.")
+   (ebrowse-struct :initform nil
+		   :initarg :ebrowse-struct
+		   )
+   )
+  "Semantic Database deriving tags using the EBROWSE tool.
+EBROWSE is a C/C++ parser for use with `ebrowse' Emacs program.")
+
+;JAVE this just instantiates a default empty ebrowse struct?
+; how would new instances wind up here?
+; the ebrowse class isnt singleton, unlike the emacs lisp one
+(defvar-mode-local c++-mode semanticdb-project-system-databases
+  ()
+  "Search Ebrowse for symbols.")
+
+(defmethod semanticdb-needs-refresh-p ((table semanticdb-table-ebrowse))
+  "EBROWSE database do not need to be refreshed.
+
+JAVE: stub for needs-refresh, because, how do we know if BROWSE files
+      are out of date?
+
+EML: Our database should probably remember the timestamp/checksum of
+     the most recently read EBROWSE file, and use that."
+  nil
+)
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+
+
+;;; EBROWSE code
+;;
+;; These routines deal with part of the ebrowse interface.
+(defun semanticdb-ebrowse-file-for-directory (dir)
+  "Return the file name for DIR where the ebrowse BROWSE file is.
+This file should reside in `semanticdb-default-save-directory'."
+  (let* ((semanticdb-default-save-directory
+	  semanticdb-default-save-directory)
+	 (B (semanticdb-file-name-directory
+	     'semanticdb-project-database-file
+	     (concat (expand-file-name dir)
+		     semanticdb-ebrowse-default-file-name)))
+	 )
+    B))
+
+(defun semanticdb-ebrowse-get-ebrowse-structure (dir)
+  "Return the ebrowse structure for directory DIR.
+This assumes semantic manages the BROWSE files, so they are assumed to live
+where semantic cache files live, depending on your settings.
+
+For instance: /home/<username>/.semanticdb/!usr!include!BROWSE"
+  (let* ((B (semanticdb-ebrowse-file-for-directory dir))
+	 (buf (get-buffer-create "*semanticdb ebrowse*")))
+    (message "semanticdb-ebrowse %s" B)
+    (when (file-exists-p B)
+      (set-buffer buf)
+      (buffer-disable-undo buf)
+      (erase-buffer)
+      (insert-file-contents B)
+      (let ((ans nil)
+	    (efcn (symbol-function 'ebrowse-show-progress)))
+	(fset 'ebrowse-show-progress #'(lambda (&rest junk) nil))
+	(unwind-protect ;; Protect against errors w/ ebrowse
+	    (setq ans (list B (ebrowse-read)))
+	  ;; These items must always happen
+	  (erase-buffer)
+	  (fset 'ebrowse-show-fcn efcn)
+	  )
+	ans))))
+
+;;; Methods for creating a database or tables
+;;
+(defmethod semanticdb-create-database :STATIC ((dbeC semanticdb-project-database-ebrowse)
+					       directory)
+  "Create a new semantic database for DIRECTORY based on ebrowse.
+If there is no database for DIRECTORY available, then
+{not implemented yet} create one.  Return nil if that is not possible."
+  ;; MAKE SURE THAT THE FILE LOADED DOESN'T ALREADY EXIST.
+  (let ((dbs semanticdb-database-list)
+	(found nil))
+    (while (and (not found) dbs)
+      (when (semanticdb-project-database-ebrowse-p (car dbs))
+	(when (string= (oref (car dbs) reference-directory) directory)
+	  (setq found (car dbs))))
+      (setq dbs (cdr dbs)))
+    ;;STATIC means DBE cant be used as object, only as a class
+    (let* ((ebrowse-data (semanticdb-ebrowse-get-ebrowse-structure directory))
+	   (dat (car (cdr ebrowse-data)))
+	   (ebd (car dat))
+	   (db nil)
+	   (default-directory directory)
+	   )
+      (if found
+	  (setq db found)
+	(setq db (make-instance
+		  dbeC
+		  directory
+		  :ebrowse-struct ebd
+		  ))
+	(oset db reference-directory directory))
+
+      ;; Once we recycle or make a new DB, refresh the
+      ;; contents from the BROWSE file.
+      (oset db tables nil)
+      ;; only possible after object creation, tables inited to nil.
+      (semanticdb-ebrowse-strip-trees db dat)
+
+      ;; Once our database is loaded, if we are a system DB, we
+      ;; add ourselves to the include list for C++.
+      (semantic-add-system-include directory 'c++-mode)
+      (semantic-add-system-include directory 'c-mode)
+
+      db)))
+
+(defmethod semanticdb-ebrowse-strip-trees  ((dbe semanticdb-project-database-ebrowse)
+						    data)
+  "For the ebrowse database DBE, strip all tables from DATA."
+;JAVE what it actually seems to do is split the original tree in "tables" associated with files
+; im not sure it actually works:
+;   the filename slot sometimes gets to be nil,
+;      apparently for classes which definition cant be found, yet needs to be included in the tree
+;      like library baseclasses
+;   a file can define several classes
+  (let ((T (car (cdr data))));1st comes a header, then the tree
+    (while T
+
+      (let* ((tree (car T))
+	     (class (ebrowse-ts-class tree)); root class of tree
+	     ;; Something funny going on with this file thing...
+             (filename (or (ebrowse-cs-source-file class)
+			   (ebrowse-cs-file class)))
+	     )
+	(cond
+	 ((ebrowse-globals-tree-p tree)
+	  ;; We have the globals tree.. save this special.
+	  (semanticdb-ebrowse-add-globals-to-table dbe tree)
+	  )
+	 (t
+	  ;; ebrowse will collect all the info from multiple files
+	  ;; into one tree.  Semantic wants all the bits to be tied
+	  ;; into different files.  We need to do a full dissociation
+	  ;; into semantic parsable tables.
+	  (semanticdb-ebrowse-add-tree-to-table dbe tree)
+	  ))
+      (setq T (cdr T))))
+    ))
+
+;;; Filename based methods
+;;
+(defun semanticdb-ebrowse-add-globals-to-table (dbe tree)
+  "For database DBE, add the ebrowse TREE into the table."
+  (if (or (not (ebrowse-ts-p tree))
+	  (not (ebrowse-globals-tree-p tree)))
+      (signal 'wrong-type-argument (list 'ebrowse-ts-p tree)))
+
+  (let* ((class (ebrowse-ts-class tree))
+	 (fname (or (ebrowse-cs-source-file class)
+		    (ebrowse-cs-file class)
+		    ;; Not def'd here, assume our current
+		    ;; file
+		    (concat default-directory "/unknown-proxy.hh")))
+	 (vars (ebrowse-ts-member-functions tree))
+	 (fns (ebrowse-ts-member-variables tree))
+	 (toks nil)
+	 )
+    (while vars
+      (let ((nt (semantic-tag (ebrowse-ms-name (car vars))
+			      'variable))
+	    (defpoint (ebrowse-bs-point class)))
+	(when defpoint
+	  (semantic--tag-set-overlay nt
+				     (vector defpoint defpoint)))
+	(setq toks (cons nt toks)))
+      (setq vars (cdr vars)))
+    (while fns
+      (let ((nt (semantic-tag (ebrowse-ms-name (car fns))
+			      'function))
+	    (defpoint (ebrowse-bs-point class)))
+	(when defpoint
+	  (semantic--tag-set-overlay nt
+				     (vector defpoint defpoint)))
+	(setq toks (cons nt toks)))
+      (setq fns (cdr fns)))
+
+    ))
+
+(defun semanticdb-ebrowse-add-tree-to-table (dbe tree &optional fname baseclasses)
+  "For database DBE, add the ebrowse TREE into the table for FNAME.
+Optional argument BASECLASSES specifyies a baseclass to the tree being provided."
+  (if (not (ebrowse-ts-p tree))
+      (signal 'wrong-type-argument (list 'ebrowse-ts-p tree)))
+
+  ;; Strategy overview:
+  ;; 1) Calculate the filename for this tree.
+  ;; 2) Find a matching namespace in TAB, or create a new one.
+  ;; 3) Fabricate a tag proxy for CLASS
+  ;; 4) Add it to the namespace
+  ;; 5) Add subclasses
+
+  ;; 1 - Find the filename
+  (if (not fname)
+      (setq fname (or (ebrowse-cs-source-file (ebrowse-ts-class tree))
+		      (ebrowse-cs-file (ebrowse-ts-class tree))
+		      ;; Not def'd here, assume our current
+		      ;; file
+		      (concat default-directory "/unknown-proxy.hh"))))
+
+  (let* ((tab (or (semanticdb-file-table dbe fname)
+		  (semanticdb-create-table dbe fname)))
+	 (class (ebrowse-ts-class tree))
+	 (scope (ebrowse-cs-scope class))
+	 (ns (when scope (cedet-split-string scope ":" t)))
+	 (nst nil)
+	 (cls nil)
+	 )
+
+    ;; 2 - Get the namespace tag
+    (when ns
+      (let ((taglst (if (slot-boundp tab 'tags) (oref tab tags) nil)))
+	(setq nst (semantic-find-first-tag-by-name (car ns) taglst))
+	(when (not nst)
+	  (setq nst (semantic-tag (car ns) 'type :type "namespace"))
+	  (oset tab tags (cons nst taglst))
+	  )))
+
+    ;; 3 - Create a proxy tg.
+    (setq cls (semantic-tag (ebrowse-cs-name class)
+			    'type
+			    :type "class"
+			    :superclasses baseclasses
+			    :faux t
+			    :filename fname
+			    ))
+    (let ((defpoint (ebrowse-bs-point class)))
+      (when defpoint
+	(semantic--tag-set-overlay cls
+				   (vector defpoint defpoint))))
+
+    ;; 4 - add to namespace
+    (if nst
+	(semantic-tag-put-attribute
+	 nst :members (cons cls (semantic-tag-get-attribute nst :members)))
+      (oset tab tags (cons cls (when (slot-boundp tab 'tags)
+				 (oref tab tags)))))
+
+    ;; 5 - Subclasses
+    (let* ((subclass (ebrowse-ts-subclasses tree))
+	   (pname (ebrowse-cs-name class)))
+      (when (ebrowse-cs-scope class)
+	(setq pname (concat (mapconcat (lambda (a) a) (cdr ns) "::") "::" pname)))
+
+      (while subclass
+	(let* ((scc (ebrowse-ts-class (car subclass)))
+	       (fname (or (ebrowse-cs-source-file scc)
+			  (ebrowse-cs-file scc)
+			  ;; Not def'd here, assume our current
+			  ;; file
+			  fname
+			  )))
+	  (when fname
+	    (semanticdb-ebrowse-add-tree-to-table
+	     dbe (car subclass) fname pname)))
+	(setq subclass (cdr subclass))))
+    ))
+
+;;;
+;; Overload for converting the simple faux tag into something better.
+;;
+(defmethod semanticdb-normalize-tags ((obj semanticdb-table-ebrowse) tags)
+  "Convert in Ebrowse database OBJ a list of TAGS into a complete tag.
+The default tag provided by searches exclude many features of a
+semantic parsed tag.  Look up the file for OBJ, and match TAGS
+against a semantic parsed tag that has all the info needed, and
+return that."
+  (let ((tagret nil)
+	)
+    ;; SemanticDB will automatically create a regular database
+    ;; on top of the file just loaded by ebrowse during the set
+    ;; buffer.  Fetch that table, and use it's tag list to look
+    ;; up the tag we just got, and thus turn it into a full semantic
+    ;; tag.
+    (while tags
+      (let ((tag (car tags)))
+	(save-excursion
+	  (semanticdb-set-buffer obj)
+	  (let ((ans nil))
+	    ;; Gee, it would be nice to do this, but ebrowse LIES.  Oi.
+	    (when (semantic-tag-with-position-p tag)
+	      (goto-char (semantic-tag-start tag))
+	      (let ((foundtag (semantic-current-tag)))
+		;; Make sure the discovered tag is the same as what we started with.
+		(when (string= (semantic-tag-name tag)
+			       (semantic-tag-name foundtag))
+		  ;; We have a winner!
+		  (setq ans foundtag))))
+	    ;; Sometimes ebrowse lies.  Do a generic search
+	    ;; to find it within this file.
+	    (when (not ans)
+	      ;; We might find multiple hits for this tag, and we have no way
+	      ;; of knowing which one the user wanted.  Return the first one.
+	      (setq ans (semantic-deep-find-tags-by-name
+			 (semantic-tag-name tag)
+			 (semantic-fetch-tags))))
+	    (if (semantic-tag-p ans)
+		(setq tagret (cons ans tagret))
+	      (setq tagret (append ans tagret)))
+	    ))
+	(setq tags (cdr tags))))
+    tagret))
+
+(defmethod semanticdb-normalize-one-tag ((obj semanticdb-table-ebrowse) tag)
+  "Convert in Ebrowse database OBJ one TAG into a complete tag.
+The default tag provided by searches exclude many features of a
+semantic parsed tag.  Look up the file for OBJ, and match TAG
+against a semantic parsed tag that has all the info needed, and
+return that."
+  (let ((tagret nil)
+	(objret nil))
+    ;; SemanticDB will automatically create a regular database
+    ;; on top of the file just loaded by ebrowse during the set
+    ;; buffer.  Fetch that table, and use it's tag list to look
+    ;; up the tag we just got, and thus turn it into a full semantic
+    ;; tag.
+    (save-excursion
+      (semanticdb-set-buffer obj)
+      (setq objret semanticdb-current-table)
+      (when (not objret)
+	;; What to do??
+	(debug))
+      (let ((ans nil))
+	;; Gee, it would be nice to do this, but ebrowse LIES.  Oi.
+	(when (semantic-tag-with-position-p tag)
+	  (goto-char (semantic-tag-start tag))
+	  (let ((foundtag (semantic-current-tag)))
+	    ;; Make sure the discovered tag is the same as what we started with.
+	    (when (string= (semantic-tag-name tag)
+			   (semantic-tag-name foundtag))
+	      ;; We have a winner!
+	      (setq ans foundtag))))
+	;; Sometimes ebrowse lies.  Do a generic search
+	;; to find it within this file.
+	(when (not ans)
+	  ;; We might find multiple hits for this tag, and we have no way
+	  ;; of knowing which one the user wanted.  Return the first one.
+	  (setq ans (semantic-deep-find-tags-by-name
+		     (semantic-tag-name tag)
+		     (semantic-fetch-tags))))
+	(if (semantic-tag-p ans)
+	    (setq tagret ans)
+	  (setq tagret (car ans)))
+	))
+    (cons objret tagret)))
+
+;;; Search Overrides
+;;
+;; NOTE WHEN IMPLEMENTING: Be sure to add doc-string updates explaining
+;; how your new search routines are implemented.
+;;
+(defmethod semanticdb-find-tags-by-name-method
+  ((table semanticdb-table-ebrowse) name &optional tags)
+  "Find all tags named NAME in TABLE.
+Return a list of tags."
+  ;;(message "semanticdb-find-tags-by-name-method name -- %s" name)
+  (if tags
+      ;; If TAGS are passed in, then we don't need to do work here.
+      (call-next-method)
+    ;; If we ever need to do something special, add here.
+    ;; Since ebrowse tags are converted into semantic tags, we can
+    ;; get away with this sort of thing.
+    (call-next-method)
+    )
+  )
+
+(defmethod semanticdb-find-tags-by-name-regexp-method
+  ((table semanticdb-table-ebrowse) regex &optional tags)
+  "Find all tags with name matching REGEX in TABLE.
+Optional argument TAGS is a list of tags to search.
+Return a list of tags."
+  (if tags (call-next-method)
+    ;; YOUR IMPLEMENTATION HERE
+    (call-next-method)
+    ))
+
+(defmethod semanticdb-find-tags-for-completion-method
+  ((table semanticdb-table-ebrowse) prefix &optional tags)
+  "In TABLE, find all occurances of tags matching PREFIX.
+Optional argument TAGS is a list of tags to search.
+Returns a table of all matching tags."
+  (if tags (call-next-method)
+    ;; YOUR IMPLEMENTATION HERE
+    (call-next-method)
+    ))
+
+(defmethod semanticdb-find-tags-by-class-method
+  ((table semanticdb-table-ebrowse) class &optional tags)
+  "In TABLE, find all occurances of tags of CLASS.
+Optional argument TAGS is a list of tags to search.
+Returns a table of all matching tags."
+  (if tags (call-next-method)
+    (call-next-method)))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;; Deep Searches
+;;
+;; If your language does not have a `deep' concept, these can be left
+;; alone, otherwise replace with implementations similar to those
+;; above.
+;;
+
+(defmethod semanticdb-deep-find-tags-by-name-method
+  ((table semanticdb-table-ebrowse) name &optional tags)
+  "Find all tags name NAME in TABLE.
+Optional argument TAGS is a list of tags t
+Like `semanticdb-find-tags-by-name-method' for ebrowse."
+  ;;(semanticdb-find-tags-by-name-method table name tags)
+  (call-next-method))
+
+(defmethod semanticdb-deep-find-tags-by-name-regexp-method
+  ((table semanticdb-table-ebrowse) regex &optional tags)
+  "Find all tags with name matching REGEX in TABLE.
+Optional argument TAGS is a list of tags to search.
+Like `semanticdb-find-tags-by-name-method' for ebrowse."
+  ;;(semanticdb-find-tags-by-name-regexp-method table regex tags)
+  (call-next-method))
+
+(defmethod semanticdb-deep-find-tags-for-completion-method
+  ((table semanticdb-table-ebrowse) prefix &optional tags)
+  "In TABLE, find all occurances of tags matching PREFIX.
+Optional argument TAGS is a list of tags to search.
+Like `semanticdb-find-tags-for-completion-method' for ebrowse."
+  ;;(semanticdb-find-tags-for-completion-method table prefix tags)
+  (call-next-method))
+
+;;; Advanced Searches
+;;
+(defmethod semanticdb-find-tags-external-children-of-type-method
+  ((table semanticdb-table-ebrowse) type &optional tags)
+  "Find all nonterminals which are child elements of TYPE
+Optional argument TAGS is a list of tags to search.
+Return a list of tags."
+  (if tags (call-next-method)
+    ;; Ebrowse collects all this type of stuff together for us.
+    ;; but we can't use it.... yet.
+    nil
+    ))
+
+;;; TESTING
+;;
+;; This is a complex bit of stuff.  Here are some tests for the
+;; system.
+
+(defun semanticdb-ebrowse-run-tests ()
+  "Run some tests of the semanticdb-ebrowse system.
+All systems are different.  Ask questions along the way."
+  (interactive)
+  (let ((doload nil))
+    (when (y-or-n-p "Create a system database to test with? ")
+      (call-interactively 'semanticdb-create-ebrowse-database)
+      (setq doload t))
+    ;;  Should we load in caches
+    (when (if doload
+	      (y-or-n-p "New database created.  Reload system databases? ")
+	    (y-or-n-p "Load in all system databases? "))
+      (semanticdb-load-ebrowse-caches)))
+  ;; Ok, databases were creatd.  Lets try some searching.
+  (when (not (or (eq major-mode 'c-mode)
+		 (eq major-mode 'c++-mode)))
+    (error "Please make your default buffer be a C or C++ file, then
+run the test again..")
+    )
+
+  )
+
+(defun semanticdb-ebrowse-dump ()
+  "Find the first loaded ebrowse table, and dump out the contents."
+  (interactive)
+  (let ((db semanticdb-database-list)
+	(ab nil))
+    (while db
+      (when (semanticdb-project-database-ebrowse-p (car db))
+	(setq ab (data-debug-new-buffer "*EBROWSE Database*"))
+	(data-debug-insert-thing (car db) "*" "")
+	(setq db nil)
+	)
+      (setq db (cdr db)))))
+
+(provide 'semantic/db-ebrowse)
+
+;;; semanticdb-ebrowse.el ends here