Using CSCOPE – source browsing tool

Posted: July 9, 2010 in cscope, emacs, tutorial

Here I found that “For those coding in C in large projects cscope is etags killer” (see ctags), so I decided to give it a try.

(From file xcscope.el - Cscope interface for Emacs)
;; Cscope is designed to answer questions like:
;;
;;         Where is this variable used?
;;         What is the value of this preprocessor symbol?
;;         Where is this function in the source files?
;;         What functions call this function?
;;         What functions are called by this function?
;;         Where does the message "out of space" come from?
;;         Where is this source file in the directory structure?
;;         What files include this header file?

As usually, we will illustrate what cscope is and how to use it, in a real world example.

First, install cscope program, if your system doesn’t have it already. I am using Slackware 13.0 with cscope version 15.6 installed by default. We will download some C source code on which we want to test cscope (I decided to download PostgreSQL source, version 8.4.4) and uncompress it .

mkdir -p /home/user/projects/foo
cd /home/user/projects/foo
wget http://wwwmaster.postgresql.org/redir/198/h/source/v8.4.4/postgresql-8.4.4.tar.bz2
tar jxvf postgresql-8.4.4.tar.bz2

Generate file cscope.files which should contain a list of all files that we want to index with cscope (.c and .h files). Because we want absolute path file names, we will first change to root directory and find will then give us absolute paths:

cd /
find /home/user/projects/foo | egrep -i "\.(c|h)$" > /home/user/projects/foo/cscope.files

Generate cscope database and open cscope user interface: (argument -q makes searches run much faster for large databases)

cd /home/user/projects/foo
cscope -q

If you are an Emacs user, you will probably want to use cscope in your favorite editor and to do this, you must copy files cscope-indexer and xcscope.el in appropriate folders. These files we can be found in folder contrib/xcscope/ in cscope source code. File cscope-indexer (which is a shell script that generates a list of files to index and optionally generate a cscope database) must be executable and placed in some directory in system PATH. Usually, my executable files are placed in ~/bin folder and PATH variable is updated by adding this lines to ~/.bashrc: (make sure ~/bin exists and that you are using bash shell)

PATH="~/bin:$PATH"
export PATH

Check if ~/bin folder is in your path by echoing PATH variable. You may want to add the following to your ~/.bash_profile file:

if [ -f ~/.bashrc ]; then
source ~/.bashrc
fi

to be sure that ~/.bashrc will be executed.

File xcscope.el must be copied in some folder in Emacs’s load path. Usually, my .el files are in folder ~/elisp and this folder can be included in Emacs load path by adding this line to ~/.emacs:

(add-to-list 'load-path "~/elisp")

Also, make sure that folder ~/elisp exists. Now, download cscope source (at this time, the latest version is 15.7a and file is called cscope-15.7a.tar.bz2) and place it in home folder. Then, uncompress it and copy the files:

cd ~
tar jxvf cscope-15.7a.tar.bz2
cp cscope-15.7a/contrib/xcscope/cscope-indexer ~/bin
chmod a+x ~/bin/cscope-indexer
cp cscope-15.7a/contrib/xcscope/xcscope.el ~/elisp

When this is done, we can include cscope in Emacs by adding this line to ~/.emacs :

(require 'xcscope)

Start Emacs, type M-x cscope and type TAB key (one or more times). If you see a list of cscope functions in other buffer, everything is fine. Set the cscope-initial-directory variable by typing M-x cscope-set-initial-directory and ~/projects/foo in the mini buffer (we can check variable values in Emacs by typing M-x describe-variable following the variable name). Now, Emacs will look for cscope database in this folder, so it’s time to create one.

From Emacs, go to project folder ~/project/foo with C-x C-f or M-x dired (now key bindings for cscope will be accessible – all beginning with C-c s). Create list of files to index and cscope database with M-x cscope-index-files (this should create files cscope.files and cscope.out in ~/project/foo).

You can bind commands that you will use most frequently on function keys, by adding something like this to ~/.emacs:

(define-key global-map [(control f4)]  'cscope-pop-mark)
(define-key global-map [(control f5)]  'cscope-find-this-text-string)
(define-key global-map [(control f6)]  'cscope-find-this-symbol)
(define-key global-map [(control f7)]  'cscope-find-functions-calling-this-function)
(define-key global-map [(control f8)]  'cscope-find-called-functions)
(define-key global-map [(control f9)]  'cscope-prev-symbol)
(define-key global-map [(control f10)] 'cscope-next-symbol)

Now, try to find symbol conn that represents a connection to the PostgreSQL database. All you need to do is M-x cscope-find-this-symbol conn (or C-F6 conn if you made this shortcut) and by M-x cscope-next-symbol (or C-F10) you can go through all of them.

List of all commands and key bindings are: (feel free to experiment)

(From file xcscope.el)
;; * Keybindings:
;;
;; All keybindings use the "C-c s" prefix, but are usable only while
;; editing a source file, or in the cscope results buffer:
;;
;;      C-c s s         Find symbol.
;;      C-c s d         Find global definition.
;;      C-c s g         Find global definition (alternate binding).
;;      C-c s G         Find global definition without prompting.
;;      C-c s c         Find functions calling a function.
;;      C-c s C         Find called functions (list functions called
;;                      from a function).
;;      C-c s t         Find text string.
;;      C-c s e         Find egrep pattern.
;;      C-c s f         Find a file.
;;      C-c s i         Find files #including a file.
;;
;; These pertain to navigation through the search results:
;;
;;      C-c s b         Display *cscope* buffer.
;;      C-c s B         Auto display *cscope* buffer toggle.
;;      C-c s n         Next symbol.
;;      C-c s N         Next file.
;;      C-c s p         Previous symbol.
;;      C-c s P         Previous file.
;;      C-c s u         Pop mark.
;;
;; These pertain to setting and unsetting the variable,
;; `cscope-initial-directory', (location searched for the cscope database
;;  directory):
;;
;;      C-c s a         Set initial directory.
;;      C-c s A         Unset initial directory.
;;
;; These pertain to cscope database maintenance:
;;
;;      C-c s L         Create list of files to index.
;;      C-c s I         Create list and index.
;;      C-c s E         Edit list of files to index.
;;      C-c s W         Locate this buffer's cscope directory
;;                      ("W" --> "where").
;;      C-c s S         Locate this buffer's cscope directory.
;;                      (alternate binding: "S" --> "show").
;;      C-c s T         Locate this buffer's cscope directory.
;;                      (alternate binding: "T" --> "tell").
;;      C-c s D         Dired this buffer's directory
Comments
  1. Cscope *is* awesome. And one of the coolest things is that it’s almost as old as Unix (dating to the early ’70s, I believe). Semantic, part of Cedet, fulfills some cimilar functions, but it’s not quite as good. You can only use it to find function definitions or function calls, not symbols (that I’m aware of).

    I feel like I’m setting up my own alternative to Cedet with Cscope, Auto-complete, C-Eldoc mode and Imenu.

Leave a comment