ぼくのDOSS奮闘記 〜LibreOfficeを手探ってみた〜 2/3

makeを無事終えたこの日の実験。全員がcalcの起動までできていたのでここからデバッガを動かしてみることにした。gnuplotの時に行った方法とは異なり、LibreOfficeでは開発用にこのようなコマンドが用意されていた。

$ make debugrun

これを実行することでgdbデバッグモードに移行する。何事もなくデバッガが立ち上がったように見えるが実は./autogen.shの実行時のオプションとしてつけた--enable -dbgutil がないとおそらくできなかったと思われる。つけ忘れていたらまたmakeし直しだったと思うと恐ろしい。

とりあえず上手いやり方もわからなかったのでgnuplotでやったようにmainにbreak pointを置いてrunしたのだが、この方法は完全に間違っていた。gnuplot程度の規模なら起動時点から動作を追っていけばいずれ所望の部分にたどり着くのだが、LibreOfficeはそんなことを許してくれる規模ではなかった。TAさんのアドバイスによれば、具体的に何を変えたいのかを決めてからそこの変更をするための部分をピンポイントで見つけ出した方が良いとのことだった。

そう、何を変えるかをまだ決めていなかったのだ。メンバーで話し合った結果、関数を用いた計算の処理に少し変更を加えようという話になり、まずウォーミングアップとして=Combin(9,2)と表記する組み合わせの計算を=9C2のように演算子のように書けるようにしようと決めた。今考えると、これをウォーミングアップなどと言っていた過去の自分を殴りたい。

ここからの作業がひたすら泥沼だった。とりあえず+や-などの演算子の記号と処理の対応づけをしているファイルがあるはずなのでそれを探すことにしたが、いくら探しても見つからない。というか探す出発点がまるで思いつかない。とりあえず思いつく演算子関連のワードを色々とgrepで検索してみるがいまいち見つからない。GUIでセルを選択した時に新たなスレッドが立つのでこのスレッドから流れを追おうとも考えたがこの作戦もうまく行かなかった。また困ったことにルートディレクトリからgrepをかけてもファイル数が多すぎるため検索ができないのである程度フォルダに検討をつけてgrepするしかないのだ。幸い、Calc関連のファイルがscというディレクトリにまとまっていることに気づいたので少し探索はしやすくなったのだが、このディレクトリ内にあるだろうという先入観がまた発見の遅れを生むことになる。3人がかりでクサいファイルの捜索にあたっていたが、丸々2日間ほどは大きな進捗は生まれずただ時間だけが流れていった。

4日目あたりでようやく演算子の定義に関する重要なファイルをいくつか発見できた。まず /formula/inc/core_resource.hrcというファイル(hrcってなんの拡張子?)に記号と実行する演算の対応表を見つけた。具体的には下のような感じ。

 

{ "+" , SC_OPCODE_ADD },
{ "-" , SC_OPCODE_SUB },
{ "*" , SC_OPCODE_MUL },

 つまり、追加したい演算子の文字と、それに対応する何かを関連づけている。このSC_OPCODE_ADDなどを定義している部分を探すと、include/formula/compiler.hxxにこれらを定義している部分を見つけた。 

 

#define SC_OPCODE_ADD 50
#define SC_OPCODE_SUB 51

また、include/formula/opcode.hxxには演算子を識別するtokenをこの定数に結びつけていると思われる部分を見つけた。

 

 ocAdd = SC_OPCODE_ADD,
ocSub = SC_OPCODE_SUB,

 

ocAddなどのtokenを実際の計算では使用すると推測されたので、この3つを書き換えることで新たな演算子を登録することができるのではないかと考えた。

また、ScCompiler::CompileStringという関数で入力文字列から演算子に変換すること、ScInterpreter::Interpretという関数で実際に計算をする関数に飛ぶ(ocAddならScAdd関数など)ことを突き止めた。この辺りを新しい演算子に対応させれば早くも動作するようになるのではないかと少し希望が見えてきたところである。

さて、ここで少し別の問題が浮上していた。makeをすると途中で落ちてしまうのである。どうやらTestで落ちているらしいのだが、実行するごとに違う部分でエラーを吐いてしまうのでとても困っていた。TAさんに聞いても根本的な解決方法はわからなかったため、いっそテスト自体を実行しない方法を探したほうが良さそうと言われた。探してみるとすぐにテストなしのmakeを行う次のようなコマンドを見つけた。

 

$ make build-nocheck

この方法でmakeをしたところ正常にmakeが完了したのでとりあえずこれで先に進むことにした。結局最後までtestが通らない原因はわからなかった...

さて、演算子の実装の話に戻ろう。表示されるエラーなどから演算子の文字として用いようとしている'C'はセル番号や関数名の先頭の文字と重なることから不適切であることがわかった。そこでおそらく何にも使われていないであろう'@'を'C'の代わりとして用いることにした。

ここまでで'@'が今回実装したいCombinationの演算子としては認識されたが、なぜか演算が実行されなかった。ここでまたしばらく足止めを食らうことになるのだが、再びgrepなどを繰り返し行った結果、formula/source/core/api/FormulaCompiler.cxxで木構造から演算の順序を決める処理をしている部分を発見した。つまり掛け算は足し算より優先して行う、のような取り決めをしている部分である。組み合わせ演算子は当然加減算よりは優先されるので、今回は累乗を表す演算子ocPowと同等の優先度を持つ位置にocCombinを配置することにした。

さて、6日間かかってようやく一つの演算子を追加することに成功した。全くウォーミングアップという内容ではなかったが、計算の流れをなんとなく追うことができたと思う。ラストの記事ではこの実装をもとに残り2つの機能の実装をどのようにしたかをまとめようと思う。