Sei sulla pagina 1di 28

Interactively Examining a C

cscope:

Program
cscope is an interactive program that locates specified elements of code
in C, lex, or yacc source files. With cscope, you can search and edit your
source files more efficiently than you could with a typical editor. That's
because cscope supports function calls--when a function is being called,
when it is doing the calling--as well as C language identifiers and
keywords.

This chapter is a tutorial on the cscope browser provided with this


release and is organized into the following sections:

• The cscope Process


• Basic Use
• Unknown Terminal Type Error

The cscope Process


When cscope is called for a set of C, lex, or yacc source files, it builds a
symbol cross-reference table for the functions, function calls, macros,
variables, and preprocessor symbols in those files. You can then query
that table about the locations of symbols you specify. First, it presents
a menu and asks you to choose the type of search you would like to
have performed. You may, for instance, want cscope to find all the
functions that call a specified function.

When cscope has completed this search, it prints a list. Each list entry
contains the name of the file, the number of the line, and the text of
the line in which cscope has found the specified code. In our case, the
list also includes the names of the functions that call the specified
function. You now have the option of requesting another search or
examining one of the listed lines with the editor. If you choose the
latter, cscope invokes the editor for the file in which the line appears,
with the cursor on that line. You can now view the code in context and,
if you wish, edit the file as any other file. You can then return to the
menu from the editor to request a new search.

Because the procedure you follow depends on the task at hand, there
is no single set of instructions for using cscope. For an extended
example of its use, review the cscope session described in the next

1
section. It shows how you can locate a bug in a program without
learning all the code.

Basic Use
Suppose you are given responsibility for maintaining the program prog.
You are told that an error message, out of storage, sometimes appears
just as the program starts up. Now you want to use cscope to locate
the parts of the code that are generating the message. Here is how
you do it.

Step 1: Set Up the Environment

cscope is a screen-oriented tool that can only be used on terminals


listed in the Terminal Information Utilities (terminfo) database. Be sure
you have set the TERM environment variable to your terminal type so
that cscope can verify that it is listed in the terminfo database. If you
have not done so, assign a value to TERM and export it to the shell as
follows:

In a Bourne shell, type:

$ TERM=term_name; export TERM

In a C shell, type:

% setenv TERM term_name

You may now want to assign a value to the EDITOR environment


variable. By default, cscope invokes the vi editor. (The examples in this
chapter illustrate vi usage.) If you prefer not to use vi, set the EDITOR
environment variable to the editor of your choice and export EDITOR, as
follows:

In a Bourne shell, type:

$ EDITOR=emacs; export EDITOR

In a C shell, type:

% setenv EDITOR emacs

2
You may have to write an interface between cscope and your editor. For
details, see Command-Line Syntax for Editors.

If you want to use cscope only for browsing (without editing), you can
set the VIEWER environment variable to pg and export VIEWER. cscope will
then invoke pg instead of vi.

An environment variable called VPATH can be set to specify directories


to be searched for source files. See View Paths.

Step 2: Invoke the cscope Program

By default, cscope builds a symbol cross-reference table for all the C,


lex, and yacc source files in the current directory, and for any included
header files in the current directory or the standard place. So, if all the
source files for the program to be browsed are in the current directory,
and if its header files are there or in the standard place, invoke cscope
without arguments:

% cscope

To browse through selected source files, invoke cscope with the names
of those files as arguments:

% cscope file1.c file2.c file3.h

For other ways to invoke cscope, see Command-Line Options.

cscope builds the symbol cross-reference table the first time it is used
on the source files for the program to be browsed. By default, the
table is stored in the file cscope.out in the current directory. On a
subsequent invocation, cscope rebuilds the cross-reference only if a
source file has been modified or the list of source files is different.
When the cross-reference is rebuilt, the data for the unchanged files is
copied from the old cross-reference, which makes rebuilding faster
than the initial build, and reduces startup time for subsequent
invocations.

Step 3: Locate the Code

3
Now let's return to the task we undertook at the beginning of this
section: to identify the problem that is causing the error message out
of storage to be printed. You have invoked cscope, the cross-reference
table has been built. The cscope menu of tasks appears on the screen.

The cscope Menu of Tasks:

% cscope
cscope Press the ? key for help
Find this C symbol:
Find this global definition:
Find functions called by this function:
Find functions calling this function:
Find this text string:
Change this text string:
Find this egrep pattern:
Find this file:
Find files #including this file:

Press the Return key to move the cursor down the screen (with
wraparound at the bottom of the display), and ^p (Control-p) to move
the cursor up; or use the up (ua) and down (da) arrow keys. You can
manipulate the menu and perform other tasks with the following
single-key commands:

TABLE 9-1 cscope Menu Manipulation Commands

Tab Move to the next input field.


Return Move to the next input field.
^n Move to the next input field.
^p Move to the previous input field.
^y Search with the last text typed.
^b Move to the previous input field and search pattern.
^f Move to the next input field and search pattern.

^c
Toggle ignore/use letter case when searching. For example, a search for FILE
matches file and File when ignoring the letter case.
^r Rebuild cross-reference.
! Start an interactive shell. Type ^d to return to cscope.

4
^l Redraw the screen.
? Display the list of commands.
^d Exit cscope.

If the first character of the text for which you are searching matches
one of these commands, you can escape the command by entering a \
(backslash) before the character.

Now move the cursor to the fifth menu item, Find this text string,
enter the text out of storage, and press the Return key.

cscope Function: Requesting a Search for a Text String:

$ cscope
cscope Press the ? key for help
Find this C symbol
Find this global definition
Find functions called by this function
Find functions calling this function
Find this text string: out of storage
Change this text string
Find this egrep pattern
Find this file
Find files #including this file

Note – Follow the same procedure to perform any other task listed in
the menu except the sixth, Change this text string. Because this task is
slightly more complex than the others, there is a different procedure
for performing it. For a description of how to change a text string, see
Examples.

cscopesearches for the specified text, finds one line that contains it,
and reports its finding.

cscope Function: Listing Lines Containing the Text String:

Text string: out of storage


File Line
1 alloc.c 63 (void) fprintf(stderr, "\n%s: out of storage\n",
argv0);
Find this C symbol:
Find this global definition:

5
Find functions called by this function:
Find functions calling this function:
Find this text string:
Change this text string:
Find this egrep pattern:
Find this file:
Find files #including this file:

After cscope shows you the results of a successful search, you have
several options. You may want to change one of the lines or examine
the code surrounding it in the editor. Or, if cscope has found so many
lines that a list of them does not fit on the screen at once, you may
want to look at the next part of the list. The following table shows the
commands available after cscope has found the specified text:

TABLE 9-2 Commands for Use After an Initial Search

Edit the file referenced by this line. The number you type corresponds to an item
1 -9
in the list of lines printed by cscope.

Space Display the next set of matching lines.


+ Display the next set of matching lines.
^v Display the next set of matching lines.
-- Display the previous set of matching lines.
^e Edit the displayed files in order.
> Append the list of lines being displayed to a file.
| Pipe all lines to a shell command.

Again, if the first character of the text for which you are searching
matches one of these commands, you can escape the command by
entering a backslash before the character.

Now examine the code around the newly found line. Enter 1 (the
number of the line in the list). The editor is invoked with the file
alloc.c with the cursor at the beginning of line 63 of alloc.c.

cscope Function: Examining a Line of Code:

6
{
return(alloctest(realloc(p, (unsigned) size)));
}
/* check for memory allocation failure */
static char *
alloctest(p)
char *p;
{
if (p == NULL) {
(void) fprintf(stderr, "\n%s: out of storage\n", argv0);
exit(1);
}
return(p);
}
~
~
~
~
~
~
~
"alloc.c" 67 lines, 1283 characters

You can see that the error message is generated when the variable p is
NULL. To determine how an argument passed to alloctest() could have
been NULL, you must first identify the functions that call alloctest().

Exit the editor by using normal quit conventions. You are returned to
the menu of tasks. Now type alloctest after the fourth item, Find
functions calling this function.

cscope Function: Requesting a List of Functions That Call alloctest():

Text string: out of storage


File Line
1 alloc.c 63(void)fprintf(stderr,"\n%s: out of storage\n",argv0);
Find this C symbol:
Find this global definition:
Find functions called by this function:
Find functions calling this function: alloctest
Find this text string:
Change this text string:
Find this egrep pattern:
Find this file:
Find files #including this file:

7
cscope finds and lists three such functions.

cscope Function: Listing Functions That Call alloctest():

Functions calling this function: alloctest


File Function Line
1 alloc.c mymalloc 33 return(alloctest(malloc((unsigned) size)));
2 alloc.c mycalloc 43 return(alloctest(calloc((unsigned) nelem,
(unsigned) size)));
3 alloc.c myrealloc 53 return(alloctest(realloc(p, (unsigned)
size)));
Find this C symbol:
Find this global definition:
Find functions called by this function:
Find functions calling this function:
Find this text string:
Change this text string:
Find this egrep pattern:
Find this file:
Find files #including this file:

Now you want to know which functions call mymalloc(). cscope finds ten
such functions. It lists nine of them on the screen and instructs you to
press the space bar to see the rest of the list.

cscope Function: Listing Functions That Call mymalloc():

Functions calling this function: mymalloc

File Function Line

1 alloc.c stralloc 24 return(strcpy(mymalloc(strlen(s) + 1), s));

2 47 symbol = (struct symbol *)mymalloc(msymbols


crossref
crossref.c * sizeof(struct symbol));

63 srcdirs = (char **) mymalloc(nsrcdirs *


3 dir.c makevpsrcdirs
sizeof(char*));

167 incdirs = (char **)mymalloc(sizeof(char


4 dir.c addincdir
*));

168 incnames = (char **)mymalloc(sizeof(char


5 dir.c addincdir
*));

439 p = (struct listitem *)


6 dir.c addsrcfile
mymalloc(sizeof(struct listitem));

7 87 displine = (int *) mymalloc(mdisprefs *


dispinit
display.c sizeof(int));

8
8 19 h = (struct cmd *) mymalloc(sizeof(struct
addcmd
history.c cmd));

212 s = mymalloc((unsigned )(strlen(reffile)


9 main.c main
+strlen(home) + 2));

* 9 more lines - press the space bar to display more *


Find this C symbol:
Find this global definition:
Find functions called by this function:
Find functions calling this function:
Find this text string:
Change this text string:
Find this egrep pattern:
Find this file:
Find files #including this file:

Because you know that the error message out of storage is generated
at the beginning of the program, you can guess that the problem may
have occurred in the function dispinit() (display initialization).

To view dispinit(), the seventh function on the list, type 7.

cscope Function: Viewing dispinit() in the Editor:

void
dispinit()
{
/* calculate the maximum displayed reference lines */
lastdispline = FLDLINE - 4;
mdisprefs = lastdispline - REFLINE + 1;
if (mdisprefs > 9) {
mdisprefs = 9;
}
/* allocate the displayed line array */
displine = (int *) mymalloc(mdisprefs * sizeof(int));
}
^L/* display a page of the references */
void
display()
{
char file[PATHLEN + 1]; /* file name */
char function[PATLEN + 1];/* function name */
char linenum[NUMLEN + 1]; /* line number */
int screenline; /* screen line number */
int width; /* source line display width */
register int i, j;
"display.c" 622 lines, 14326 characters

9
mymalloc() failed because it was called either with a very large number
or a negative number. By examining the possible values of FLDLINE and
REFLINE, you can see that there are situations in which the value of
mdisprefs is negative, that is, in which you are trying to call mymalloc()
with a negative number.

Step 4: Edit the Code

On a windowing terminal, you may have multiple windows of arbitrary


size. The error message out of storage might have appeared as a
result of running prog in a window with too few lines. In other words,
that may have been one of the situations in which mymalloc() was
called with a negative number. Now you want to be sure that when the
program aborts in this situation in the future, it does so after printing
the more meaningful error message screen too small. Edit the function
dispinit() as follows.

cscope Function: Correcting the Problem:

void
dispinit()
{
/* calculate the maximum displayed reference lines */
lastdispline = FLDLINE - 4;
mdisprefs = lastdispline - REFLINE + 1;
if (mdisprefs > 9) {
mdisprefs = 9;
}
/* allocate the displayed line array */
displine = (int *) mymalloc(mdisprefs * sizeof(int));
}
^L/* display a page of the references */
void
display()
{
char file[PATHLEN + 1]; /* file name */
char function[PATLEN + 1];/* function name */
char linenum[NUMLEN + 1]; /* line number */
int screenline; /* screen line number */
int width; /* source line display width */
register int i, j;
"display.c" 622 lines, 14326 characters

10
You have fixed the problem we began investigating at the beginning of
this section. Now if prog is run in a window with too few lines, it does
not simply fail with the unedifying error message out of storage.
Instead, it checks the window size and generates a more meaningful
error message before exiting.

Command-Line Options

As noted, cscope builds a symbol cross-reference table for the C, lex,


and source files in the current directory by default. That is,

% cscope

is equivalent to:

% cscope *.[chly]

We have also seen that you can browse through selected source files
by invoking cscope with the names of those files as arguments:

% cscope file1.c file2.c file3.h

cscope provides command-line options with greater flexibility in


specifying source files to be included in the cross-reference. When you
invoke cscope with the -s option and any number of directory names
(separated by commas):

% cscope -s dir1,dir2,dir3

cscope builds a cross-reference for all the source files in the specified
directories as well as the current directory. To browse through all of
the source files whose names are listed in file (file names separated by
spaces, tabs, or new-lines), invoke cscope with the -i option and the
name of the file containing the list:

% cscope -i file

If your source files are in a directory tree, use the following commands
to browse through all of them:

11
% find . -name '*.[chly]' -print | sort > file
% cscope -i file

If this option is selected, however, cscope ignores any other files


appearing on the command-line.

The -I option can be used for cscope in the same way as the -I option
to cc. See Include Files.

You can specify a cross-reference file other than the default cscope.out
by invoking the -f option. This is useful for keeping separate symbol
cross-reference files in the same directory. You may want to do this if
two programs are in the same directory, but do not share all the same
files:

% cscope -f admin.ref admin.c common.c aux.c libs.c


% cscope -f delta.ref delta.c common.c aux.c libs.c

In this example, the source files for two programs, admin and delta, are
in the same directory, but the programs consist of different groups of
files. By specifying different symbol cross-reference files when you
invoke cscope for each set of source files, the cross-reference
information for the two programs is kept separate.

You can use the -pn option to specify that cscope display the path
name, or part of the path name, of a file when it lists the results of a
search. The number you give to -p stands for the last n elements of
the path name you want to be displayed. The default is 1, the name of
the file itself. So if your current directory is home/common, the command:

% cscope -p2

causes cscope to display common/file1.c, common/file2.c, and so forth


when it lists the results of a search.

If the program you want to browse contains a large number of source


files, you can use the -b option, so that cscope stops after it has built a
cross-reference; cscope does not display a menu of tasks. When you
use cscope -b in a pipeline with the batch(1) command, cscope builds
the cross-reference in the background:

12
% echo 'cscope -b' | batch

Once the cross-reference is built, and as long as you have not changed
a source file or the list of source files in the meantime, you need only
specify:

% cscope

for the cross-reference to be copied and the menu of tasks to be


displayed in the normal way. You can use this sequence of commands
when you want to continue working without having to wait for cscope to
finish its initial processing.

The -d option instructs cscope not to update the symbol cross-reference. You can use it
to save time if you are sure that no such changes have been made; cscope does not check
the source files for changes.

Note – Use the -d option with care. If you specify -d under the
erroneous impression that your source files have not been changed,
cscope refers to an outdated symbol cross-reference in responding to
your queries.

Check the cscope(1) man page for other command-line options.

View Paths

As we have seen, cscope searches for source files in the current


directory by default. When the environment variable VPATH is set, cscope
searches for source files in directories that comprise your view path. A
view path is an ordered list of directories, each of which has the same
directory structure below it.

For example, suppose you are part of a software project. There is an


official set of source files in directories below /fs1/ofc. Each user has a
home directory (/usr/you). If you make changes to the software
system, you may have copies of just those files you are changing in
/usr/you/src/cmd/prog1. The official versions of the entire program can
be found in the directory /fs1/ofc/src/cmd/prog1.

Suppose you use cscope to browse through the three files that
comprise prog1, namely, f1.c, f2.c, and f3.c. You would set VPATH to
/usr/you and /fs1/ofc and export it, as in:

13
In a Bourne shell, type:

$ VPATH=/usr/you:/fs1/ofc; export VPATH

In a C shell, type:

% setenv VPATH /usr/you:/fs1/ofc

You then make your current directory /usr/you/src/cmd/prog1, and


invoke cscope:

% cscope

The program locates all the files in the view path. In case duplicates
are found, cscope uses the file whose parent directory appears earlier
in VPATH. Thus, if f2.c is in your directory, and all three files are in the
official directory, cscope examines f2.c from your directory, and f1.c
and f3.c from the official directory.

The first directory in VPATH must be a prefix of the directory you will be
working in, usually $HOME. Each colon-separated directory in VPATH must
be absolute: it should begin at /.

cscope and Editor Call Stacks

cscope and editor calls can be stacked. That is, when cscope puts you in
the editor to view a reference to a symbol and there is another
reference of interest, you can invoke cscope again from within the
editor to view the second reference without exiting the current
invocation of either cscope or the editor. You can then back up by
exiting the most recent invocation with the appropriate cscope and
editor commands.

Examples

This section presents examples of how cscope can be used to perform


three tasks: changing a constant to a preprocessor symbol, adding an
argument to a function, and changing the value of a variable. The first
example demonstrates the procedure for changing a text string, which
differs slightly from the other tasks on the cscope menu. That is, once
you have entered the text string to be changed, cscope prompts you for

14
the new text, displays the lines containing the old text, and waits for
you to specify which of these lines you want it to change.

Changing a Constant to a Preprocessor Symbol

Suppose you want to change a constant, 100, to a preprocessor


symbol, MAXSIZE. Select the sixth menu item, Change this text string,
and enter \100. The 1 must be escaped with a backslash because it has
a special meaning (item 1 on the menu) to cscope. Now press Return.
cscope prompts you for the new text string. Type MAXSIZE.

cscope Function: Changing a Text String:

cscope Press the ? key for help


Find this C symbol:
Find this global definition:
Find functions called by this function:
Find functions calling this function:
Find this text string:
Change this text string: \100
Find this egrep pattern:
Find this file:
Find files #including this file:
To: MAXSIZE

cscope displays the lines containing the specified text string, and waits
for you to select those in which you want the text to be changed.

cscope Function: Prompting for Lines to be Changed:

cscope Press the ? key for help


Find this C symbol:
Find this global definition:
Find functions called by this function:
Find functions calling this function:
Find this text string:
Change this text string: \100
Find this egrep pattern:
Find this file:
Find files #including this file:
To: MAXSIZE

15
You know that the constant 100 in lines 1, 2, and 3 of the list (lines 4,
26, and 8 of the listed source files) should be changed to MAXSIZE. You
also know that 0100 in read.c and 100.0 in err.c (lines 4 and 5 of the
list) should not be changed. You select the lines you want changed
with the following single-key commands:

TABLE 9-3 Commands for Selecting Lines to be Changed

1-9 Mark or unmark the line to be changed.


* Mark or unmark all displayed lines to be changed.
Space Display the next set of lines.
+ Display the next set of lines.
- Display the previous set of lines.
a Mark all lines to be changed.
^d Change the marked lines and exit.
Esc Exit without changing the marked lines.

In this case, enter 1, 2, and 3. The numbers you type are not printed
on the screen. Instead, cscope marks each list item you want to be
changed by printing a > (greater than) symbol after its line number in
the list.

cscope Function: Marking Lines to be Changed:

Change "100" to "MAXSIZE"


File Line
1>init.c 4 char s[100];
2>init.c 26 for (i = 0; i < 100; i++)
3>find.c 8 if (c < 100) {
4 read.c 12 f = (bb & 0100);
5 err.c 19 p = total/100.0; /* get percentage */
Find this C symbol:
Find this global definition:
Find functions called by this function:
Find functions calling this function:
Find this text string:
Change this text string:
Find this egrep pattern:
Find this file:
Find files #including this file:

16
Select lines to change (press the ? key for help):

Now type ^d to change the selected lines. cscope displays the lines that
have been changed and prompts you to continue.

cscope Function: Displaying Changed Lines of Text:

Changed lines:
char s[MAXSIZE];
for (i = 0; i < MAXSIZE; i++)
if (c < MAXSIZE) {
Press the RETURN key to continue:

When you press Return in response to this prompt, cscope redraws the
screen, restoring it to its state before you selected the lines to be
changed.

The next step is to add the #define for the new symbol MAXSIZE.
Because the header file in which the #define is to appear is not among
the files whose lines are displayed, you must escape to the shell by
typing !. The shell prompt appears at the bottom of the screen. Then
enter the editor and add the #define.

cscope Function: Exiting to the Shell:

Text string: 100


File Line
1 init.c 4 char s[100];
2 init.c 26 for (i = 0; i < 100; i++)
3 find.c 8 if (c < 100) {
4 read.c 12 f = (bb & 0100);
5 err.c 19 p = total/100.0;
/* get percentage */
Find this C symbol:
Find this global definition:
Find functions called by this function:
Find functions calling this function:
Find this text string:
Change this text string:
Find this egrep pattern:
Find this file:
Find files #including this file:
$ vi defs.h

17
To resume the cscope session, quit the editor and type ^d to exit the
shell.

Adding an Argument to a Function

Adding an argument to a function involves two steps: editing the


function itself and adding the new argument to every place in the code
where the function is called.

First, edit the function by using the second menu item, Find this global
definition. Next, find out where the function is called. Use the fourth
menu item, Find functions calling this function, to obtain a list of all
the functions that call it. With this list, you can either invoke the editor
for each line found by entering the list number of the line individually,
or invoke the editor for all the lines automatically by typing ^e. Using
cscope to make this kind of change ensures that none of the functions
you need to edit are overlooked.

Changing the Value of a Variable

At times, you may want to see how a proposed change affects your
code.

Suppose you want to change the value of a variable or preprocessor


symbol. Before doing so, use the first menu item, Find this C symbol, to
obtain a list of references that are affected. Then use the editor to
examine each one. This step helps you predict the overall effects of
your proposed change. Later, you can use cscope in the same way to
verify that your changes have been made.

Command-Line Syntax for Editors

cscope invokes the vi editor by default. You can override the default
setting by assigning your preferred editor to the EDITOR environment
variable and exporting EDITOR, as described in Step 1: Set Up the
Environment. However, cscope expects the editor it uses to have a
command-line syntax of the form:

% editor +linenum filename

as does vi. If the editor you want to use does not have this command-
line syntax, you must write an interface between cscope and the editor.

18
Suppose you want to use ed. Because ed does not allow specification of
a line number on the command-line, you cannot use it to view or edit
files with cscope unless you write a shell script that contains the
following line:

/usr/bin/ed $2

Let's name the shell script myedit. Now set the value of EDITOR to your
shell script and export EDITOR:

In a Bourne shell, type:

$ EDITOR=myedit; export EDITOR

In a C shell, type:

% setenv EDITOR myedit

When cscope invokes the editor for the list item you have specified,
say, line 17 in main.c, it invokes your shell script with the command-
line:

% myedit +17 main.c

myedit then discards the line number ($1) and calls ed correctly with the
file name ($2). Of course, you are not moved automatically to line 17
of the file and must execute the appropriate ed commands to display
and edit the line.

Unknown Terminal Type Error


If you see the error message:

Sorry, I don't know how to deal with your "term" terminal

your terminal may not be listed in the Terminal Information Utilities


(terminfo) database that is currently loaded. Make sure you have
assigned the correct value to TERM. If the message reappears, try
reloading the Terminal Information Utilities.

If this message is displayed:

19
Sorry, I need to know a more specific terminal type than "unknown"

set and export the TERM variable as described in Step 1: Set Up the
Environment.

Using Cscope on large projects (example: the Linux


kernel)
Cscope can be a particularly useful tool if you need to wade into a large code base. You
can save yourself a lot of time by being able to do fast, targeted searches rather than
randomly grepping through the source files by hand (especially since grep starts to take a
while with a truly large code base).

In this tutorial you'll learn how to set up Cscope with a large project. We'll use as our
example the Linux kernel source code, but the basic steps are the same for any other large
project, including C++ or Java projects.

1. Get the source. First get the source code. You can download the Linux kernel
source from http://www.kernel.org. For the rest of this tutorial, I'll assume you've
downloaded Linux 2.4.18 and installed it into /home/jru/linux-2.4.18.

Note: Make sure you've got enough disk space: the kernel tarball alone is 30 MB,
it expands into 150 MB of source code, and the Cscope database we'll generate
will gobble up another 20-100+ MB (depending on how much of the kernel code
you decide to include in the database). You can put the Cscope database on a
different disk partition than the source code if you need to.

2. Figure out where you want to put your Cscope database files. I'll assume
you'll use /home/jru/cscope as the directory to store your database and
associated files.
3. Generate cscope.files with a list of files to be scanned. For some projects,
you may want to include every C source file in the project's directories in your
Cscope database. In that case you can skip this step, and just use 'cscope -R' in
the project's top-level directory to build your Cscope database. But if there's some
code that you wish to exclude, and/or your project contains C++ or Java source
code (by default Cscope only parses files with the .c, .h, .y, or .l extensions),
you'll need to generate a file called cscope.files, which should contain the
name of all files that you wish to have Cscope scan (one file name per line).

You'll probably want to use absolute paths (at least if you're planning to use the
Cscope database within an editor), so that you can use the database from
directories other than the one you create. The commands I show will first cd to
root, so that find prints out absolute paths.

20
For many projects, your find command may be as as simple as

cd /
find /my/project/dir -name '*.java'
>/my/cscope/dir/cscope.files

For the Linux kernel, it's a little trickier, since we want to exclude all the code in
the docs and scripts directories, plus all of the architecture and assembly code for
all chips except for the beloved Intel x86 (which I'm guessing is the architecture
you're interested in). Additionally, I'm excluding all kernel driver code in this
example (they more than double the amount of code to be parsed, which bloats
the Cscope database, and they contain many duplicate definitions, which often
makes searching harder. If you are interested in the driver code, omit the relevant
line below, or modify it to print out only the driver files you're interested in):

LNX=/home/jru/linux-2.4.18
cd /
find $LNX
\
-path "$LNX/arch/*" ! -path "$LNX/arch/i386*" -prune -o
\
-path "$LNX/include/asm-*" ! -path "$LNX/include/asm-i386*"
-prune -o \
-path "$LNX/tmp*" -prune -o
\
-path "$LNX/Documentation*" -prune -o
\
-path "$LNX/scripts*" -prune -o
\
-path "$LNX/drivers*" -prune -o
\
-name "*.[chxsS]" -print >/home/jru/cscope/cscope.files

While find commands can be a little tricky to write, for large projects they are
much easier than editing a list of files manually, and you can also cut and paste a
solution from someone else.

4. Generate the Cscope database. Now it's time to generate the Cscope database:
5. cd /home/jru/cscope # the directory with 'cscope.files'
6. cscope -b -q -k

The -b flag tells Cscope to just build the database, and not launch the Cscope
GUI. The -q causes an additional, 'inverted index' file to be created, which makes
searches run much faster for large databases. Finally, -k sets Cscope's 'kernel'
mode--it will not look in /usr/include for any header files that are #included in
your source files (this is mainly useful when you are using Cscope with operating
system and/or C library source code, as we are here).

21
On my 900 MHz Pentium III system (with a standard IDE disk), parsing this
subset of the Linux source takes only 12 seconds, and results in 3 files
(cscope.out, cscope.in.out, and cscope.po.out) that take up a total of 25
megabytes.

7. Using the database. If you like to use vim or emacs/xemacs, I recommend that
you learn how to run Cscope within one of these editors, which will allow you to
run searches easily within your editor. We have a tutorial for Vim, and emacs
users will of course be clever enough to figure everything out from the helpful
comments in the cscope/contrib/xcscope/ directory of the Cscope
distribution.

Otherwise, you can use the standalone Cscope curses-based GUI, which lets you
run searches, then launch your favorite editor (i.e., whatever $EDITOR is set to in
your environment, or 'vi' by default) to open on the exact line of the search result.

If you use the standalone Cscope browser, make sure to invoke it via

cscope -d

This tells Cscope not to regenerate the database. Otherwise you'll have to wait
while Cscope checks for modified files, which can take a while for large projects,
even when no files have changed. If you accidentally run 'cscope', without any
flags, you will also cause the database to be recreated from scratch without the
fast index or kernel modes being used, so you'll probably need to rerun your
original cscope command above to correctly recreate the database.

8. Regenerating the database when the source code changes.

If there are new files in your project, rerun your 'find' command to update
cscope.files if you're using it.

Then simply invoke cscope the same way (and in the same directory) as you did
to generate the database initially (i.e., cscope -b -q -k).

A tutorial example: locating the source of


the error message
In this example, the task is to locate the source of an error message ``out of storage''
that is printed when a program is run. Assume that you are working with unfamiliar code.
You will invoke cscope and start your search for the problem by locating the section of
code where the error message is generated. Move the cursor to the fifth menu item, that
is:

22
List lines containing this text string

Now enter the text to be searched for:

out of storage

This process is shown in the next example.

cscope Press the ? key for help

List references to this C symbol:

Edit this function or #define:

List functions called by this function:

List functions calling this function:

List lines containing this text string: out of storage

Change this text string:

List the file names containing this text string:

Press the <Return> key. The cscope tool searches for the specified text and finds one line
that contains it.
NOTE: The same procedure is followed to perform any other task listed in the menu,
except the sixth, changing a text string. For a description and examples of changing a text
string, see ``Changing a text string''.

cscope reports its findings as follows:

Text string: out of storage

File Line

1 alloc.c 56 (void) fprintf(stderr,

"\n%s: out of storage\n",

argv[0] );

Edit this function or #define:

List functions called by this function:

23
List functions calling this function:

List lines containing this text string:

Change this text string:

List file names containing this text string:

After cscope shows the results of a successful search in this way, you have several
options. For example, you may want to edit one of the lines found. If cscope has found
several lines and a list of them will not fit on the screen at once, you may want to look at
the next part of the list. The following table shows the commands available after cscope
has found the specified text.

Commands for use after initial search

Command Meaning
1-9 edit this line
(the number you type corresponds to an item
in the list of lines printed by cscope)
space display the lines after the current line
+ display the lines after the current line
- display the lines before the current line
<Ctrl>e edit all lines
> append the list of lines being displayed to a file
NOTE: If the first character of the text you are searching for matches one of these
commands, precede it with a ``\'' (backslash).

Now examine the code around the newly found line. Enter ``1'' (the number of the line in
the list). The editor will be invoked with the file alloc.c; the cursor will be at the
beginning of line 56 of the text file.

{
return(alloctest(realloc(p,(unsigned) size)));
}
/* check for memory allocation failure */

static char *

alloctest(p)

char *p;

24
if (p == NULL) {

(void) fprintf(stderr,

"\n%s: out of storage\n",

argv[0]);

exit(C);

return(p);

"alloc.c" 60 lines, 1022 characters

By examining the code, you learn that the error message is generated when the variable p
is NULL. To determine how an argument passed to alloctest could have been NULL, you
must first identify the functions that call alloctest.

Exit the editor by using normal write and quit conventions, and return to the menu of
tasks. Now request a list of functions that call alloctest, as shown in the next example:

Text string: out of storage

File Line

1 alloc.c 56 (void) fprintf(stderr,"\n%s: out of storage\n",

argv[0] );

List references to this C symbol:

Edit this function or #define:

List functions called by this function:

List functions calling this function: alloctest

List lines containing this text string:

Change this text string:

List file names containing this text string:

25
cscope finds and lists three such functions:
Functions calling this function: alloctest

File Function Line

1 alloc.c mymalloc 26 return(alloctest(malloc((unsigned) size)));

2 alloc.c mycalloc 36 return(alloctest(calloc((unsigned) nelem,

(unsigned) size)));

3 alloc.c myrealloc 46 return(alloctest(realloc(p, (unsigned)

size)));

List references to this C symbol:

Edit this function or #define:

List functions called by this function:

List functions calling this function:

List lines containing this text string:

Change this text string:

List file names containing this text string:

Now you need to know which functions call mymalloc. cscope finds ten such functions.
It lists seven of them on the screen and instructs you to press the space bar to see the rest
of the list.
Functions calling this function: mymalloc

File Function Line

1 alloc.c stralloc 17 return(strcpy(mymalloc(strlen(s)

+ 1), s));

2 dir.c makesrcdirlist 70 srcdirs = (char **)

mymalloc(nsrcdirs*sizeof(char*));

3 dir.c makesrcdirlist 89 s = mymalloc(strlen(srcdirs[i])

+ n);

4 dir.c makefilelist 115 srcfiles = (char **)

26
mymalloc(msrcfiles*sizeof(char*));

5 dir.c makefilelist 116 srcnames = (char **)

mymalloc(msrcfiles*sizeof(char*));

6 dir.c addincdir 212 incdirs = (char **)

mymalloc(sizeof(char *));

7 display.c dispinit 76 displine = (int *)

mymalloc(mdisprefs * sizeof(int));

* 3 more lines - press the space bar to display more *

List references to this C symbol:

Edit this function or #define:

List functions called by this function:

List functions calling this function:

List lines containing this text string:

Change this text string:

List file names containing this text string:

Because you know that the error message ("out of storage") is generated at the
beginning of the program, you can guess that the problem may have occurred in the
function dispinit (display initialization). To view dispinit, the seventh function on the
list, type ``7'':
void dispinit()
{
/* calculate the maximum displayed reference lines */
lastdispline = FLDLINE - 4;
mdisprefs = lastdispline - REFLINE + 1;
if (mdisprefs > 9) {
mdisprefs = 9;
}
/* allocate the displayed line array */
displine = (int *) mymalloc(mdisprefs * sizeof(int));
}
^L/* display a page of the references */

void display(){

27
char file[PATHLEN + 1]; /* file name */

char function[PATLEN + 1]; /* function name */

char linenum[NUMLEN + 1]; /* line number */

int screenline; /* screen line number */

int width; /* source line display width */

register int i, j;

"display.c" 440 lines, 10198 characters

Examining this code, you will see that mymalloc failed because it was called with a
negative number. You are now in a position to fix the problem. The program needs a
mechanism such that if the value of the variable mdisprefs is negative, it will abort after
printing a meaningful error message.

Stacking cscope and editor calls


cscope and editor calls can be stacked. This means that when cscope puts you in the
editor to display one symbol reference and there is another symbol of interest, you can
call cscope again from within the editor without exiting the current invocation of either
cscope or the editor. You can then back up to a previous invocation by exiting the
appropriate cscope and editor calls.

28

Potrebbero piacerti anche