CodeReadingWiki 改造版でソースコード解読

etherさん作成のCodeReadingWiki が、ソースコードを読むのにすごく便利で使わせて頂いていました。これはソースコードにglobalというツールでタグをつけ、Webブラウザから閲覧しながら必要に応じてソースコードにコメントを挿入できるソフトウェアです。

ソースコードはタグ付けされているので、簡単に変数や関数の定義位置に飛べたり、検索することができ、Webブラウザから閲覧できるので、複数の人とコメントを共有したりできます。

しかし、最近は更新が全然ないようなので、独自に少し改造しました。変更点は以下の通りです。

  • 見た目を変更
  • コメントはダブルクリックした行の下ではなく上に挿入
  • 複数のプロジェクトに対応 → データベースの構造を変更したので互換性がなくなりました。
  • コメントの検索機能を実装
  • Linux用のセットアップスクリプト作成
    • 元々のCodeReadingWikiはWindows前提でしたが、これはLinux前提です。mkcrwiki.shを移植すればWindowsでも動くとは思います。
  • ディレクトリ構造・ファイル構造を変更

スクリーンショット (gnu-globalのソースコードの例)

トップページ

crwiki01.jpg

コメントを入れたいソースコードの行(262行目)をダブルクリックしてコメントを挿入していることろ。

crwiki02.jpg

コメントを入れた後に、同じ行(262行目)をダブルクリックして、コメント挿入完了したところ。赤枠と赤文字でコメントが表示されます。

crwiki03.jpg

コメントの検索結果。global.cの262行目にfunctionというコメント文字列が存在しています。

crwiki04.jpg

ダウンロード

crwiki-mazn-0.2.tar.gz

インストール

動作確認はCentOS 5 + firefox 3.6 で行っています。手順はあまり詳細に書いていないので、不明点がある場合はコメントください。

MySQLのインストール

yumで簡単にインストール可能です。設定ファイル例はcrwiki-mazn-x.x.tar.gzに入っていますので参考にしてください。

# yum install mysql-server

MySQLのインストールの詳細は省略します。MySQL起動後、以下をMySQLに対して発行しテーブルを作成します。

CREATE DATABASE crwiki;
CREATE TABLE remarks (prj VARCHAR(65) NOT NULL, src VARCHAR(255) NOT NULL, line INT NOT NULL, remark MEDIUMTEXT NOT NULL, PRIMARY KEY(prj, src, line)) TYPE = MYISAM ;

PHPのインストール

# yum install php

PHP mbstring や php-mysqlのインストール

PHP関連の必要なモジュールをインストールします。

# yum install php-mbstring php-mysql

Apacheのインストール

Apacheはデフォルトでインストールされるので、必要に応じてApacheのルートディレクトリを設定してあげてください。ここでは、/home/www とします。

Gnu Globalのインストール

Gnuglobal はCentOSには付属していないので、ソースからインストールします。今回は global-5.8.2 で動作確認をしています。バージョンが異なると、globalで生成されるhtmlファイルに違いが出て、うまく動かない可能性がありますので注意です。

CodeReadingWiki (crwiki) のインストール

今回のディレクトリ構成は以下のようにします。

/home/www                        ・・・ Apacheのルートディレクトリ
       |--- crwiki               ・・・ crwiki用のディレクトリ
               |--- linux-kernel ・・・ 解読したいソースコード

crwiki をダウンロード・展開し、すべてのファイルを/home/www/crwikiのディレクトリに移動します。ファイルに含まれているファイルは以下のファイルです。

  • crwiki.awk          ・・・ globalで生成したhtmlを変更するためのawkファイル。mkcrwiki.sh から使われる
  • crwiki.js               ・・・ Webブラウザへ送信されるJavaScriptファイル
  • crwikiconf.cgi     ・・・ crwikiの設定ファイル。主にDBの接続設定を記述
  • crwikilib.php      ・・・ crwikiの処理を行うメインファイル
  • mkcrwiki.sh        ・・・ 解析実行用シェル。解析したいソースコードのあるディレクトリに対して実行する
  • style.css               ・・・ Webブラウザに送信されるスタイルシート
  • my.cnf                    ・・・MySQLの設定ファイル例。削除しても構いません

crwikiの設定を行います。MySQLに接続するためのホスト名、ユーザ名、パスワードを設定してください。

# vi /home/www/crwiki/crwikiconf.cgi
<?php
$dba_class   = "MySQLAgent";
$host        = "localhost";
$user        = "root";
$password    = "hogehoge";
$db          = "crwiki";
$db_charcode = "utf8";
?>

読みたいソースコードをcrwikiディレクトリにディレクトリを一個作って置きます。ここでは、linux-kernel というフォルダにLinux カーネルソースコードがあるとします。

ソースを置いたら、mkcrwiki.shでソースコードの解析をします。

#  cd /home/www/crwiki/
# ./mkcrwiki.sh linux-kernel

プロジェクト名を設定します。プロジェクト名はユニークにしてください。
デフォルトではディレクトリ名が入っています。プロジェクト名が空の場合は動作しません。

# vi linux-kernel/crwiki.php
<?php
// Prject Name
$prj = "linux-kernel“;
require ‘../crwikilib.php’;
?>

あとは対象サーバのURLにWebブラウザでアクセスしてください。

参考URL

http://rainyday.blog.so-net.ne.jp/2006-10-07

http://sourceforge.jp/projects/crwiki/


Cのコメント部分を正規表現で検索@vim

ソースコードを機械的に解析する際、コメントが邪魔だったりします。

viでコメント部分を削除しようとして、正規表現で以下のようにコメント部分を検索するとします。

\/\*.*\*\/

これは、/*で始まり、任意の文字列”.*”が続いた後に、*/で終わる部分にマッチしますので、

/* hoge */

というコメント部分にもちろんマッチしますが、実は最も長い部分にマッチするため、

/* hoge */ int a = 0; /* hoge */

は、int a =0; も含めてマッチしてしまいます。よって、/* と */の間にはコメントの閉じである*/がこないことを正規表現で表現する必要があります。

ここで、少し考え方が難しくなります。 じつは正規表現で否定を表現する場合、[^abc]と表現できますが、これはabcという文字列がこないという意味ではなくて、aかbかcがこないという意味なので目的にあいません。

よって、任意の文字”.”を[^*/]に置き換えた場合は、*または/ではないという意味なので、

\/\*[^*/]*\*\/

という正規表現は、

/* hoge/hoge */

という”/”を含んだコメントにマッチしなくなってしまいます。

では”*/”という文字列ではない という表現はどう表現すればよいのでしょうか。

正規表現では文字列否定専用の表現はありません。そこで”/” 以外の文字」と「直前が “*” 以外の “/”」と考えます。

これを正規表現と表すと

\([^\/]\|[^*]\/\)*

となり、/* と */の条件も付け加えると

 \/\*\([^\/]\|[^*]\/\)*\*\/

となります。

さらに、/* */は途中に改行が入る可能性があります。”.”は改行にはマッチしないので、改行の表現である”\n”をマッチの条件に追加して

\/\*\([^\/]\|[^*]\/\|\n\)*\*\/

となり、なんとか動いてくれたようです。複雑ですね~

これを使用することで、コメントの中にある文字列を探すことも可能になります。

上記を整理すると、Cにおいて 以下が改行を考慮した*/以外の文字列を示しているので

\([^\/]\|[^*]\/\|\n\)*

コメント内の文字列を探すには、探す文字列の前後にこの表現があればよいことになります。つまりhogeを探すならこのようになります。

\/\*\([^\/]\|[^*]\/\|\n\)*hoge\([^\/]\|[^*]\/\|\n\)*\*\/

なお、上記で説明した正規表現は、実はprintf などの文字列内にある/* */もマッチしてしまいます。他にも条件によっては動作がおかしくなる可能性があるので注意してくださ。

文字列を含まないというのを汎用的に表現すると、もっと難しく、さらにメモリ消費が激しいようです。参考サイトには文字列を含まない正規表現を自動生成してくれるJavascriptもありますが、maznの環境では動作が重く、実用に耐えられませんでした。

参考
http://blog.livedoor.jp/froo/archives/50581540.html
http://funcchan.blog16.fc2.com/blog-entry-39.html
http://www.kt.rim.or.jp/~kbk/regex/regex.html


screenコマンド覚え書き@Linux

ssh接続が切れても作業環境を保てたり、複数画面を切り替えられたり、画面上の文字列をコピペできたりと、かなり便利なscreenコマンドですが、少し使わないでいると使い方をすぐに忘れてしまうので、覚え書き。

まずは最低限の設定。

screenへ何かコマンドを送りたいとき Ctrl + aを使うのがデフォルトなのですが、Ctrl + aはコマンドラインでは行の先頭にカーソルを移動させる命令でよく使うので、maznはCtrl + oに変更しています。

~/.screenrc以下を記述するだけです。

escape "^Oo"

さらに、screenで複数の画面を使っていると、今使っている画面が何番かわからなくなるので、コマンドのプロンプトに画面の番号を表示するように変更。~/.bashrcに以下を追記。screenコマンドを立ち上げると、$TERMにscreenがセットされるようです。

if [ "$TERM" == "screen" ]; then
    export PS1='h:$WINDOW:w$ '
fi

さらに、KtermやPuttyのタイトルバーに出てくる文字列も変えたい場合は~/.screenrcにこう書く。

defhstatus "$USER@^EH_^En ^Et -- ^EW"

”user名@host名_スクリーン番号 スクリーン名 — 非アクティブなスクリーン名一覧”が表示されます。

screenの基本
※以下は、上記のCtrl+oへの変更はしておらず、screenへの命令はデフォルトのCtrl+aを使っていると仮定

screenを立ち上げて、hogeと表示してみる。

$ screen
$ echo hoge
hoge

screenから一時的に抜ける (デタッチという)

Ctrl+a d を入力

現在のスクリーン一覧表示。上で一時的に抜けたscreenが表示されます。

$ screen -list
There is a screen on:
        10230.pts-0.pc01 (Detached)
1 Socket in /var/run/screen/S-mazn.

デタッチしているスクリーンに再度繋ぐ(アタッチという)。上で打ったecho hogeが残っているのが確認できます。

$ screen -r 10230
$ echo hoge
hoge
$

画面上の文字列をコピー

Ctrl+a ESC を入力してコピーモードにする

矢印キーでカーソルを自由に動かせるので、コピーしたい文字の先頭に移動しスペースを入力。ここでは echo hogeをコピーします。

$ echo hoge
hoge
$

さらに矢印キーでコピーしたい文字列の最後に移動。

$ echo hoge
hoge
$

スペース入力でコピー完了。 さらにCtrl+]で貼り付け。

$ echo hoge
hoge
$ echo hoge   ← echo hogeがコマンドラインに貼り付けられる

リターンを押せばもちろんecho hogeが実行されます。

仮想の新しい画面を作る。

Ctrl+a c を入力

新しいシェルが立ち上がります。

$

今立ち上がっている画面一覧を表示。

Ctrl+a w  を入力

ターミナルの一番下に以下のように立ち上げている画面一覧が表示されます。

0-$ notitle  1*$ notitle

screen立ち上げた直後の画面番号が0、Ctrl+a cで作った画面番号が1で、”*”がついているのが今見ている画面です。

試しにgehoと表示

$ echo geho
geho
$

画面0に戻る

Ctrl+a 0  と入力
$ echo hoge
hoge
$

画面1に戻る

Ctrl+a 1  と入力
$ echo geho
geho
$

直前の画面(ここでは画面0)に戻る

Ctrl+a Ctrl+a と入力
$ echo hoge
hoge
$

まだ、いろいろできますが、書くのが面倒なのでコマンドと意味だけ。

次の番号の画面へ   Ctrl+a n または Ctrl+a Ctrl+n
前の番号の画面へ   Ctrl+a p または Ctrl+a Ctrl+p
現在の画面破棄 Ctrl+a Ctrl+k
bashにCtrl+a(カーソルを先頭に)を送る      Ctrl+a a
ウィンドウを分割する Ctrl+a S
分割したウィンドウを閉じる Ctrl+a Q
分割したウィンドウで他のウィンドウへ移る Ctrl+a I

できることはこんなもんじゃないです。詳細はmanでもみてください。


vimでシンタックスハイライトの関連づけ拡張子を追加する@CentOS 5.3

vimで.shの拡張子を開くと、シェルの構文がハイライトされるし、.c を開けばC言語の構文がハイライトされます。しかし拡張子がなかったり、拡張子間違っているとハイライトされません。

こういう時、例えばシェルモードでハイライトしたいときは

:set filetype=sh

とコマンドを打つことで色がつきます。しかし、毎回打つのは面倒ですよね。その場合、/usr/share/vim/vim70/filetype.vimに拡張子との関連づけを追加してあげることで、自動でハイライトさせることができます。

例えばC言語のファイル .c は以下のように定義されています。

au BufNewFile,BufRead *.c                      call s:FTlpc()

これを参考にし、例えば拡張子hogeをc言語として認識させるには以下のように追記してあげます。

au BufNewFile,BufRead *.c                      call s:FTlpc()
au BufNewFile,BufRead *.hoge                      call s:FTlpc()

スペースの入ったディレクトリ名やファイル名をスクリプトで処理する@Linux

findコマンドでスペース入ったディレクトリやファイルを検索し、その結果をforで処理しようとすると、スペースが区切り文字になってしまい、うまく処理できません。

その時はreadを使って以下のようにするとうまく処理できます。

tar.gzファイルを処理する場合
$ find . -name "*.tar.gz" | while read file; do echo "$file"; done