This page needs info on how to actually use these tools. I believe I’ve installed the pieces correctly, but now I need to know how to actually use them. An intro on some of the basic commands would be greatly appreciated.
Cscope http://cscope.sf.net is a program that generates index tables from C and C++ source files. It is also a client program that knows how to use the generated index tables to answer questions such as where is a symbol defined, where is a symbol referenced, etc.
It works fine with GNU Emacs 21.2 under Debian GNU/Linux as well as under Windows XP (and probably other Windows OS’es) if cscope is compiled using Cygwin http://www.cygwin.com provided GNU tools, i.e., typical “./configure; make; make install” steps work fine.
It does not compile using MSYS on MS Windows.
Darryl Okahata’s xcscope.el comes with the cscope package. This package is stable, and development is continuing in its own tree (https://github.com/dkogan/xcscope.el). This tree fixes various bugs and adds various features. Most significantly, multiple results are now displayed in the cscope buffer at a time. This makes management of multiple searches dramatically better. The full change log is available in the README at the above link. This xcscope.el package is currently available on MELPA and in Debian and in Ubuntu (package name is “xcscope-el”). Following comments are about Darryl’s original xcscope.el. I’ll review (and possibly absort) the patches mentioned here shortly.
I don’t know cscope.el, but I discovered xcscope.el recently – and this is really practical! Don’t use M-x grep anymore!
mmc: I have this problem with xcscope.el: When i invoke a long time lasting search, and go into minibuffer (think M-x), when cscope finishes its job, xcsope will present the found file inside the minibuffer. I have made this fix:
(defun cscope-process-sentinel (process event) (let* (.....) ;; Don't present the new buffer (file) inside minibuffer! (if (minibuffer-window-active-p old-buffer-window) (setq old-buffer-window (next-window old-buffer-window))) ....
GP: I unsuccessfully tried modifying xcscope.el so that it uses the “cscope -b -q -k” options, I want the -q option on my large code base, so that symbol search becomes quicker. Does anyone have suggestion on how I should make xcscope.el work with the “-q” option?
Just touch the file cscope.po.out and cscope.in.out after finishing index. It works for me. And try google bscope, you will find a new cscope interface faster than xscope. – highfly22 at gmail dot com
Thank Darryl for bringing us such an amazing tool. However, despite much convenience it provides there are still some guys, including me 😊, asking for certain new feature now and then on news groups: going back and forth the search history.
I think the primary benifit of this feature is to give us a clue how we gotten into current position. I used to ask myself “how I get into function?” since the code I’m reading has really deep call stacks and I can’t keep them all in my mind. The other benifit is that, for large projects, cscope-ing sometimes could be time-consuming.
I hacked the code for that feature (http://sourceforge.net/tracker/index.php?func=detail&aid=1839942&group_id=4664&atid=304664). Your comments are appreciated.
USAGE: For basic usage refer to original comments. To view previous search result, call cscope-history-backward (’C-c s v’ or just ‘v’ in cscope buffer) or cscope-history-forward (’V’).
Latest changes are: Change behavior of history ring to (which i think is) a more reasonable flavor. Change/Add key-bindings Add function cscope-history-clear Fix bug of can’t call history related functions except in cscope buffer.
Chris: I have been looking to get xcscope.el and emacs to cooperate under windows XP without cygwin. I found this native win32 version of cscope (http://code.google.com/p/cscope-win32/). Unfortunately xcscope.el uses a bash script (cscope-indexer) to generate the cscope database. Not finding a windows compatible version, I decided to come up with my own port. This is the cscope-indexer.bat I came up with. Feel free to use/modify/debug it. Place cscope-indexer.bat in your PATH and it should be working with xcscope.
@echo off & setlocal enableextensions REM ****************************************************************** REM Not responsible for any loss resulting from the use of this script REM ****************************************************************** REM sed and grep should be installed and in PATH REM those windows version can be installed via MSYS package (http://www.mingw.org/wiki/MSYS) set n=0 set recursive=0 set listonly=0 set verbose=0 set LIST_FILE="" set DATABASE_FILE="" set param="%*%" :LOOP if "%~1" == "" goto PROCESS if "%~1" == "-r" goto RECURSE if "%~1" == "-i" goto LISTFILE if "%~1" == "-f" goto CSCOPEOUT if "%~1" == "-l" goto LISTONLY if "%~1" == "-v" goto VERBOSE shift goto LOOP :RECURSE set recursive=1 shift goto LOOP :LISTFILE shift set LIST_FILE="%~1" shift goto LOOP :CSCOPEOUT shift set DATABASE_FILE="%~1" shift goto LOOP :LISTONLY set listonly=1 shift goto LOOP :VERBOSE set verbose=1 shift goto LOOP :PROCESS IF %verbose%==1 echo cscope-indexer args: %param% IF %recursive%==1 goto GET_RECURSE_SRC dir /B > %LIST_FILE%.tmp goto CSCOPE :GET_RECURSE_SRC dir /S /B > %LIST_FILE%.tmp goto CSCOPE :CSCOPE IF %listonly%==1 goto ALMOST_DONE grep -i -E "\.([chly](xx|pp)*|cc|hh)$" %LIST_FILE%.tmp | sed -e "s/^/\"/;s/$/\"/" > %LIST_FILE% cscope -b -i %LIST_FILE% -f %DATABASE_FILE% goto DONE :ALMOST_DONE grep -i -E "\.([chly](xx|pp)*|cc|hh)$" %LIST_FILE%.tmp > %LIST_FILE% goto DONE :DONE del "%LIST_FILE%.tmp" echo Done
Here is a patch created from revision 1.14 of contrib/xcscope/xcscope.el in the official cscope CVS repository on SourceForge that fixes a bug causing databases to be skipped over when using
‘cscope-database-regexps’ if they are contained in the same directory. I emailed Darryl Okahata with the patch but I do not know if he is still reachable.
--- xcscope.el.cvs 2011-09-23 10:31:31.874724475 -0400 +++ xcscope.el 2011-09-23 10:35:11.423813160 -0400 @@ -1012,9 +1012,9 @@ (make-variable-buffer-local 'cscope-search-list) -(defvar cscope-searched-dirs nil - "The list of database directories already searched.") -(make-variable-buffer-local 'cscope-searched-dirs) +(defvar cscope-searched-databases nil + "The list of databases already searched.") +(make-variable-buffer-local 'cscope-searched-databases) (defvar cscope-filter-func nil @@ -1925,17 +1925,20 @@ (progn ;; Handle the case where `cscope-directory' is really ;; a full path name to a cscope database. - (setq base-database-file-name + (setq database-file cscope-directory + base-database-file-name (file-name-nondirectory cscope-directory) cscope-directory (file-name-directory cscope-directory)) - )) + ) + ;; Else set database-file to default name + (setq database-file (concat cscope-directory base-database-file-name))) (setq cscope-directory (file-name-as-directory cscope-directory)) - (if (not (member cscope-directory cscope-searched-dirs)) + (if (not (member database-file cscope-searched-databases)) (progn - (setq cscope-searched-dirs (cons cscope-directory - cscope-searched-dirs) + (setq cscope-searched-databases (cons database-file + cscope-searched-databases) done t) )) ) @@ -1958,8 +1961,8 @@ (if cscope-command-args (setq options (append options cscope-command-args))) (setq database-file (concat cscope-directory base-database-file-name) - cscope-searched-dirs (cons cscope-directory - cscope-searched-dirs) + cscope-searched-databases (cons database-file + cscope-searched-databases) ) ;; The database file and the directory containing the database file @@ -2041,7 +2044,7 @@ (setq default-directory directory cscope-start-directory nil cscope-search-list (cscope-find-info directory) - cscope-searched-dirs nil + cscope-searched-databases nil cscope-command-args args cscope-filter-func filter-func cscope-sentinel-func sentinel-func
I got the original cscope-indexer script to work by copying it to the bin folder of an installed MinGW and the following trivial patch for xcscope.el. Your PATH has to be set accordingly, though.
--- xcscope.el (revision 9370) +++ xcscope.el (working copy) @@ -2123,7 +2123,7 @@ (setq cscope-unix-index-process (apply 'start-process "cscope-indexer" cscope-unix-index-process-buffer - cscope-indexing-script args)) + "sh" cscope-indexing-script args)) (set-process-sentinel cscope-unix-index-process 'cscope-unix-index-files-sentinel) (process-kill-without-query cscope-unix-index-process)
cscope and Windows: for versions up to 1.54, binaries compiled with DJGPP are provided (e.g., csc154b.zip).
xcscope.el is not included and is obtained separately by downloading the source. Update the global
PATH variable with the location of
xcscope.el in the
site-lisp directory, and add the following lines to
(require 'xcscope) (setq cscope-do-not-update-database t)
xcscope.el does automatic indexing by use of a Bash script (
cscope-indexer). As Windows lacks Bash support, automatic indexing is here disabled (although the MSYS project does include a
sh.exe executable which can run such scripts). To index manually and recursively, in the uppermost directory run
-b flag tells
cscope to just build the database and then exit. Otherwise,
cscope is terminated by
This seems to work adequately with GNU Emacs 22.1.
a possibly handy hack:
(defun my-find-tag(&optional prefix) "union of `find-tag' alternatives. decides upon major-mode" (interactive "P") (if (and (boundp 'cscope-minor-mode) cscope-minor-mode) (progn (ring-insert find-tag-marker-ring (point-marker)) (call-interactively (if prefix 'cscope-find-this-symbol 'cscope-find-global-definition-no-prompting ))) (call-interactively 'find-tag)))
(substitute-key-definition 'find-tag 'my-find-tag global-map)
Chris: I like this native win32 cscope version: http://code.google.com/p/cscope-win32. See the xcscope.el section for integration under windows.
I think the cscope-do-not-update-database variable does not exist anymore in recent versions of xcscope, in version 1.0 packaged in debian it’s cscope-option-do-not-update-database. Good to know if you work on a big codebase.
When working on large projects, it is desirable that only entries of concern are shown, say only show results in header files etc.. This code snippet works atop xcscope.el and provides the capability of hide/show results according to regexp: https://github.com/lgfang/elisp/blob/master/cscope-filter.el
ascope is an improvement over xcscope that runs all queries through a single cscope process, instead of starting a new process and reloading the database for each query. It was made by Staton Sun as a merge between xscope and another single-process interface, bscope (not listed here) Original ML post. A copy of the file is made available here: Lisp:ascope.el
I just ran some benchmarks, and I’m pretty sure the performance benefits of this are way overblown: http://notes.secretsauce.net/notes/2014/03/25_cscope-benchmarks.html . If I’m wrong about something here, please tell me.
Bill Carpenter’s cscope.el mode is available from this wiki:
Here’s another that I found on emacswiki; I have no idea how it compares to the others: http://emacswiki.org/xcscope+.el
There is another cscope.el out there. To get it, visit this MercurialMode repository: http://hg.serpentine.com/cscope-fu. (Link down 2010-04-18) (To get the latest version of cscope.el, click on the manifest-link, then the cscope.el filename and finally raw to download the file.)
The CEDET (CollectionOfEmacsDevelopmentEnvironmentTools) suite can use cscope as a backend for several tasks. These include:
rscope is a new implementation taking its roots from ascope, thus running a single cscope process for each cscope database. It’s a bit more versatile than ascope because it copes with multiple cscope databases (and hence spawns one cscope process per database once).
It was developped by Robert Jarzmik and is in rscope's github repository. The page explains the usage, which is globally very close to xscope in terms of key bindings.
-q enables fast symbol lookup via an inverted index. The following used xcscope.el to search a Linux source tree. Without -q the search took 1.39 seconds. With -q it took 0.08 seconds.
The database without -q:
[bwong@bwong-ds linux-g1]$ ls -l cscope.* -rw-rw-r--. 1 bwong bwong 1054231 Apr 14 11:23 cscope.files -rw-rw-r--. 1 bwong bwong 335946981 Apr 14 11:23 cscope.out [bwong@bwong-ds linux-g1]$
Search with -d:
Finding symbol: memparse Database directory: /home/bwong/dev/linux-g1/ ... Search complete. Search time = 1.39 seconds.
Build the database with -q:
[bwong@bwong-ds linux-g1]$ rm cscope.out [bwong@bwong-ds linux-g1]$ cscope -bq [bwong@bwong-ds linux-g1]$ ls -l cscope.* -rw-rw-r--. 1 bwong bwong 1054231 Apr 14 11:23 cscope.files -rw-rw-r--. 1 bwong bwong 70328320 Apr 24 10:54 cscope.in.out -rw-rw-r--. 1 bwong bwong 335946981 Apr 24 10:54 cscope.out -rw-rw-r--. 1 bwong bwong 471233016 Apr 24 10:54 cscope.po.out [bwong@bwong-ds linux-g1]$
Search with -d:
Finding symbol: memparse Database directory: /home/bwong/dev/linux-g1/ ... Search complete. Search time = 0.08 seconds.
If you are changing only a subtree and want the database updated automatically with your changes, while still getting fast searches for the rest of the tree, define the directory-to-cscope-database mappings like this:
(setq cscope-database-regexps '( ( "^/home/bwong/dev/linux-g1/kernel" (t) ( "/home/bwong/dev/linux-g1/" ("-d") ) ) )
In this example you are making changes only in the kernel directory so it has a default database that is updated when files change:
[bwong@bwong-ds linux-g1]$ ls kernel/cscope.* kernel/cscope.files kernel/cscope.out [bwong@bwong-ds linux-g1]$
The cscope-database-regexps value causes any searches originating under linux-g1/kernel to use linux-g1/kernel/cscope.*, updating the database as files change, and then finish searching using linux-g1/cscope.*, while not updating that database.
A search originating under linux-g1/kernel:
Finding symbol: memparse Database directory: /home/bwong/dev/linux-g1/kernel/ ------------------------------------------------------------------------------- *** crash_dump.c: setup_elfcorehdr elfcorehdr_addr = memparse(arg, &end); setup_elfcorehdr elfcorehdr_addr = memparse(end + 1, &end); ... ------------------------------------------------------------------------------- Database directory: /home/bwong/dev/linux-g1/ ------------------------------------------------------------------------------- *** lib/cmdline.c: <global> EXPORT_SYMBOL(memparse); ... *** sound/core/memalloc.c: snd_mem_proc_write (size = memparse(token, &endp)) < 64*1024 || ------------------------------------------------------------------------------- Search complete. Search time = 0.46 seconds.