Oracle Solaris Studio 12.2: C ユーザーガイド

第 8 章 cscope: 対話的な C プログラムの検査

cscope は、プログラムC、lex、または yacc ソースファイル内のコードの特定の要素を探し出す対話型プログラムです。cscope ブラウザを使用すると、従来のエディタよりも効率的にソースファイルを検索、編集できます。これは、cscope が関数呼び出し (関数がいつ呼び出され、いつその関数を実行するか) についてと、C 言語の識別子とキーワードを理解しているためです。

本章は cscope ブラウザについて説明します。この章は、このリリースに付属している cscope ブラウザの使い方を学ぶための資料として利用できます。


注 –

cscope プログラムは、まだ 1999 ISO/IEC C 規格用に作成されたコードを認識できるように更新されていません。たとえば、1999 ISO/IEC C 規格で導入された新しいキーワードを認識しません。


8.1 cscope プロセス

cscope は、C、lexyacc のソースファイルを読み取り、ファイル内の関数、関数呼び出し、マクロ、変数、前処理シンボルのシンボル相互参照表を作成します。次に作成した表を検索して、ユーザーが指定したシンボルの位置を探し出します。cscope は、最初にメニューを表示し、実行したい検索のタイプを聞いてきます。たとえば、cscope で特定の関数を呼び出しているすべての関数を検索することがあります。

検索が終了すると、cscope は結果を表示します。リストの各エントリ行には、cscope によって指定したコードが見つかったファイル名、行番号、その行のテキストが含まれます。この例では、指定された関数を呼び出している関数名も表示されます。リストを表示したあとは、新しく検索するか、あるいはリストに表示された行をエディタで調べるかを選択することができます。後者の場合、cscope はその行があるファイルをエディタで読み込んで、その行にカーソルを移動します。ここで、その行の前後関係を調べることができます。さらにほかのファイルと同じように編集することもできます。エディタを終了したら、メニューに戻って新しい検索を始めます。

作業内容によって手順も変わってくるので、cscope の使用方法は 1 通りではありません。cscope の詳しい使用方法や、コード全体を調べることなくプログラム内のバグを探し出す方法については、次の節で説明します。

8.2 基本的な使用方法

たとえば、プログラム prog の開始直後に 「out of storage」というエラーメッセージが表示されることがあると想定します。これを解決するには、まず cscope を使用してコード内のメッセージを発行している場所を探し出さなければいけません。この場合、次の手順で実行します。

8.2.1 ステップ 1: 環境設定

cscope は、画面指向ツールです。使用できる端末は、端末情報ユーティリティー (terminfo) データベースに書かれているものに限られます。TERM 環境変数を自分の端末タイプに設定してあることを確認してください。 cscope は TERM 環境変数の値を見て、それが terminfo データベースに存在するか確認します。まだ設定していない場合は、次のようにして TERM に値を設定し、それをシェルに伝えます。

B シェルの場合は次のように入力します。


$ TERM=term_name; export TERM

C シェルの場合は次のように入力します。


% setenv TERM term_name

次に、EDITOR 環境変数に値を設定します。 デフォルトでは、cscopevi エディタを起動します (本章の例も vi を使用して説明しています)。vi を使用しない場合は、EDITOR 環境変数を任意のエディタ名に変更して、EDITOR をエクスポートします。

B シェルの場合は次のように入力します。


$ EDITOR=emacs; export EDITOR

C シェルの場合は次のように入力します。


% setenv EDITOR emacs

cscope とエディタ間のインタフェースを設定しなければいけません。詳細は、「8.2.9 エディタのコマンド行構文」を参照してください。

cscope を表示するためだけに使用する (編集は使用しない) 場合は、VIEWER 環境編集を pg に設定して VIEWER をエクスポートします。cscopevi の代わりに pg を起動します。

環境変数 VPATH には、ソースファイルの検索対象ディレクトリを指定します。「8.2.6 ビューパス (Viewpath)」を参照してください。

8.2.2 ステップ 2: cscope プログラムの起動

デフォルトでは、cscope は現ディレクトリ内にあるすべての C、lex、および yacc のソースファイルのシンボル相互参照表、および現ディレクトリまたは標準位置内にあるすべてのインクルードヘッダーファイルのシンボル相互参照表を作成します。したがって、表示するプログラムのすべてのソースファイルが現ディレクトリにあり、かつそのヘッダーファイルが現ディレクトリまたは標準位置にある場合は、cscope を引数なしで起動します。


% cscope

特定のソースファイルを表示する場合は、そのファイルの名前を引数にして cscope を起動します。


% cscope file1.c file2.c file3.h

cscope のほかの起動方法については、「8.2.5 コマンド行オプション」を参照してください。

プログラムを表示するため、最初に cscope が使用されるときにシンボル相互参照表が作成されます。デフォルトでは、作成されたシンボル相互参照表は現ディレクトリ内の cscope.out ファイルに格納されます。そのあと cscope を再び起動すると、前回と比較してソースファイルが修正されていたとき、またはソースファイルのリストが異なるときだけ相互参照表が作成し直されます。相互参照表を再び作成する時には、変更されていないファイルのデータは前回の相互参照表からコピーされます。これによって、最初の作成時より作成速度が速くなり、起動時のスタートアップ時間も短くなります。

8.2.3 ステップ 3: コード位置の確定

本節の最初で述べた本来の作業に戻り、「out of storage」のエラーメッセージの原因となっている場所を確定します。cscope が起動され、相互参照表が作成されました。画面には、cscope の作業メニューが表示されます。

cscope の作業メニュー


% 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:

Return キーを押すと、カーソルが下に移動し (画面の一番下まで移動すると、先頭に戻る)、^p (Ctrl+p キー) を押すと、上に移動します。また、上矢印 (ua) と下矢印 (da) キーも使用できます。次の単一キーコマンドを使用すれば、メニュー操作とそのほかの作業が行えます。

表 8–1 cscope メニュー操作コマンド

Tab 

次の入力フィールドへ移動する 

Return 

次の入力フィールドへ移動する 

^n

次の入力フィールドへ移動する 

^p

前の入力フィールドへ移動する 

^y

最後に入力したテキストを検索する 

^b

逆方向にパターンを検索する 

^f

順方向にパターンを検索する 

^c

検索時に大文字と小文字を区別するか否かのトグルスイッチ (大文字と小文字を区別しない場合、たとえば FILE 文字列は fileFile の両方と一致)。

^r

相互参照表を再作成する 

!

対話型シェルを起動する (^dcscope に復帰)

^l

画面を描き直す 

?

コマンドのリストを表示する 

^d

cscope を終了する

検索文字列の最初の文字が前述のいずれかのコマンドと一致する場合は、検索文字列の前にバックスラッシュ (\) を加えてコマンドと区別します。

たとえば、カーソルを 5 番目のメニュー項目「Find this text string」に移動して文字列「out of storage」を入力し、Return キーを押します。

cscope 関数: 文字列検索の要求


$ 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

注 –

6 番目の「Change this text string」項目以外のメニュー項目についても同じ手順に従ってください。6 番目の項目はほかの項目よりも多少複雑なので手順が異なります。文字列の変更方法については、「8.2.8 例」を参照してください。


cscope は指定された文字列を検索し、それを含む行を見つけ出して次のように検索結果を表示します。

cscope 関数: 文字列を含む cscope 行のリスト表示


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:
Find this text string:
Change this text string:
Find this egrep pattern:
Find this file:
Find files #including this file:

cscope によって検索結果が正常に表示されたら、次の操作を選択します。行を変更したり、またはその行の前後をエディタで調べることができます。あるいは、cscope の検索結果のリストが一画面に収まらない場合は、リストの次の部分を見ることもできます。cscope が指定した文字列を検索したあとに使用可能なコマンドを次に示します。

表 8–2 最初の検索後に使用するコマンド

1 -9

この行を含むファイルを編集する (入力した番号は cscope が表示したリストの行番号に対応する)

スペース 

次画面のリストを表示する 

+

次画面のリストを表示する 

^v

次画面のリストを表示する 

前画面のリストを表示する 

^e

表示されたファイル順に編集する 

>

表示されているリストをファイルへ追加する 

|

全行をパイプでシェルコマンドに渡す 

ここでも、検索文字列の最初の文字が前述のいずれかのコマンドと一致する場合は、検索文字列の前にバックスラッシュ (\) を加えてコマンドと区別します。

次に、新しく検索した行の前後を調べます。「1」 (リスト内の行番号) を入力してください。エディタが起動され、alloc.c ファイルが読み込まれます。カーソルは、alloc.c の 63 行目の先頭に移動します。

cscope 関数: コード行の検査


{
   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

変数 pNULL のときに、エラーメッセージが出力されることがわかります。alloctest() に渡される引数がなぜ NULL になったのかを調べるには、まず alloctest() を呼び出している関数を確定する必要があります。

通常の終了方法でエディタを終了し、作業メニューに戻ります。ここで、4 番目の項目「Find functions calling this function」のあとに alloctest と入力します。

cscope 関数: 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:

cscope は検索を実行し、次の 3 つの関数のリストを表示します。

cscope 関数: alloctest() を呼び出す Listing 関数


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:

今度は、mymalloc() を呼び出す関数を調べます。cscope は、次のような 10 個の関数を見つけ出します。そのうち 9 個を画面に表示し、残りの 1 個を見るにはスペースバーを押すように指示しています。

cscope 関数: mymalloc() を呼び出す Listing 関数


Functions calling this function: mymalloc

File         Function       Line
1 alloc.c    stralloc       24 return(strcpy(mymalloc
                            (strlen(s) + 1), s));
2 crossref.c crossref       47 symbol = (struct symbol *)mymalloc
                            (msymbols * sizeof(struct symbol));
3 dir.c      makevpsrcdirs  63 srcdirs = (char **) mymalloc
                            (nsrcdirs * sizeof(char*));
4 dir.c      addincdir      167 incdirs = (char **)mymalloc
                            (sizeof(char *));
5 dir.c      addincdir      168 incnames = (char **)
                            mymalloc(sizeof(char *));
6 dir.c      addsrcfile     439 p = (struct listitem *) mymalloc
                            (sizeof(struct listitem));
7 display.c  dispinit       87 displine = (int *) mymalloc
                            (mdisprefs * sizeof(int));
8 history.c  addcmd         19  h = (struct cmd *) mymalloc
                            (sizeof(struct cmd));
9 main.c     main           212 s = mymalloc((unsigned )
                            (strlen(reffile) +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:

「out of storage」のエラーメッセージはプログラムの開始直後に出力されるので、関数 dispinit() (表示の初期化) 内で問題が発生していることが推測できます。

dispinit() はリストの 7 番目の関数なので、これを参照するには「7」と入力します。

cscope 関数: dispinit() をエディタで参照


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

mymalloc() が失敗したのは、非常に大きな数または負数を引数にして呼び出されたためです。FLDLINEREFLINE が取り得る値を調べてみると、mdisprefs の値が負になる場合があることがわかります。この場合、mymalloc() は負数を引数にして呼び出されます。

8.2.4 ステップ 4: コードの編集

ウィンドウ形式の端末では、任意のサイズのウィンドウを複数使用できます。「out of storage」のエラーメッセージが出力されたのは、prog を実行するウィンドウ内の行数が少なすぎたためと考えられます。つまり、mymalloc() が負数を引数にして呼び出された場合にこのような状況が発生する可能性があるということです。今後このような状況が発生した場合に、もっとわかりやすいエラーメッセージ、たとえば「Screen too small」を出力してプログラムを中止するように設定しておくとよいでしょう。それには dispinit() 関数を次のように編集します。

cscope 関数: 問題箇所の修正


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

以上で、本節の最初で調査を開始した問題箇所は修正されました。これで、行数が少なすぎるウィンドウ内で prog を実行したときに、単に意味不明のエラーメッセージ「out of storage」を出力して中止するのではなく、ウィンドウサイズを検査してわかりやすいエラーメッセージを出力したあとに終了するようになります。

8.2.5 コマンド行オプション

すでに述べたとおり、cscope はデフォルトでは現ディレクトリ内にある C、lex、および yacc ソースファイルのシンボル相互参照表を作成します。次に例を示します。


% cscope

これは次のように指定するのと同じことです。


% cscope *.[chly]

指定したソースファイルを表示するには、ソースファイル名を引数に指定して cscope を起動します。


% cscope file1.c file2.c file3.h

cscope のコマンド行オプションを使用して、相互参照表に含まれるソースファイルをさらに自由に指定することもできます。それには、次のように -s オプションのあとにコンマで区切られた任意の数のディレクトリ名を指定して cscope を起動します。


% cscope– s dir1,dir2,dir3

cscope は現ディレクトリ内だけでなく、指定されたディレクトリ内にあるすべてのソースファイルを対象に相互参照表を作成します。ファイル中にリストされているソースファイル (ファイル名をスペースやタブまたは復帰改行で区切ったもの) のすべてを表示するには、– i オプションとリストを持つファイル名を指定して cscope を起動します。


% cscope– i file

ソースファイルがディレクトリツリーの中にある場合は、次のコマンドでディレクトリツリー内のすべてのソースファイルを簡単に表示できます。


% find .–  name ’*.[chly]’– print | sort > file
% cscope– i file

このオプションを使用しても、コマンド行でファイルが指定されている場合、cscope によって指定されたファイル以外については無視されます。

-I オプションは、cc に対する -I オプションと同じような形式で cscope にも指定できます。「2.16 インクルードファイルを指定する方法」を参照してください。

-f オプションを使用すると、デフォルトの cscope.out 以外のファイルを相互参照ファイルとして指定できます。このオプションは、同じディレクトリ内に異なるシンボル相互参照ファイルを保管するのに役立ちます。たとえば、2 つのプログラムが同じディレクトリ内にあるが、すべてのファイルを共有しているとは限らない場合に使用します。


% cscope– f admin.ref admin.c common.c aux.c libs.c
% cscope– f delta.ref delta.c common.c aux.c libs.c

この例では、2 つのプログラム admindelta のソースファイルは同じディレクトリ内にありますが、プログラムを構成するファイルは異なっています。cscope 起動時に、別のシンボル相互参照ファイルを指定しておくことによって、2 つのプログラムの相互参照情報を別々に保管できます。

– pn オプションを使用すると、cscope は検索結果でリストされたファイルのあるパス名やそのパス名の一部を表示することができます。– p のあとの n には、パス名の中で最後から何番目までの要素を表示させたいかを指定します。デフォルト値は 1 で、これはファイル名そのものを意味します。したがって現ディレクトリが home/common の場合、次のコマンドによって


% cscope– p2

cscope によって検索結果のリストに表示されるパス名が、common/file1.ccommon/file2.c のように表示されます。

表示するプログラムが大量のソースファイルを含む場合、– b オプションを使用して、相互参照表を作成したあとで cscope を終了することができます。このとき、cscope は作業メニューを表示しません。パイプラインで、cscope– bbatch(1) コマンドとともに使用する場合、cscope は相互参照表をバックグラウンドで作成します。


% echo ’cscope -b’ | batch

相互参照表がいったん作成されると、その後、ソースファイルまたはソースファイルのリストを変更しないかぎり、次のように指定するだけで


% cscope

相互参照表がコピーされ、通常どおり作業メニューが表示されます。このコマンドシーケンスを使用すると cscope の初期処理の終了を待たずに作業を続けることができます。

– d オプションは、cscope にシンボル相互参照表を更新させません。このオプションを指定すると、cscope はソースファイルの変更を検査しないため時間の節約になります。変更されていないと確信できる場合にのみ使用してください。


注 –

-d オプションの使用には注意が必要です。ソースファイルが変更されていることに気付かずに – d オプションを使用すると、cscope は古いシンボル相互参照表を使用して照会に応じてしまいます。


ほかのコマンド行オプションについては、cscope(1) のマニュアルページを参照してください。

8.2.6 ビューパス (Viewpath)

前述のように cscope は、デフォルトでは現ディレクトリ内のソースファイルを検索します。環境変数 VPATH が設定されているときは、cscope は VPATH に指定されたディレクトリ内のソースファイルを検索します。ビューパスとは、順序付けされたディレクトリのリストで、リスト内の各ディレクトリの下は同じディレクトリ構造になっています。

たとえば、ユーザーがあるソフトウェアプロジェクトのメンバーであるとします。/fs1/ofc 下のディレクトリには、正式バージョンのソースファイルがあります。メンバーはホームディレクトリ (/usr/you) を持っており、ソフトウェアシステムを変更する場合は、変更するファイルだけを /usr/you/src/cmd/prog1 にコピーします。全プログラムの正式バージョンは、/fs1/ofc/src/cmd/prog1 にあります。

cscope を使用して、prog1 を構成する 3 つのファイル (f1.cf2.cf3.c) を表示します。まず VPATH/usr/you/fs1/ofc に設定してエクスポートします。

B シェルの場合は次のように入力します。


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

C シェルの場合は次のように入力します。


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

次に、現ディレクトリを /usr/you/src/cmd/prog1 に移動して cscope を起動します。


% cscope

cscope はビューパスにあるすべてのファイルの位置を調べます。同じファイルが複数のディレクトリにある場合は、cscopeVPATH 内で先に現れたディレクトリの下にあるファイルを使用します。したがって、f2.c がユーザーのディレクトリにあり (3 つのファイルはすべて正式バージョン用ディレクトリの下にもある場合)、cscopef2.c はユーザーディレクトリのものを、f1.c および f3.c は正式バージョン用のディレクトリのものを検査します。

VPATH 内の最初のディレクトリは、作業用ディレクトリの接頭辞 (通常は $HOME) でなければいけません。VPATH 内のコロンで区切られたそれぞれのディレクトリは、/ から始まる絶対パス名でなければいけません。

8.2.7 cscope とエディタ呼び出しのスタック

cscope とエディタの呼び出しはスタックできます。たとえば、cscope がエディタを起動してシンボルへの参照を調べているときに、ほかにも参照関係を調べたいシンボルがある場合、エディタ内部から再び cscope を起動して 2 番目の参照関係を調べることができます。現在起動中の cscope やエディタを終了する必要はありません。一番最後に起動した cscope またはエディタコマンドを正常に終了すれば、1 つ前の状態に戻ることができます。

8.2.8 例

cscope が次の 3 つの作業を行うのにどのように使用されるかを見ていきます。対象とする作業は、定数をプリプロセッサシンボルに変更する、関数に引数を追加する、変数の値を変更するの 3 つです。最初の例では、文字列の変更手順を示します。この作業は、cscope メニューのほかの作業項目とは少し異なっています。変更したい文字列を入力すると、cscope はそれを置き換える新しい文字列を聞いてきます。画面には古い文字列を含む行が表示されます。ここで、どの行に含まれる文字列を変更するかを指定します。

8.2.8.1 例 1: 定数をプリプロセッサシンボルに変更する

たとえば、定数 100 をプリプロセッサシンボル MAXSIZE に変更するとします。6 番目のメニュー項目「Change this text string」を選択して \100 と入力します。1 の前にはバックスラッシュを加えて、cscope のメニュー項目番号を意味する 1 と区別します。Return キーを押すと cscope は新しい文字列を聞いてくるので、MAXSIZE と入力します。

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: \100
Find this egrep pattern:
Find this file:
Find files #including this file:
To:  MAXSIZE

cscope は、指定された文字列を含む行を表示します。どの行の文字列を変更するかが選択されるまで入力待ちになります。

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: \100
Find this egrep pattern:
Find this file:
Find files #including this file:
To:  MAXSIZE

リストの 1、2、3 行目 (ソースファイル内の行番号はそれぞれ 4、26、8 行目) に含まれる定数 100 は、MAXSIZE に変更すべきだとわかります。さらに、read.c0100 (4 行目) と err.c100.0 (5 行目) は変更すべきではないこともわかります。次の単一キーコマンドを使用して、変更したい行を選択します。

表 8–3 変更する行を選択するコマンド

1-9

変更対象の行をマークしたり、マークを削除する 

*

すべての表示行を変更対象としてマークしたり、マークを削除する 

スペース 

次画面のリストを表示する 

+

次画面のリストを表示する 

前画面のリストを表示する 

a

すべての行を変更対象としてマークする 

^d

マークされた行を変更して終了する 

Esc

マークされた行を変更しないで終了する 

この場合、12、および 3 を入力します。入力した番号は画面上には表示されません。代わりに cscope は各行の行番号のあとに > (右不等号) を表示することによって、変更箇所を示します。

cscope 関数: 変更行のマーキング


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:
Select lines to change (press the ? key for help):

ここで、^d を入力して選択行を変更します。cscope は変更後の各行を表示し、作業の継続を促します。

cscope 関数: 変更後のテキスト行表示


Changed lines:

    char s[MAXSIZE];
    for (i = 0; i < MAXSIZE; i++)
    if (c < MAXSIZE) {

Press the RETURN key to continue:

このプロンプトに対して Return キーを押すと、cscope は画面を書き換えて変更行を指定する前の画面に戻ります。

次に新しいシンボル MAXSIZE#define 文を追加します。#define 文を追加するヘッダーファイルは、現在表示されている行の参照元ファイルの中にはありません。したがって、! と入力してシェルに入る必要があります。シェルプロンプトが画面の一番下に現れます。あとは、エディタを起動して #define 文を追加します。

cscope 関数: シェルへの一時移行


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

cscope セッションへ戻るには、エディタを終了し、^d を入力してシェルを終了させます。

8.2.8.2 例 2: 関数に引数を追加する

関数に引数を追加するには、関数そのものを編集することとその関数が呼び出されているすべての箇所に新しい引数を追加することの 2 つのステップがあります。cscope を使用して簡単にこのステップを実行できます。

まず、2 番目のメニュー項目「Find this global definition」を使用して、関数を編集します。次に、その関数がどこで呼び出されているかを探します。4 番目のメニュー項目「Find functions calling this function」を使用すると、ある関数を呼び出しているすべての関数のリストを表示することができます。このリストを使用して、リストの各行番号を個々に入力してエディタを起動するか、または ^e を入力して、各行のすべての参照元ファイルを対象にエディタを自動的に起動することができます。このような修正処理に cscope を使用すると、修正を必要とする関数はすべて修正され、見落とすことがありません。

8.2.8.3 例 3: 変数の値を変更する

変更内容がコードにどのように影響するかを見たいときに、表示手段として cscope が力を発揮します。

変数の値またはプリプロセッサシンボルを変更する場合を考えてみます。実際に変更する前に、最初のメニュー項目「Find this C symbol」を使用して、変更によって影響を受ける参照箇所のリストを表示します。それから、エディタを起動して各参照箇所を調べます。これによって、変更によるすべての影響を予測できます。同様に cscope を使用して、間違いなく変更されたことも確認できます

8.2.9 エディタのコマンド行構文

デフォルトでは、cscopevi エディタを起動します。EDITOR 環境変数に任意のエディタ名を設定して EDITOR をエクスポートすると、デフォルトを変更することができます。この手順については、「8.2.1 ステップ 1: 環境設定」で述べたとおりです。ただし、cscope は、使用するエディタのコマンド行構文が次の形式であるとみなします。


% editor +linenum filename

これは vi と同じです。使用したいエディタがこのようなコマンド行構文を持っていない場合は、cscope とエディタ間のインタフェースを定義する必要があります。

ed を使用する場合を考えてみます。ed では、コマンド行内に行番号を指定することができないので、そのままでは cscope のエディタとして使用できません。そこで、次のような行を含むシェルスクリプトを作成します。


/usr/bin/ed $2

ここでは、シェルスクリプトを myedit とします。環境変数 EDITOR の値をこのシェルスクリプトに設定して EDITOR をエクスポートします。

B シェルの場合は次のように入力します。


$ EDITOR=myedit; export EDITOR

C シェルの場合は次のように入力します。


% setenv EDITOR myedit

cscope は、指定されたリスト項目 (たとえば、main.c の 17 行目) を読み込んでエディタを起動するとき、次のようなコマンド行を使用してシェルスクリプトを起動します。


% myedit +17 main.c

myedit は第一引数の行番号 ($1) を無視して、第二引数のファイル名 ($2) だけを使用して ed を正しく呼び出します。希望する行を表示および編集するには、適切な ed コマンドを実行する必要があります。すなわち、17 行目に自動的に移動することはありません。

8.3 不明な端末タイプのエラー

次のエラーメッセージが出力されることがあります。


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

このメッセージは、現在ロードされている端末情報ユーティリティー (terminfo) データベース内に使用端末が含まれていないことを意味します。TERM に正しい値が設定されていることを確認してください。それでもメッセージが出力される場合は、端末情報ユーティリティーを再ロードしてください。

次のようなメッセージも表示されることがあります。


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

「8.2.1 ステップ 1: 環境設定」で説明した手順に従って、TERM を設定してエクスポートしてください。