global

標準では入っていないコマンドですが、globalと言うsource codeを見たりする時に、結構便利なツール類が存在します。これらはtag fileを作成し、これらをemacs等から読込むことによってタグジャンプを行ったり、変数や関数が相互参照可能なhtmlを作成してくれます。

gtags

gtagsコマンドは、カレントディレクトリ以下のソースを再帰的に走査して、ソース中のシンボルを集めます。そしてクロスリファレンスデータをタグファイル(GTAGS, GRTAGS, GSYMS, GPATH)に書き込みます。

gtagsコマンドのオプションは幾つかありますが、通常はファイルが存在する場所でを実行させるだけで、tag fileが作成されます。

# gtags
      

サポートしている言語は、C, C++, yacc, java, PHP,およびアセンブラです。それそれの言語は、拡張子で識別されるようになっているようです。

上記以外の拡張子を識別させたい場合は、/etc/gtags.confに設定すれば認識させるようにできます。

識別する拡張子を追加する

例えば、.php5という拡張子をphpとして認識させるようにしてみましょう。

最初に、/etc/gtags.confをエディタ等で開きます。/etc/gtags.confが存在しない場合はソースファイルからコピーします。

# cp gtags.conf /etc/gtags.conf
# vi /etc/gtags.conf
      

ローカルに設定したい場合は、.globalrcを作成してこれを編集します。

$ cp gtags.conf $HOME/.globalrc
$ vi $HOME/.globalrc
      

ファイルを開くとlangmapの記述あるので、ここに.php5を追加します。

common:\
        :skip=GPATH,GTAGS,GRTAGS,GSYMS,HTML/,HTML.pub/,html/,tags,TAGS,ID,y.tab.c,y.tab.h,.notfunction,cscope.out,.gdbinit,SCCS/,RCS/,CVS/,CVS
ROOT/,{arch}/,.svn/,.git/,.cvsrc,.cvsignore,.gitignore,.cvspass,.cvswrappers,.deps/,autom4te.cache/,.snprj/:\
        :langmap=c\:.c.h,yacc\:.y,asm\:.s.S,java\:.java,cpp\:.c++.cc.cpp.cxx.hxx.hpp.C.H,php\:.php.php3.phtml.php5:

htags

htagsコマンドは、gtagsコマンドで作ったtag fileよりHTMLを作成するツールです。このコマンドには、便利なオプションが数多くあります

-a
アルファベット順に並んだの関数一覧を作成します。
--caution
「ファイルが多いのでDownload Toolを使って全部落とさないでね」と注意書(英語だけど)を入れる。
-c, --compact
gzipを使用して圧縮したファイルを作成します。
--cvsweb URL
--cvsweb http://www.foo.bar/cvsweb/などとしておくと,現在参照しているファイルのcvswebへのリンクを作成してくれる。
--cvsweb-cvsroot cvsroot
cvsweb URL内のcvsrootを指定します。
-D, --dynamic
デフォルトでは関数などの参照リストは静的なページですが、これを指定するとCGIにより動的に作成されます。
-d, --dbpath dbpath
GTAGS GRTAGSが存在するディレクトリを指定します。デフォルトはカンレントディレクトリです。
-f
検索フォームを作成します。
-F
フレームを使用したページを作成します。
--full-path
ファイルインデックスのファイル名がフルパスで表示されます。
-g, --gtags
HTMLを作成する前に、gtagを実行させます
-I, --icon
リンクにicon画像を使用する。
--disable-grep
検索フォームのgrep機能を無効にする。
--gtagsconf
configuration fileの場所を指定する
--gtagslabel label
configuration fileのラベルを使用する。
--insert-header file
<body>タグの直下にカスタムヘッダを挿入する。
--insert-footer file
<body>タグの直前にカスタムフッタを挿入する。
--item-order spec
トップページに表示する項目を指定します。指定できる文字は次のようになります。
  1. c:caution
  2. s:search form
  3. m:mains
  4. d:definition
  5. f:file
デフォルトは、csmdfが指定されます。
-m, --main-func name
メイン関数名を指定します。デフォルトはmain
-n, --line-number[=columns]
行番号を付加します。デフォルトのcolumns(コラム幅)は4です。
--no-map-file
MAPやFILEMAPファイルを作成しません。
-o, --other
ソースファイルだけでなく、バイナリーファイルを除く他のファイルも対象にします。
--statistics
統計情報を画面に出力します。
-s, --symbol
関数だけではなくシンボルにもアンカーを付けます。GSYMSファイルが必要
-S, --secure-cgi cgidir
cgiを置くディレクトリを指定します。デフォルトは/cgi-binです。gtags.confの設定を書き換えて指定することも可能です。
-t
titleを指定
-T, --table-flist[=fields]
ファイルリストを<table>タグを使用して作成します。fieldsの値は行数の幅になります。デフォルトは5
--table-list
リストタグに<table>タグを使用します。
-v, --verbose
饒舌モード
-w, --warning
warningを出力します
-x
XHTMLで作成します。

私の場合、次のようなオプションを使い実行しています。TMPDIRをカレントにしているのは、kernelソースなどの巨大なファイルを処理すると/tmpがあふれるからです。

# export TMPDIR=./
# htags -afFIsx --line-number=5 --tabs 8 -t 'Foo Bar Title'
      

色を変える

htagsコマンドで作成したHTMLには、関数・シンボルやコメントに色がつきますが、固定された色指定となっているので、これを変更してみます。

これらの色を指定しているのは、gtags.confの一番下にhtagsの設定が書かれているので修正します。

htags:\
        #BODYの色
        :body_begin=<body text='#191970' bgcolor='#f5f5dc' vlink='gray'>:body_end=</body>:\
        :table_begin=<table>:table_end=</table>:\
        #タイトルの色
        :title_begin=<h1><font color='#cc0000'>:title_end=</font></h1>:\
        #コメントの色
        :comment_begin=<i><font color='green'>:comment_end=</font></i>:\
        # define文の色
        :sharp_begin=<font color='darkred'>:sharp_end=</font>:\
        # 括弧の色
        :brace_begin=<font color='red'>:brace_end=</font>:\
        :warned_line_begin=<span style='background-color\:yellow'>:warned_line_end=</span>:\
        # 予約語のスタイル
        :reserved_begin=<b>:reserved_end=</b>:script_alias=/cgi-bin/:\
        :ncol#4:tabs#8:normal_suffix=html:gzipped_suffix=ghtml:\
        :definition_header=no:	

グリーンで表示された場所を、自分の好きな色に変更し、htagsを実行すればOKです。

xhtmlの場合

htagsに-xオプションを付けて実行すると、xhtmlで出力されます。この場合、上記で修正した色は反映されません。その代わりにHTMLディレクトリにstyle.cssが作成されるので、これを修正すれば好きな色に変更できます。

自分の場合、下記のようなスタイルにしています。

/* BODYスタイル */
body		{
  background:  #333;
  color:       #eee8cd;
  padding:     5px 5px 10px 30px;
  font-size:   10pt;
}
A:link          { color: #CCCC66; }
A:visited       { color: #CCCC66; }
A:active        { color: #FFFF99; }
A:hover         { color: #FFFF99; }
.title		{ color: #cc0000; }
.error		{ color: red; }
.cvs		{ font-size: 90%; }
.caution	{ text-align: center; margin: 1em 40px; }
.left		{ text-align: left; }
.center		{ text-align: center; }
.right		{ text-align: right; }
img.icon	{ vertical-align: top; border: 0; }
th, td		{ white-space: nowrap; }
.tag		{ text-align: left; }
.line		{ text-align: right; }
.code		{ text-align: left; }
th.file		{ text-align: center; }
td.file		{ text-align: left; }
table.flist	{ border-spacing: 2px; width: 100%; }
em		{ font-style: normal; }
/* コメントスタイル */
em.comment	{ color: #ff4040; font-style: italic; }
/* プリプロセッサーのスタイル */
em.sharp	{ color: #ffa500; }
/* 括弧のスタイル */
em.brace	{ color: #a2cd5a; }
em.position	{ color: gray; font-style: italic; }
em.warned	{ background-color: yellow; }
em.string	{ text-decoration: underline; }
/* 予約語のスタイル */
strong.reserved	{ font-weight: bold; color:#c1cdcd; }	

指定ファイルの指定行をハイライト表示させる

プログラムの説明を書くとき、ソースファイルを一部を示して解説すると言うのはよくある事ですが、示すソースファイルが長いものだとページ全体が見難くなってしまいます。そんな時、リンクをクリックすればプログラムの説明する個所に飛んで、さらにその個所がハイライトされていると便利かも知れない。

例えばこんな感じでリンクにする。
OpenBSDではCPUの判定はlocore.sで行なっており、判定結果はメモリ上にストアされる。

phpを使ってそんな機能を行なうsearch.phpをつくってみました(結構適当に...)。search.phpは幾つかのパラメータを受け付けます。

endとoffsetが両方指定された場合は、endが有効になります。search.phpをHTML/S/に置かないとうまく動作しません。下記に簡単な動作説明を書いておきます。

該当ファイルを見つける

htagsで出力された、ソースファイルのhtmlはHTML/S/の下に作成されるようですが、変換後は数字.htmlと言うファイル名でで出力されてしまいます。この数字は、元のソースファイル名と一対一に対応付けられていて、globalではfid(file id?)と呼ばれているようです。

このfidはglobalコマンドで取り出す事ができます。例えばlocore.sのfidを取り出す場合は、下記のようにします。

$ global -P --result=ctags-xid locore.s
203 path                1 arch/i386/i386/locore.s
$
      

最初の値203がlocore.sのfidとなり、HTML/S/203.htmlがlocore.sのソースとなります

マッチしたファイルが複数ある場合は、結果も複数個出ています。

$ global -P --result=ctags-xid main
206 path                1 arch/i386/i386/mainbus.c  
2534 path                1 kern/init_main.c  
2598 path                1 kern/uipc_domain.c  
2622 path                1 lib/libkern/__main.c  
2921 path                1 net80211/ieee80211_regdomain.c  
2922 path                1 net80211/ieee80211_regdomain.h  
3168 path                1 sys/domain.h      
$
      

phpでは、globalコマンドをexec関数で呼び出してfidを取得します。

// グローバルコマンドの位置
$global_path = "/usr/local/bin/global";
// GTAGSファイルの場所
$tag_path = "/home/yanagimoto/public_html/contents/OpenBSD4.2/HTML/S/";

if(!empty($_REQUEST['filename'])){
    // GTAGSのある場所に移動して、globalコマンドを実行
    chdir($tag_path);
    $search_file=escapeshellcmd($_REQUEST['filename']);
    $result = explode("\n",trim(shell_exec("$global_path -P --result=ctags-xid $search_file")));
    // 複数ある場合は終わり
    if(count($result) > 1) die("too many file found!");
    // 無い場合は終わり
    if(count($result) == 0) die("file not found!");
}	

指定行へジャンプ

htmlの各行には<a name='L1'>等とアンカーが付いているので、body タグにonloadで指定行にジャンプするようにjavascriptを追加します。例えばstart=270だった場合は次のように編集します。

<body OnLoad="location.hash = 'L265'">	

ハイライトの指定

ハイライト開始行から終了行までに、スタイルを追加します。start=270,end=480の場合は、次のようになります。

<div style='color:#de9ede;background:#5a5d5a;margin-top:10px;width:100%;'><a name='L270'>  270 try386:
.....
<a name='L481'>  481 </div>	

xhtmlの場合は、class='reverse'を追加します。

<div class='reverse'><a id='L270' name='L270' />  270 try386:
.....
<a id='L481' name='L481' />  481 </div>	

"HTML/style.css"には、reverseと言うクラスは無いので追加しておくと幸せになれます。

/* ハイライトのスタイル定義 */
.reverse {
  color: #de9ede;
  background: #5a5d5a;
  margin-top:10px;
  width : 100%;
}	
Last modified: Wed Dec 19 22:08:14 2007 JST