2007年3月1日

Alicia! Alicia!! Alicia!!!

Alicia というのは、この場合 Uniadex 社さんが開発した crash のフロントエンドソフトだ。
最新版は 1.1.4で、sourceforge に登録されたのが「2006-3-14」という実に『年度末』を意識したいいタイミングで更新が止まってしまっている。頼むよ…。

おおよそ1年経つと他のソフトはイロイロ進化していくわけで、そういう意味ではIPAのお金で開発するのはいいがその後の金策の目処が立たない場合、お金以上に人の努力が風化してしまうという、実にもったいない代物である。

その中でも最ももったいないのが、
このプログラムは perl の Term::ReadLine::Perl を前提にしている
という点だったりする。

ご存知の通り、perl は 5になってからオブジェクト指向もどきな記述も許すようになった。この事実と CPAN の発展のおかげで、perl には山のような…そう、文字通り山のようなライブラリセットがある。その中に、readline ライブラリを perl で実装する、というものがある。

Term::ReadLine::Stub というライブラリがスタブライブラリだ。デフォルトでもこいつは存在するが、コイツ自身はスタブなので本当の本当に最小限度の事しかしてくれない。オブジェクト指向と言った通り、もし独自の Term::ReadLine もどきのライブラリが作りたければ、Term::ReadLine::HogeHoge という名前で作ればよい。Term::ReadLine とメソッドなどの形式をきっちりあわせておけば、Term::ReadLine を使うように作られたプログラムは、全部あなたの Term::ReadLine::HogeHoge でも動くことになる。

で、大雑把に言って、HogeHoge の部分には今、2種類の実装がある。Term::ReadLine::Perl Term::ReadLine::Gnu の2つだ。

Term::ReadLine::Perl は、結構昔からある実装で、deprecated扱いである。ようするに、今これをベースに物を作ってもうまく動かないのだ。

Term::ReadLine::Gnu は、gnu readline ライブラリのフロントエンド perl ライブラリで、これを導入すると、Term::ReadLine のデフォルトが stub から Gnu に完全に override するという気合の入った代物だ。

さて。通常のオブジェクト指向であれば、Term::ReadLine::Perl と Term::ReadLine::Gnu は同居できる。もし、あなたが Term::ReadLine::Perl を使って何かしたければ、
$readline = new Term::ReadLine::Perl 'hoge';
とすればよい。Term::ReadLine::Gnu を指定する必要があるなら、
$readline = new Term::ReadLine::Gnu 'hoge';
になるし、どれでもいいや、というなら、
$readline = new Term::Readline 'hoge;
と初期化すればよい。あとは $readline->readline(); のようにメソッドを呼べばよい。

しかし、相手は perl。そうは問屋がおろさない。

問題は、Term::ReadLine::Perl は deprecated な理由。実は、Term::ReadLine::Gnu と Term::ReadLine::Perl のインストール順序と、利用するコードによっては、 $readline-> で参照しているはずの関数の一部が、Term::ReadLine::Gnu のもののままになっており、そいつが必要なメソッドを Term::ReadLine::Perl が実装していないため、実行時エラーを吐いて止まってしまうのだ。Aliciaにはどうやらこのような使い方をしている部分があるらしい。そして、Term::ReadLine::Perl しかインストールしていない環境でしかテストしていないらしいのだ。

厄介なのは、
$readline = new Term::ReadLine 'hoge';
のようにデフォルト利用に設定した場合、実は何が使われるかはインストール順序依存だ、という点にもある。環境によって、Alicia は動いたり動かなかったりするのだ。

実は直す方法は判っている。次のパッチを当てればよい:
diff -ur Alicia-1.1.4/lib/Alicia/ReadLine.pm Alicia-1.1.4-fix/lib/Alicia/ReadLine.pm
--- Alicia-1.1.4/lib/Alicia/ReadLine.pm 2005-03-03 13:47:00.000000000 +0900
+++ Alicia-1.1.4-fix/lib/Alicia/ReadLine.pm 2007-03-02 00:17:21.238375000 +0900
@@ -14,12 +14,13 @@
package Alicia::ReadLine;

use Term::ReadLine;
+use Term::ReadLine::Gnu;

@ISA = qw (Term::ReadLine);

sub new {
my $class = shift;
- my $self = new Term::ReadLine;
+ my $self = new Term::ReadLine::Gnu $class;
return bless $self;
}

ようするに Term::ReadLine::Gnu を強要してしまえばよいのだ。

取り合えず、この方法で Alicia は動く。
問題は、Alicia を作った人たちが、Term::ReadLine::Perl を使ったと言いながら、Term::ReadLine で $self を作り上げている点だ。彼らは、Term::ReadLine::Perl の何に依存してコードを作ったのだろう? そこを踏むにはどうすればいいのだろう??
これが判らないと、テストもデバッグも出来ない…。