KAKASIの写経とバグ修正

Pocket

ここのところKAKASIのコードをいじっています。昔から再実装したいと考えていたのですが、コードを十分理解していない部分もあったので、目視でソースを見ながらエディタで書き写す「写経」的なことをやってみました。

写経の過程でいくつかの潜在的なバグが発見でき、本体にコミットすることもできました。内容は以下です。

それ以外にもいくつかコミットがありますが、直接的なバグではないもの(即値の代入、不適切なマクロ定数の利用、実害のないロジックミス)ばかりです。

それ以外にも問題はありましたが、それらは修正に関して検討が必要なものだったので、Tracにチケットを作る程度にとどめています。

写経したKAKASIのコードも一応gitにおいてあります。ただし動作検証は行っていません。あくまで実験として行ったものです。環境変数で辞書のディレクトリを指定すればおそらく動作はするはずです。

作業に関して、ソースの可読性を高めるため以下のことを念頭に行いました。

  • K&Rスタイルの廃止
  • 単純なマクロ定義だった定数をいくつかenum化
  • 配列定数として埋め込んでいたいくつかのテーブルを外部ファイル化
  • 文字エンコーディング定数でマジックナンバーだったものをマクロ化(dict.cのみ)
  • CMakeの採用

特に文字エンコーディングがらみはかなりわかりやすくなったのではないかと思います。旧来のコードの一部を引用してみます。

    while(*p != '\0') {
        if (*p == '\033') {
            if ((p[1] == '$') &&
                ((p[2] == '@') || (p[2] == 'B'))) {
                kanji = 1;
                p += 2;

ESC $ BというのはISO-2022-JPでG0をJIS X 0208に指定するためのエスケープシーケンスですが、これをマクロで以下のように書き換えました。

    while (*p != NULLCHAR) {
        if (*p == ESCAPE) {     /* ESC (0x1b) */
            if ((p[1] == G0_JISX0208_1ST) &&
                ((p[2] == G0_JISC6226_2ND) || (p[2] == G0_JISX0208_2ND))) {
                kanji = 1;
                p += 2;

コメントがなくても意味が理解しやすくなったと思っています。まだ道半ばではありますが、ゆくゆくはfrom scratchなコードを起こしたいと思っています。