2007/12/31

積極的にユーザに問い合わせるべきだと思う

文字コードの自動認識についていろいろ調べてみると、少なくとも日本語では、完全な自動認識というのは不可能であるらしい。まぁ、当たり前と言えば当たり前だが。当然のことながら、Shift-JISとEUC-JPとASCIIとJISとでは、文字コードとして使用する値が部分的に重複している。もし、入力したテキストファイル中に、たまたま重複した領域の値しか含まれていなかったとしたら、機械には判断のしようがない。

極端なことを言うと、A~Zまでのアルファベットしか含まれていないテキストファイルを読み込んだとき、それをASCIIと判断するべきなのか、Shift-JISとするべきかEUC-JPとするべきか、あるいはJISなのかBIG5なのか、それはユーザにしか判らない問題だと思われる。

無論、そのほかの様々な情報を総合すれば、ある程度の推定を下すことも可能だ。例えば、ShifT-JISとEUC-JPとで重複している文字コードの領域というのは、Shift-JIS側では余り使用されることの無いであろう文字ばかりであるとか、言語や文字コードが違えば値の出現頻度が変わるとか(例えば英語ならスペースやeが多い)、使用しているロケールがjaならばEUC-JPである可能性が高くBIG5は余り使われないだろうとか、いろいろと考えることができる。

だが、そういった情報による判断は万能ではない。ユーザの中には変な文字ばっかり使いたがる奴だっているかも知れない。意味もなく旧字旧仮名を使う気色の悪い連中だって、世の中にはいるのだ。どんな奴がいるか、知れたものではない。

いずれにせよ、完全な認識ができない限りどんなに高い精度で予測しようとも、必ず文字コードをユーザに問い合わせる機能は必要になるということだ。ということであれば、認識精度はそこそこでも構わないから、判断がつかないのならつかないなりに、ちゃんと「判らない」という答えを返す方が重要なのではないかと思う。

つまり、間違った答えを本物と信じて、ユーザに何も問い合わせることなくそのまま処理を続行してしまうのは、よろしくないのではないかと思われる。それならば、積極的にユーザに問い合わせるべきなのではないだろうか。

2007/12/24

文字コードの自動認識

主筆」第19版を公開して以降、少しばかり開発を中断している。前にも書いたが、物の開発に対する意欲にはいくらか波があり、今はその谷間に来ている為である。とはいっても全く手を休めているわけではなく、エンコードの自動認識を行う機能を少しずつ作りつつある。ゆっくりとではあるが。

エンコードの自動認識は、今更自分で作り込まなくとも、既存の物がいくらでもあるような気もするのだが、いろいろと思うところがあって、結局自分で作ることにした。要は、「主筆」は日本語に依存したくないから、エンコードの自動認識機能も様々なエンコードに容易に対応できるようにしておきたかったのだ。

理論上は、世の中で使われているありとあらゆるエンコードに対応できるような自動認識機能を、自力で実装してしまえばいい。だが俺は、スワヒリ語やタガログ語はもとよりドイツ語やフランス語すら理解し得ない都合上、世の中全てのエンコードを使ってテストを行うことができない。つまり、英語と日本語以外のエンコードに対応できる自動認識機能は、俺には実装することができないのである。

ではどうすればいいのか。仕方がないからここは、俺には対応し得ないエンコードに対応する為のモジュールを、容易に追加・削除できるようにしておくしかない。そして後は、将来の俺か、あるいは俺以外の誰かに期待するしかない。

とはいっても、俺以外の誰かが俺にはできないことをやってくれるとは、到底思えないのだが。

2007/12/08

出処進退

第19版を公開し、Webページも更新したところで、Fire v250の方のOSを入れ替えることにした。どうにも環境の出来が悪く気に入らないためだ。ついでに、開発環境もSun Studio 11からSun Studio 12に更新することにした。

ところで、Sun Studio 12はSolaris 8には対応していない。ここでもし、開発用のソフトをSun Studio 12にしてしまったとしたら、Solaris 8は切り捨てなければならないことになるのだろうか?

確かに、今までの開発方式を踏襲するのであれば、そういうことになる。だが、残念ながら俺は、まだSolaris 8を見捨てるつもりはない。例えSunが捨てても俺は捨てない。

ではどうするのか? Sun Studio 12に乗り換えたときにSolaris 8で実行できるバイナリが生成できなくなるのは、Sun Studio 12がSoaris 8上で動作しないためである。つまり、Solaris 8で動作するバイナリを生成するためには、Solaris 8上でコンパイルしなければならないため、使用しているコンパイラがSolaris 8で動作しないとなると、Solaris 8用のバイナリが生成できないと言うことになるのだ。(WindowsではAPIの互換性さえ保っておけば、Windows XP上でコンパイルしたバイナリもWindows NT 4.0上で動作させることができるし、うまくすれば9x系でも動作する。だが、残念ながらSolarisはそういうことはできないようになっているらしい。)

だがここで一つ疑問が生じる。なぜ、Sun Studio 12を使って作られたプログラムは、Sun Studio 12でコンパイルしなければならないのか。C++で書かれているのなら、C++に対応したコンパイラを使えばコンパイルできるはずではないか?

確かにその通りである。少なくとも、CやC++で記述された範囲であれば、何もわざわざSun Studio 12でコンパイルしなくともForte developper 6.0でだってコンパイルすることができる(はずだ)。だが、そうでない部分が一箇所ある。それは、X-Designerで生成されたファイルだ。

GUIのデザインを作成するツールであるX-Designerは、設計されたGUIを独自のファイル形式で保存する。そして、コンパイル時には保存された独自形式のファイルを読み込み、Cのソースコードを出力する。問題はこの独自形式のファイルで、こいつは古いバージョンの奴で作られたファイルを読むことはできるのだが、新しいバージョンのX-Designerで生成されたファイルを、古いバージョンのX-Designerで読み込むことができないのだ。Sun Studio 11と12の互換性についてはまだ調査していないが、少なくともForte Developper 6.0 Update 2とSun Studio 11の間ではそういう関係になっていた。だから、Sun Studio 11と12でも同様であると考えた方が良いだろう。

つまり、一度でもGUIのデザインをSun Studio 12で編集してしまったら、金輪際二度とSun Studio 11には戻れないと言うことだ。だから、Son Studio 12がSolaris 8に対応していないと、Solaris 8用のバイナリが生成できないという理論が導き出されることになる。

だがよく考えてみれば、というかよく考えなくとも、Solaris 8上でできないのはX-Designerの独自形式のファイルからCのソースコードを生成する部分なだけであって、生成されたCのコードがあればForte Developper 6.0やSun Studio 11でコンパイルすることが可能なはずである。現に、一筋縄ではいかなかったとはいえ、似たようなことであれば、やったことはなくはない。

だから、うまい具合にMakefileを書いて、X-Designerで生成したGUIを表示するためのCのソースも一緒に配布してやるようにすれば、Solaris 8上でコンパイルすることも可能になるはずなのである。とはいえ、リンクするライブラリを配布する問題とか、いろいろとパス名が違う問題とかがあり、そう簡単にできることでもないのだが。

いずれにせよ、多少工夫してやればSun Studio 12に乗り換えてもSolaris 8を切り捨てる必要はなさそうである。

だが、ここにいたって別種の問題が持ち上がってきた。それは、Solarisの将来のバージョンではCDEがサポートされなくなることだ。前々からそんな話はなくもなかったが、ここに来て、CDEでログインする際に「将来のバージョンではサポートされなくなるから早くJava Desktop Systemに切り替えろ」という意味のメッセージが表示されるようになった。

見てくれが悪いからなのか共産主義者が多いからなのか何なのかは知らないが、世の中一般ではCDEは嫌われる傾向になるらしい。だが、誰なんと言おうとも俺はCDEが好きだ。GNOME何か死んでも使いたくない。あんな腐った鈍重なデスクトップ環境など、到底使用には耐えない。とはいえ、OpenWindowsと同様にSolarisでCDEが使えなくなるのは、もはや時間の問題である。

こうなると、さすがにそろそろ「主筆」の出処進退について考えなくてはならなくなるようだ。主筆はSolaris上のCDEで快適に動作することを特徴としている。そのCDEが無くなるとなると、「主筆」の居場所も無くなってしまうのだ。

どうやら、俺と「主筆」に与えられた選択肢は三つあるようだ。一つはこのままSolarisのCDEと共に心中する道だ。未だにCP/Mを使い続ける人がいるのと同じように、Solaris/CDEもこの世の中から完全に消えて無くなるまでには、相当の時間がかかるものと思われる。だから、このままCDEに拘泥し続けて残存者利益を享受し、最後はCDEと共にひっそりと消えていくという道が考えられる。

二つ目はネイティブのデスクトップ環境をJava Desktop Systemに替えることだ。なんだかんだと言っても、やはり時代はGNOMEやKDEに傾きつつある。これは致し方のない事実だ。ということで、「主筆」をJDS上で快適に動作するよう作り直すという方法が考えられる。だがこれは、GPL臭いものは嫌いだという俺の宗教観に真っ向から対立する道であり、そう容易には採用できない。そもそも、GNOMEをメインのデスクトップ環境として使うようにするのであれば、そもそもがSolarisである必要はなくLinuxに乗り換えてしまった方がマシである。

三つ目は、未だにCDEで頑張り続けている他の商用UNIXすなわちAIXないしHP-UXに乗り換える道だ。今の俺の心情では、この方向性が一番魅力的である。だが、それにはAIXないしHP-UXが動作するマシンを用意する必要があるため、それなりに経済的負担を負わなければならないという問題がある。

最近仕事で、HP-UXに触れる機会があり、その痺れるようにカッコイイCDEのデザインに心引かれつつある。やはり、売れなくなってきて共産主義者に媚びを売る様になった軟弱者とは格が違う。ログイン画面もへたれならログイン後の画面もいい加減で、俺の心の琴線を刺激してやまない。アレぞまさしく男のロマンだ。俺の目指すべき理想の姿がそこにある。

だがそうは言っても、俺の手元にある実弾は心許ない。もう少し戦線が回復できたら、HP-UXかAIXへの移行について検討することとしよう。とりあえずそれまでは、Solaris依存の部分を共通的な方式に変更する仕事でもやることにしよう。

2007/12/02

第19版の公開

とうとう「主筆」の第19版を公開した。

第18版との最大の違いは印刷機能が実装されたことだけなのだが、それでも公開するまでに半年以上の時間を要してしまった。

意外と地道に書き続けているblogを読み返してみれば、実は相当以前から印刷機能の実装に取り組んできていたらしい。一番古い記述は2007年1月22日にまで遡る。この当時はまだ第18版を公開していなかったことを考えれば、印刷機能の実装には随分時間がかかったものだと、言わざるを得ない。

だが、時間がかかったのは手を抜いていたばかりではない。純粋に開発工数が嵩んだためでもある。俺にとっては未知の言語であるPostScriptを勉強しつつ、それを出力するために必要となる多数のパラメタを入力させるインタフェースを作り込み、最終的にプリンタまで送り出すための出力処理など、思えば長い道程だった。

中でも特に苦しんだのが、エンコードの違いによる差異だ。印刷するとき、PostScriptの中でフォントを指定する必要がある。だが、そのフォントはエンコードによってそれぞれ別のフォント名を指定する必要がある。つまり、フォントはエンコードを意識するのだ。その為、そのPostScriptを生成する主筆側でも、ロケールに合わせてフォントを替えてやるようにしてやる必要がある。

だが、ここに一つ大きな罠がある。PostScript チュートリアル&クックブックを見ると、日本語環境において利用可能なフォントは、JIS・SJIS・EUCのそれぞれの環境におけるゴシック体と明朝体であると記載されている。だが、Solarisでは使用されるエンコードがUnicodeになる可能性がある。

もし単純に、PostScript内でのエンコードをカレントのロケールに合わせて、同時にフォント名もロケールに合わせて入力させるようにした場合、Unicodeでは印刷できないということになってしまう。

俺個人としてはUnicodeのロケールで使うつもりは更々無いのだが、とは言ってもロケールへの非依存は主筆の特徴として高らかに謳っていることでもあり、無視するわけにはいかない。

ということで、こういう事にした。まず、少なくとも日本語環境ではフォント名はEUCのものに固定する。当然、PostScript内に出力される文字列もEUCにする。それでもって、日本語以外の環境に対応するために、"PostScript内で使用するエンコード"をリソースで設定できるようにする。

こうすれば、例えロケールがUnicodeのものであったとしても印刷することが可能になる。

だがその為には、印刷前にテキストをEUCに変換してやる処理を入れなければならない。しかも都合の悪いことに、エンコード変換処理は別プロセスに切り出してしまってある。その都合上、エンコード変換はそう容易には行かない。

だが、容易には行かないとは言っても、やるしかないのだから実装した。パイプやテンポラリのファイルを駆使し、入力されたヘッダやフッタの文字列も含め、然るべくエンコードを変換するよう作り込んだ。

お陰で、印刷処理を行っているモジュールが随分肥大してしまった。単純に行数で行けば、このファイルが一番長い。仕方がないとはいえ、見苦しいことこの上ない。

だがまぁいいだろう。いろいろあったが、これで、テキストエディタとして最低限必要な印刷機能が実装されたのだから。

2007/11/18

第19版のコンパイル

主筆」第19版の配布用バイナリを作成するために、Solaris8でコンパイルしようとしているのだが、これがどうにもうまくいかない。時刻を取得するために使用しているlocaltime_rという関数が見つからないとか抜かし、コンパイルを完遂しないでいやがる。

原因はなんだか知らんが、どうやらSolarisとPOSIXの微妙な違いにあるらしい。とりあえず、ヘッダファイルとかマニュアルとかをみると、コンパイル時に「-D_REENTRANT」という指定を入れて、「_REENTRANT」というマクロがdefineされるようにしてやればいいらしい。

だが、この指定を入れるとスレッドやプロセスの扱いが微妙に変わるというようなことがマニュアルに書かれている。この微妙な変化が動作に悪い影響を与えなければいいのだが。

それにしても、今現在Solaris8はBlade 100のマシンにインストールしてあるのだが、これでコンパイルすると時間がかかってたまらない。64ビットで最適化を入れてコンパイルすると、すべての処理が終わるまでに25分掛かる。でもって、コンパイルの最後の方でリンクのエラーとかが出て、またやり直しになったりして、本当に疲れる。

しかも、そうこうしているうちにマシンの環境を破壊してしまい、起動しなくなってしまった。原因は分かっているので、うまくすれば復旧する事もできたのかもしれないが、面倒だから再インストールする事にした。

このところ立て続けに再インストールの作業を行っているから、さすがにそろそろ慣れてきた。Solaris8を入れた後に行う設定作業や、入れたり削除したりするパッケージ、あるいはその順番など、いくら物覚えの悪い俺でも体で覚えてきた。だから、インストールを始めてから1日ほどで元通りの環境を再現することができた。

今現在は、足止めを食らった分を取り戻すべく、Solaris8上でコンパイルを行っている。差具我にそろそろうまくいってくれても良さそうなものなのだが。

2007/11/13

Sun Studio 12

気がつくとSun Studio 12の日本語版が公開されていた。早速落としてみたが、まだ入れてはいない。

しかし、ダウンロードするファイルの容量がSun Studio 11の頃と比較して、大幅に増えている。1138.93MBもありやがる。しかも、bzip2で圧縮されている。

その上、Sun Studio 12はよく見るとSolaris 8には対応していない。ちょっとばかり、嫌なことになってきた。

2007/11/04

古いバグ

第19版を公開するために必要な作業はおよそ終了した。後はホームページの紹介の文章を多少いじくるだけでいい。だがその前に、二三気になる点を修正することにした。

そのうちの一つに、長い間原因不明のまま放置してきた、時々「主筆」が二つ起動することがあるという問題がある。これは、ファイルをダブルクリックしたり、あるいはコマンドで主筆を起動した際に、主筆が同時に二つ起動し、なおかつその双方ともが同じファイルを開いてしまうという現象である。

主筆では、同じファイルが同時に複数回開かれることの無いように制御を行っている。だがそれが時々うまくいかなくなるのだ。うまくいかなくなるだけならまだいいのだが(よくないが)、しかし、主筆サーバ内の制御ロジックは、同じファイルを開いた奴が複数個存在しないことを前提としている都合上、この問題が発生すると内部の状態が不正になる可能性がある。

しかも、このバグは滅多に発生しないという最悪な性質を持っている。そのため、いつかなる時にいかなる原因で発生するのか、追求に手間取った。というか、ほとんど対処できなかった。

当初は、この問題では起動する主筆は必ず二つであり、三つ以上になることが無いと言う事から、主筆サーバ内のロジックを疑っていた。主筆サーバでは、クライアントや主筆から受け付けた要求の処理に失敗したら、もう一度だけリトライするよう実装してある。つまり、俺はこのリトライ処理の周辺で何かおかしなことになっているのではないか、と考えたのだ。この周辺の処理、すなわち、主筆サーバが主筆を起動し、主筆サーバ内の管理リストを更新するまでの処理は、意外と複雑なことになっている。だから、この複雑なところが一番臭いと、そう踏んだのだ。

だが、事実はそうではなかった。よくよく調べてみると、結局原因はプロセスの起動処理にあることが判明した。

プロセスを起動する処理は、その処理結果として起動したプロセスのプロセスIDを返すようにしている。また、処理に失敗した場合には-1を返す。ここの処理に下らないバグがあり、生成したプロセスのpidによっては、起動に成功したにも関わらず-1が返されてしまうことがあったのだ。そのため、主筆サーバ内のリトライ制御によりもう一度起動処理が行われれ、結果として主筆が二つ起動してしまっていたのだ。

下らないバグというのの概要はこうだ。

プロセス起動では、親プロセスでforkして子プロセスを生成し、その子プロセスからさらにもう一度forkを行い孫プロセスを生成して、その孫プロセスがexecする。そして中間の子プロセスはそのまま_exitする。こうすることによって、起動された孫プロセスをinitの子として、ゾンビプロセスなどの諸々の問題を回避するようにしている。これは、ゾンビプロセスの発生を防ぐ古典的なんだそうだ。

主筆では、この処理の中で子プロセスはforkする以外にもう一つだけ仕事を行っている。それは、親プロセスに孫プロセスのpidを通知する処理である。すなわち、親プロセスは孫プロセスのpidを知り得ないから、子か孫に教えてもらわねばならないのである。

そして本問題の原因は、このpidの通知方法にあった。なんと恐ろしいことに、子プロセスはその終了ステータスとして孫プロセスのpidを通知しようとしていたのだ。でもって、親プロセスのその終了ステータスをもって、起動した孫プロセスのpidとして関数の戻り値としていた。

もうね、ほんとに俺はアホかバカかと。プロセスの終了ステータスは1バイトしか返せないのだから、pidを終了ステータスにして_exitしたら、その下位1バイトしか親プロセスに返されないに決まっているではないか。下位1バイトしか返されないのであれば、たまたまそのバイトが0xFFになることだってあるではないか。0xFFであれば、データの扱いによっては-1になることも十分にあり得るではないか。

結局、このバグがたまにしか発動しない理由もこれでわかった。下位1バイトがたまたま0xFFになるのが、たまにしか起こらないからなのだ。

原因がわかれば対処法も自ずと明らかになる。用はpidの伝達に終了ステータスは使えないのだから、おとなしくパイプで通知してあげるようにすればいいだけだ。ちょっと面倒だとはいえ、ほかに方法はない。

この対応を入れることにより、問題は解消されたはずだ。生成された孫プロセスのpidが確実に親プロセスに通知されることも確認できたし、孫プロセスの下位1バイトが0xFFになる場合においても、主筆が二つ起動されることがない事は確認した。

バグというのは、たとえどんなに不可解な現象で、原因が全く推定できないようなものであっても、わかってみればこんな下らない事だったのかと、思わずにはいられないものだ。こんな些末な、あるいはこんな明白なものであればもっと早くに気がついて然るべきだと、いつもそう思うのではあるが、それがなかなかそうもいかない。人間というのは不思議なものだ。

2007/11/03

CD-R

Solarisにパッチを当てる度、いつも二・三個失敗して余ってしまう物がある。どうやら8/07以降のSolarisに含まれているとか言うパッケージを入れねばならないらしい。ならば、それを落としてきてCD-Rに焼かねばならないのだが、しかし、俺の手元にあるCD-Rの残弾は心許ない。

普段CD-Rはバックアップ取得用に少しずつ消費しているのではあるが、LinuxやSolaris等、特にOSのディスクイメージを落としてきてインストールする場合などには、まとまって消費される事がある。

腐るものでも無し、まとめて買って備蓄しておけば、それでいいのかも知れんが、しかし普段の消費量が少ないことを考えると、つい買わずにいてしまう。そしていざという時に不足に泣く事となる。

最近では店に行ってもCD-Rがあまり売っていなかったりもする。ほとんどがDVD-Rであり、昔ながらのCD-Rは棚の片隅で埃を被っていたりする。ちょっと買うのが恥ずかしい。このままでは直に手に入らなくなるのではないだろうか。もはや100円ショップではCD-Rやフロッピーディスクが姿を消しつつあるように。

それを考えればそろそろDVDかあるいはBlu-rayディスクか何かにしたほうがいいのかも知れないが、しかしいかんせん、3年掛かりの超大作といえ圧縮すれば数MBにも満たないものをバックアップするのだけであり、640MBでも多すぎるのに、なぜにわざわざ金を出してまでまでして、いらんものを買わねばならないのか。

技術革新にはおおむね肯定的な俺とはいえ、やはり規格の乱立と製品寿命の短縮には賛成できない。「あなたの損は私の利益」という言葉は経済の本質を表したものではあるのだが、しかし、消費者の利益を害する企業に将来は無いというのもまた一面の真実である。

DVD-RがCD-Rの代用品として使えるのであれば、それでもいいと思うのだが、どうもそんなことができるようになっているとは思えないし、新しいドライブを買う気はさらさら無いし。かといって磁気テープもまた規格乱立と非互換の泥沼だし、何か良い方法はないのだろうか。

まぁ、新しいドライブが只で手に入れば全ては丸く収まるんだがな。

2007/10/28

ドキュメント

この土日は特にすることもなかったから、「主筆」のマニュアルの作成に費やした。おかげで日本語版マニュアルとプラグイン開発ガイドの第19版をあらかた準備し終えた。

内容の最新化は当然だが、それ以外にも一部デザインの変更や日本語の見直しを行った。また、今までは目次は手作業で作成していたのだが、ちゃんと書式を設定して自動で振られるようにした。今後の作業の軽減を考えてのことだ。

表紙のデザインは相変わらず右上に主筆のネェちゃんを配置したもののままだが、表題のフォントだけ変えておいた。何となく、プロポーショナルフォントの方がしまりがあって良さそうだったからだ。

残るは英語版のマニュアルだけである。書くべきことは日本語版のものにすべて記載されているのだから、それを英語に訳していけばいいだけなのだが、この作業が非常につらい。おまけに時間がかかる。

自由に英文の読み書きができればいいのだが、なかなかそうもいかず、毎回苦労している。それなのに、日本語版マニュアルの作成以上に全く持って報いられることはない。この正真正銘の無駄な作業は、やめるべきか続けるべきか。難しいところだ。



それと、全然関係ないことだが、さっきから文字を入力していると画面下部にある「今すぐ保存」がどんどん右に伸びていく。いったい何が起きているのだろうか。

2007/10/25

妥協

最近ようやく、「主筆」の印刷機能の実装が終わった。 本当であれば、まだいろいろな機能を付けたいと思っているのだが、いつまでやっていてもきりがないので、基本的な機能が通り一辺できたところで第19版として公開することにした。

後は例のごとくドキュメントを整備するだけである。毎度のことながらこれが辛いのだが。

しかし問題はどこまで詳細に書くか、という事である。印刷機能が増えたと言うことで、最低でも印刷の仕方だけ記載すれば、それで事足りるはずである。だが、ドキュメントの品質を考えた場合は、より詳細なトラブルシュートや構成変更についても記述するべきである。

しかし当然ながら、細かく書こうと思えば思うほど泥沼にはまり、いつまで経っても公表できなくなることになる。その上、英文ドキュメントも作成しなければならないことを考えれば、ある程度のどころで妥協するのは必要欠くべからざることである。

それに、「プラグイン開発者ガイド」の英文を用意するか否かという問題もある。ページ数が多いから今までこの問題には手を付けないできていたのだが、そろそろ本気で考えても良いかも知れないと思っている。まぁ、多分作らないだろうけど。

2007/09/30

八方塞がり

プリンタに食わせるPostScriptがうまく動作しない原因が分かった。

PostScriptのコードを生成する「主筆」側では、紙の大きさや余白の大きさを知ることはできるのだが、文字の大きさを知ることができない。これはフォントに依存する問題であり、PostScriptインタプリタから情報を取得できない以上、致し方のない問題である。そのため、文字をどこに印字するか、どこで改行し、いつ改ページするかといった制御は、すべてPostScript側の演算により決定するようにしている。

それを実現するためには、印刷する各文字について一文字ずつ大きさ(幅)を取得しなければならない。そしてそれを実現するためにcshowオペレータを使用している。

cshowオペレータは、与えられた文字列を調べ、一文字ずつ分解し、各文字に対して与えられた手続きを実行するという機能を持っている。だからこれを使えば所定の目的を達することができる、そう考えたのだ。

だが、問屋はそれほど心優しく卸してはくれないようだ。

cshowオペレータはマルチバイト文字を考慮した上での文字の分割を行い、各文字に対して所定の手続きを実行する。だが、その手続きの中でできる処理には、ある程度の制約がある。

制約の一つは、showオペレータにより印字できる文字が、cshowオペレータにより分割された当該の文字だけだということだ。たとえば、cshowオペレータに”あいう”という文字を渡して分割処理をやらせたものとして、そのうちの”あ”に対して実行された「所定の手続き」について考えてみる。

この場合、「所定の手続き」の中で印刷できる文字は”あ”だけなのである。それ以外の文字を印刷しようとすると、エラーが発生する。

制約の二つ目は、「所定の手続き」の中では、分割された文字の最後の1バイトしか取得できないと言うことだ。たとえば、先ほどの例でいけば、「所定の手続き」の中では、”あ”の下位(?)1バイトしか取得できないと言うことになる。

この制約のせいで、事情に困った現象が発生する。

まず一つは改ページができなくなると言うことだ。改ページ処理自体はいいのだが、改ページに伴って行わなければならないヘッダやフッタの印刷ができないのだ。何せ、cshowオペレータにより実行される「所定の手続き」の中では、cshowにより分割された文字しか印刷できないのだから。

そういうことなら、cshowであらかじめ文字列の分割を行い、いったん配列か何かに蓄積した上で改行なり改ページなりを行えば良いように思うのだが、しかし、chowから呼び出される「所定の手続き」の中では、分割された文字の最後の1バイトしか取得できないという制約がある。そのため、分割した文字を再構成して配列に格納するなどと言った処理を行うことができない。すなわち、分割された文字は「所定の手続き」の中で印刷してしまわなければならないと言うことだ。

いったいどうすればいいのか。

文字列はcshowの中で印刷してしまわなければならない。だが、cshowの中では改ページを行うことはできない。でもって、改ページを行うべきタイミングは、cshowの中でしか知ることができない。

この八方塞がりな状態はどう打開したらいいのだろうか。何か、良い手だてはないものだろうか。

2007/09/24

PostScriptのバグ

ようやく「主筆」の印刷ダイアログからプリンタに出力できるようになった。lprに渡す引数を構成するロジックと、パイプを使ってlprの標準入力にPostScriptのデータを渡す部分を修正したら、何とか動作するようになった。

だが、印刷結果を見るとまだおかしな部分があるようだ。どうも、生成されたPostScriptに間違いがあるようなのだ。

一部はごく単純に、PostScript生成プログラムに渡す引数が間違っていただけであり、すぐに修正できたのだが、簡単には直りそうもないバグがまだ残っている。

それは、おそらく日本語フォントに関連する問題なのではないだろうか。PostScript内で文字列を表示するためにshowというオペレータを使用しているのだが、これがエラーを発生するのだ。

プリンタにより出力されたメッセージによれば、Error nameがtypecheckで、Offending operatorがshow、Error info stringがnon-CID for CID fontとなっている。

具体的にどこのshowで何の文字を出そうとして落ちているのかまでははっきりと判っているのだが、それがどうして失敗したのかが皆目見当がつかない。

やろうとしていることは、単にデバッグ用に挿入した"ABC"という文字列をshowオペレータで表示しようとしているだけなのだが。

これはどうやら、まじめにPostScriptの赤本を読まねばならないようだ。

2007/09/23

印刷機能の進捗

思いがけないイベントや、印刷機能にまつわる開発量が予想以上に大きかった都合上、進捗はかなり思わしくない。

だが、ここに来てようやくPostScriptをファイルに出力するところまではできた。まだちゃんと動作確認を取ったわけではないのだが、とりあえずそれっぽいものをファイルに出力できるようになった。

後は生成したPostScriptをlprに喰わせる部分を作るだけだ。というか、この辺りも一応は作ったのだが、まだ動かしていないから何とも言えない。少なくとも、一発で動作するとは思えない。

lprが外部のコマンドなのは致し方ないとしても、PostScriptを生成する部分までもが別プロセスに切り分けてある都合上、全ての設定値を取得した後の実際に印刷する処理が結構大きくなってしまった。

まず、PostScript生成プログラムに喰わせる入力データをパイプに書き込み、それをPostScript生成プログラムの標準入力に繋ぎ、標準出力をlprの標準入力かファイルに繋がなければならない。

こういった処理は、シェル・スクリプト等で作っているのであればそう困難な処理でもないのだが、Cでゴリゴリ記述するとなると想像以上に辛い。特に、エラー処理を考えると複雑さは想像を絶する。

「主筆」は所詮フリーソフトであり、それ程難しいことを考えているわけでもないのだが、それでもそれなりにはエラー処理を実装している。だが、パイプやファイル・ディスクリプタの操作の周辺については、エラー時の処理は多少手を抜いてある。

「主筆」のエラー処理の基本的方針は、エラーメッセージを表示し、環境に悪影響を与えないよう後始末をしつつ、当該の処理を中断するというものだ。だから、ファイルを開いている場合であればそのファイルを閉じ、作業用にメモリを確保しているのであればそのメモリ領域を開放するようにしている。だが、ファイル・ディスクリプタの操作周辺では、エラーの発生箇所によっては、完全には環境を元通りしないで処理を中断してしまう部分がある。

無論、ただ手抜きの為だけにエラー処理をごまかしている訳ではない。環境を完全に元通りにするのが困難であるか、あるいは不可能であると判断したから、そのような手抜きの実装になっているのだ。

例えば、PostScript生成プログラムの起動について考えてみる。ここでは標準入力と標準出力をそれぞれ別のファイルやパイプなどに割り当ててあげなければならない。

このとき、標準入力をファイルに差し替えるのに成功した後で、標準出力の割り当ての変更に失敗したとしたら、どうだろうか。

単純な回答としては、変更してしまった標準入力を元に戻してから処理を中断するべきである。だが、標準出力の割り当ての変更に失敗した時点で、標準入力の割り当てを元に戻す処理を行うことができるのだろうか。失敗した原因が何であれ、その失敗した処理と同じ処理を行って原状の回復ができるとは思えない。

一応、上記の例では回復させる処理は明らかであるため、実装してあるにはしてある。ただ、いざというときには予想通りに動作するとは思えないだけである。

パイプ制御はエラー処理だけでも複雑なのだが、それ以外の正常系の処理もやはりそれ相当に複雑である。正直、ここまで作ってきて言うのもなんだが、そろそろ疲れた。

2007/09/22

休暇中の進捗

結局のところ、この数日の間は会社を休んだのだが、しかし「主筆」の開発は全く進まなかった。当然だが。

休みの間やったことといえば、葬式関係の諸々と実家で飼っているペットの世話と、時々かかってくる仕事の電話に応答しただけだ。なにせ、実家にはSolarisのマシンはないし、リモートで操作できるような環境を整えてあるわけでもない。だから、たとえどんなに暇でも開発作業を進めるわけには行かなかった。

だがそれはどうでもいい。作業が進まなかったからといっても、特に何を失うわけでもない。つらいのはテレビが見れなかったことだ。どうしても地方と東京近郊とでは放送しているテレビ番組が違うし、そもそも受信できない局もある。そのため、見たい番組のほとんど全てが見れなくなってしまった。これほどひどい状態に陥ったのは、生まれてこの方一度もない。

無論、俺自身出きる限りの努力は尽くした。だが、なにぶんイベントがイベントであるため、あまり表立った行動をとることもできず、結局のところ状況の改善には貢献しなかった。

開発も進められない、テレビも見られない、かといってそれほど忙しいわけでもない。仕方がないから本を数冊買って読んでみたが、それもすぐに終わってしまい、本当に暇だった。こうすることがないと、激務の本業に戻れなくなるのではないかと心配になる。だが、プロジェクトは日々遅延しつつあり、俺がどう思おうと職場には復帰せざるを得まい。さもなくば退職あるのみだ。

気だるいが、仕方がない。非日常はこの辺で切り上げて、つらい日常生活に戻ることとするか。

2007/09/19

職業

通夜でやるイベントのなかに納棺と呼ばれるものがある。直接的には遺体を棺桶に詰めるだけの作業なのだが、それに付随して遺体のメイク、すなわち死化粧が行われる。そしてこの作業は、その筋の専門家によりおこなわれる。

その作業自体は、決して気持ちのいいもではなかったが特に何の問題もない。ただ、気になったのは「専門家」なる人物が結構かわいい若い女だったことだ。死後硬直した親父の死体をまえに不謹慎な気もしたが、かわいかったものは仕方がない。

ところで、あの女は何を思ってあんな職業に就いたのだろうか。一般的に、職業としてのメイクといえば、生きている人間に対して化粧を行うものを言うのではないだろうか。死者に対して化粧を行うのは、そう一般的な生業とは思われない。彼女の人生がどういったものだったのかは知らないが、まさかこんな事を専属で行うことになるとは、なってみるまで想像だにしなかったに違いない。

いわれてみれば、俺は結構子供の頃からコンピュータ関連の職業に就くことを目的としていたように思う。少なくとも高校の進学先を考える時点で、そのことは明確に意識していたはずだ。

そのことがいいことだったのかどうかは判らない。目標に向かって一筋に突き進むことを良しとするか、世の中にどんな職業があるのかも判らない内に自分の将来を決定してしまうことを愚かと見るか、その評価は後になってから、自分が後悔しているか否かで決定されるのだろう。少なくとも、今の俺には何ともいえない。

とりあえず、あのネェちゃんがかわいかったということと、葬儀屋や医者に比べればSEという職業はドラマにはなり得ないということだけは、よく判った。

2007/09/17

葬式

親父が死んだ。倒れてから約20時間。その間の出来事は俺の人生における一大事ではあったのだが、しかし、驚いたのはその後の展開だ。

倒れて、病院に運ばれ、呼吸が停止し、徐々に脈が弱くなり、心電図のグラフがゆっくりと平坦に近づき、脈が検出できなくなり、医者に死を告げられた、その4時間後には葬儀屋の打ち合わせコーナーで式場の大きさを決めているのだ。

病院というのは人の命を救うべく、考え得るありとあらゆる手を尽くす場所、すなわち合理と科学の権化のようなところである。それに対して葬式というのは、文化や風習・宗教の要請により行う、いわば非科学的な儀式である。その間の切り替わりがあまりに性急で、戸惑ったわけでも、面食らったわけでもないが、感慨深いものがあったと思う。

文化の切り替わりついて、特に象徴的だと思ったのが、霊安室での出来事だ。葬儀屋が病院に到着すると、親父の遺体がICUから霊安室を抜け、葬儀屋の車に乗せられたわけだが、そのとき病院の用意した可動式ベッド(例のストレッチャーという奴だ)から、葬儀屋の用意したそれに乗せ変えられるという作業があった。

病院の所有物であるベッドで使用されている布団は、使い古した木綿の肌掛け布団、要は実用本位のものであるのに対して、葬儀屋のそれは、素材は知らないがテラテラと光る、それっぽい刺繍の入った重厚な布団である。遺体が移し替えられた瞬間に、俺が存在する文化の様式が全く異なったものになったのだ。

無論、その効用については疑うべくもない。竹内式に従い死亡宣告が下されはしたものの、外見的には何らの変化もない親父のそれを見ていると、むやみに悲しみがこみ上げてくる。だが、葬儀屋と一緒に俺の人生においてはあり得ないほどの額の出費について検討していれば、やたらと花飾りの個数にこだわる親戚に責め苛まれていれば、会社の上司や同僚に然るべき事務連絡を繰り返していれば、悲しいなどと言っている余裕は無くなる。もっと直接的に身に迫る問題に忙殺されていると、自分が何のためにそれをやっているのかを忘れてしまう。

だが、あまりに早急な存在様式の変化に、坊主に払わなければならない金額の大きさに、さすがの俺も驚いた。というか、面食らった。

以前、「お葬式」という映画があったが、あれはまさに正鵠を射ていると言えるのではないだろうか。我ながら人生の不思議さの一端にふれたように思う。

2007/09/09

lpr

UNIXで印刷するにはlprとか言うコマンドを使用する必要があるらしい。では、アプリケーションから印刷したい場合にはどうしたらいいのだろうか。単純にlprコマンドを内部で呼び出すしかないのだろうか。

まぁ、別にそれであってはいけない理由はないのだが、外部のコマンドを呼び出すのは、単純な関数呼び出しに比べればずっと複雑で面倒だから、できれば避けたいと思う。

更に、「主筆」ではテキストをPostScriptに変換する部分は別のプロセスに切り分けた都合上、lprへの入力にはPostScriptに変換する処理の標準出力を繋いでやる必要があるように思う。つまり、パイプ工事をしなければならないと言うことだ。面倒なことこの上ない。

面倒だ、ということは別に大した事ではないのだが、それ以外にも悩ましい問題がある。それは、呼び出すべきlprコマンドをどこで指定させるのか、ということだ。つまり、設定値をどこに持たせるのかという問題だ。

「主筆」の設定は、主に下記のような方法で変更できるようになっている。


  1. リソースファイル

  2. 環境変数

  3. 起動時の引数

  4. リソース数により指定された設定ファイル

  5. 環境変数により指定された設定ファイル



上記の内、「起動時の引数」の使用用途は明らかだから特に迷うことはない。だが、環境変数で設定させるか、リソースで設定させるかは、なかなか明確には決められない要因がある。

元々は、「主筆」の設定はリソースで行うようにしていた。だが、リソースでの設定内容はエディタ本体(すなわちTaEditというプログラム)の中からしか参照することができない。そこで、一部の設定を環境変数により行うようにした。

つまり、リソースと環境変数は、下記のように使い分けられると言うことだ。


  1. TaEditというプログラムで使う設定値はリソースに持ってくる。例えば、motifやXt・X周辺の設定や、メッセージ、UI関係の挙動など。

  2. TaEditというプログラム以外で使用される可能性のある設定値は環境変数に持ってくる。例えば、TaEdit自体や主筆サーバ・クライアント・エンコード変換などの各プログアムのパス名や、エンコード変換で使用する設定値などがそうだ。



このルール自体は明確であり、これに従えば、ある設定値をリソースに持ってくるか環境変数にするかを悩む事はないはずである。だが、そうすると気持ちの悪い事象が発生することになる。

環境変数には、使い分けの都合上、「主筆」で起動される各種プログラムのパス名が記述されることが多い。例えば「TaEdit……」というプログラムのパス名は、全て環境変数で指定するようにしている。

だが、lprコマンドはエディタ本体でしか使用しない。つまり、上記のルールを適用するとリソースに設定するべきものとなるはずである。それでいいのだろうか。

上記のルールは、あくまでも開発する側の理論であり、ユーザからすれば全く関知しない世界の事である。それなのに、あるプログラムのパス名は環境変数で指定し、別のプログラムのパス名はリソースで設定するというのはどうだろうか。ユーザにとっては理解しがたいことのように感じられないだろうか。

つまり、リソースか環境変数かという区分は、上記のように、その設定値を使うプログラムが誰かということから決定するべきではなく、むしろ、ユーザ側から見た何らかの基準に従い分類されるべきなのである。例えば、UI関係(色やフォントなど)はリソースで設定するが、実行時の環境(プログラムのパス名など)は、環境変数で指定させるなどいったように。

ユーザ側から見た理論に基づいて分類するとなると、各項目ごとにそれぞれ人間的な判断が必要になり、技術屋としては気持ちの悪いことこの上ない。だが、一般人からみれば、技術屋の言うことの方が理解不能で気色の悪いことであるものだし、こういった価値判断の重要性は忘れてはいけないことだとも思う。

でもまぁ、どうでもいいっていえば、どうでも良いことなんだがな。

2007/09/02

壁紙のエロ画像

電車内で通信制大学のレポートを片づけようとしてsigmarionIIIを取り出し開いたのはいいが、壁紙が思いっきりエロ画像だった。隣に座っていたガキ(女)に見られたような気がしたが、まぁいいか。

当初の予定では夏休み中に「主筆」の印刷機能を実装し、第19版として公開する予定だったが、間に合わなかった。今は、印刷ダイアログが一通り動作するようになり、後はPostScriptを生成するプロセスを起動して、lprに渡す部分を実装する部分が残っているのみである。

もともと、PostSctiptを生成するプログラムには、紙一枚に複数ページを縮小して印刷する機能は実装しないつもりでいた。だが、印刷ダイアログに勢いで「N-Up」という項目を付けてしまったから、先の機能もちゃんと作っておくことにした。

追加する処理の内容としては、印刷する内容を縮小して、回転して、然るべき位置に移動させるだけだから、基本的には難しいことではないはずである。だが、回転した後に移動する場合、どっちが上でどっちが下なのか、あるいは移動した後に回転すると、どこを中心に回るのか、縮小した後に移動する場合、それぐらいの距離を動かせばいいのか、それがなかなか把握しづらい。

同じ問題がOpenGLにおけるポリゴンの描画でも発生する。あの場合は、明確に行列演算という形で、どのように考えるべきかが示されているが、残念ながら俺には理解できない。OpenGLにせよ、PostScriptにせよ、これはいろいろやってみて感覚的に理解するしかないようだ。

2007/08/22

印刷ダイアログの作成

久しぶりの連休を使って「主筆」の開発作業を進めている。この数日は、今まで作ってきた印刷機能の実装を継続して行っている。

テキストをPostScriptに変換するところはすでにできているから、後は印刷ダイアログを作って、「主筆」の本体からPostScriptを出力できるようにしてやるだけだ。だが、この印刷ダイアログという奴がなかなかの難物であることが判った。

テキストをPostScriptに変換するには、数多くの引数を渡してやらなければならない。紙の大きさや方向・ヘッダやフッタ・余白などいろいろなパラメタがある。そいつらを全部入力できるようなダイアログを作ってやらなければならない。

Windows上でVBやVCで作るのであれば、それ程大したことでもないのだが、Motifで実現するとなると、意想外に苦労させられる。どうにもウィジットが思うような位置に行ってくれなかったり、リストやコンボボックスの使い勝手がよく分からなかったり、良い感じに入力制限をかけることができなかったりする。まぁ、これは前から判っていた事でもあるのだが。

それと、思っていた以上に開発工数が嵩んだのが、デフォルト値の指定と、一度入力された値の保存に関する機能だ。さっきも書いたが、入力項目の数が多い。その為、印刷する都度全ての項目を入力し直さなければならないというのでは余りにも使い勝手が悪い。だから、一度入力された値は、再度入力し直さなくても良いような仕掛けが必要となる。

方法としてはごく単純で、全ての入力項目を、ホームディレクトリ内にINIファイルの形式で出力してあげて、次に印刷する際にはそのINIファイルの中身を読み込み、デフォルト値として表示してあげるようにするだけだ。しかし、何分項目数が多いから、面倒なことこの上ない。

お陰で、印刷ダイアログの作り込みだけで夏休みが全部消えてなくなりそうな勢いだ。全く酷い話だ。だが、まぁいい。

それと全然関係ないのだが、印刷機能を作る傍ら、時々気分転換にホームページのデザインの変更をやってみたりもしている。とりあえず今日は、トップページにあるネェちゃんの絵を替えてみた。

暑い上にエアコンも壊れているから、水着にしてしまった。



ビキニではなくワンピースなのは、純粋に俺の趣味の問題だ。

まぁ、気が変わったらまた元に戻すことになるだろう。

2007/08/18

非X下でのxdesigner

主筆」はSun Studio 11に含まれているX-Designerを用いて開発されている。そのため、コンパイル時にもxdesignerというコマンドを用いて、設計されたUIを表示するCのコードを生成するようになっている。

当然だが、コンパイラやその他諸々のツール類は、コンパイル時に何らかのウインドウを表示したりするようなことはない。むろん、xdesignerもそうだ。

だが、このxdesignerというやつは、Xが利用できない環境下では動作しないことがわかった。

このソフトは、ウインドウを表示して、対話的にUIのデザインを行うソフトである。だから、基本的にはXが必須なソフトではある。これはわかる。だが、コンパイル時には対話的な動作はなく、単に入力ファイルを読み込み、Cのコードを出すだけだから、Xがなくても動くだろうと思っていたのだが、そうではなかったようだ。

コンパイル時のOSのバージョンに関する問題から、俺はリモートのマシンで自動的にコンパイルしてくれる環境を作り込んでいたのだが、上記のようなしょっぱい理由で頓挫した。どうやら、「主筆」をリモートマシンでコンパイルするには、その都度相手のホストにXで繋いで、その上でコンパイルしなければならないようだ。

面倒なことこの上ない。

だがまぁ、いいだろう。これは、それほど頻繁にある作業ではないはずだ。ないはずだが、こういった細かい事象が、モチベーションを少しずつ削っていく。それも事実だ。

どこかで、気が向いたら是正するようにしよう。

2007/08/14

リモートマシンでの自動コンパイル1

「主筆」では、一応ソースコードも配布している。しかし、ソースコード配布用の圧縮ファイルは、今まで全て手作業で作っていた。しかしそれだと、どうにも面倒くさい上に間違えやすいため、自動化することにした。要は、ファイルを集めて圧縮するコマンドを羅列したシェルスクリプトを作成するだけなのだが。

今まで、俺が使用しているFire v250にはSolaris 8を入れてあったのだが、何となく気に入らなくなってきたからSolaris 10に変えることにした。しかし、そうなると問題が一つ発生する。今までSolaris 8を使ってきた理由でもあるのだが、Solarisでは下位のバージョンのOSでコンパイルした実行バイナリを上位のバージョンのOSで動作させることはできるのだが、その逆はできないということになっている。だから、「主筆」は意図的に古いOSの上で作るようにしてきた。

だが、それを無視して開発用のマシンにSolaris 10を入れるのであれば、それ相応の対処が必要になる。だから俺は、ある特定の目的以外には余り使用していないBlade 100(Solaris8が入っている)でコンパイルしてテストすることにした。だからその為に、簡単なコマンドだけでリモートのマシン(つまりBlade 100のホスト)でコンパイルできるような環境を整える必要があった。そういった意味でも、ソースコード配布用の圧縮ファイルの自動生成が必要になってきたのだ。

本来なら、余り本質的な事ではないし、もとより少ない時間を割いて作っているのだから、こういった作業には時間をかけたくないのだが、やらねばならないものは致し方がない。

とりあえず、昨日の夜の作業だけで圧縮ファイルを生成するところまではできた。後は、リモートのマシンにファイルを送って、コンパイルして、できたファイルを落としてくる処理を自動化するだけだ。だが、これは何か面倒な予感がする。

2007/08/05

熱帯夜

土曜日の夜は暑かった。あまりに暑くて、とうとう扇風機を買ってきてしまった。

エアコンはついてないことはないのだが、去年の夏から故障していて、完全に冷却する機能がいかれている。風は出るのだが、俺が普段寝ているところまでは届かない。それになによりも騒音が激しい。

最近では扇風機にもいろいろな形があるようで、どれにするべきか迷ったのだが、とりあえず最も普通の形のものの中で、一番安い奴にしておいた。

「タワー型」とかいう奴は、何か目新しくて興味を引いたのだが、あの形状であることに意味が見いだせなかったからやめておいた。また、最近出てきたサーキュレーターとかいう奴も、もとより故障したエアコンの代用品として買うのであるから、利点が見いだせなかった。だが、中には縦に三つ連なった奴があり大変興味がそそられたのだが、それも結局、金額的理由からあきらめた。

設置する部屋の都合や使用方法などを考えて、クリップで留めて使用するタイプの物も考えたのだが、どうにもこのタイプだと、タイマー機能が付いている物が見あたらなかったからあきらめた。また、卓上型の物も一時は考えたのだが、布団の付近に設置するちょうどよい台などが無いことから、これもあきらめた。

結局、逡巡したあげくに買ったのが、ごく一般的な扇風機だ。見ていて面白くも何ともないのだが、しかしいかんせん、安眠を確保するという至上命題があり、そのために購入する実用品以上の何者でもないのだから、仕方がない。

興味本位で変な物を買って失敗するわけにはいかなかったのだ。

このあたりは、Sunのマシンを2台も買ったことによる反省が生かされている様だ。

2007/07/27

多忙

このところの、本業の非人道的なまでの多忙も落ち着き、ようやくまともに土日を休むことができそうだ。

振り返ってみれば、今年に入ってからやたらと忙しくて、私的なことに費やす時間が全く取れずにいる。お陰で、ホームページの更新も「主筆」の開発も滞っている。

だが、「主筆」の方は長年の懸案だった印刷機能の実装もすすみ、いずれは第19版として公開できるようになるだろう。何とかして、夏休み中には公開したいものだ。

ホームページはそれに比べると事態は深刻だと思う。4月にC言語の構文解析に関する駄文を公開したきり、全く手を付けていない。最近ようやく伸びてきたアクセス数も、このままでは少なくなってしまう。

少しずつでも良いから、何か賞味期限の長いネタを書いていくようにしなければならないだろう。

2007/07/16

プリンタ

俺が、「主筆」への印刷機能の実装のために買ったプリンタは、KONICA MINOLTAのmagicolor 2550という奴だ。これは、PostScript対応プリンタの中では、俺が見つけた限りもっとも安い奴だ。だが、それでも送料込みで10万325円もした。

買ってから大分時間が経ってしまったのだが、この間ようやく、WindowsとSolarisの両方で印刷できるように設定した。Windowsで印刷できるのは当然だとしても、Solarisでちゃんとフルカラー画像や日本語を含むテキストが印刷できるのには、ちょっと感動した。

感動して、エロ画像を何枚か印刷してしまった。

ところでこのプリンタ、説明書の中にこんな記載があった。「この装置は、情報処理装置等電波障害自主規制協議会……この装置は、家庭環境で使用することを目的としていますが、……」

そうか、これは家庭用品だったのか。最大消費電力1100Wだが、印刷時にガクガクと騒音を発するが、てっぺんがかなり熱くなるが、家庭用品だったのか。まぁ、個人宅やそれに類する環境での使用がメインとなるのだろう。

全然関係ないが、以前某社製のブレードサーバの取扱説明書に、梱包用の袋はお子様の手の届かないところに片付けろ、という記載が書いてるのを見たことがある。ブレードサーバの袋で遊ぶお子様ってどんな奴なのだろうか。

そんなことはどうでも良いが、早速、この間から作ってきた、PostScript生成プログラムが生成したコードをプリンタに喰わせて、印刷させてみた。多少の調整は必要だったが、特に大きな問題もなく印刷できた。

後は、主筆本体の印刷機能の実装だ。これ自体もそう容易ではなさそうだが、まぁ、おりを見ながらボチボチ作業を進めるか。

2007/07/08

印刷機能の実装

時間がとれず、著しく進捗が悪いのだが、それでも何とか少しずつ「主筆」の印刷機能の実装が進んでいる。とりあえず今のところは、テキストを読み込んでPostScriptに変換する処理をあらかた作り終わった。

この処理は単純なフィルタであり、独立性も高いので、別プロセスとして作成することにした。必要な情報を引数で受け取り、変換前のテキストを標準入力から読み込み、結果を標準出力に書き込む。この機能を呼び出すためにはパイプを制御しなければならず何かと大変だが、ソフトウェア工学的な利点を考えれば、それだけの手をかけるだけのことはあると思っている。

今作っているのは「主筆」本体に付け加えられる、印刷ダイアログだ。この機能もうまくすれば別プロセスに分けることもでき無くもないのかもしれないが、なにぶんフォーカスの問題やMotifのなんやかやを考えた場合、「主筆」内の機能ととして実装するのが容易であるものと判断した。

ところでこの印刷ダイアログ、内部的な処理はほとんどないのだが、入力しなければならない項目が多いため、必然的にコントロールの数が多くなる。おそらく「主筆」内でもっとも複雑なダイアログになるだろう。Windowsであれば比較的こういったダイアログの制作は難しくないのだが、Motifだとどうにもうまく行かない。Widgetの配置やアタッチの設定などを試行錯誤しながら、どうにか満足のいくように作り込まねばならない。これが想像以上に時間を要する。だが、それができてしまえば、標準的なコントロールの固まりに過ぎないため、それほどの作り込みはいらないはずだ。

印刷機能を実装すると言うことは当然のことながら、実際にプリンタに出力していないことには、動作確認がとれない。だから、PostScript対応のプリンタを実際に買ってみた。しかし、いかんせんPostScript対応のプリンタは高い。かつ、俺の懐はそれほど暖かいわけではない。我ながら、何でこんなものを作るために、これほどの私財を投じなければならないのか、こんな苦労を背負わなければならないのか、自分の頭の悪さに嫌気がさす。月と6ペンスか。

全然関係ないが、この前まではこのブログ、sigmarionIIIからは投稿できなかったのだが、今日やってみたら、ちゃんとログインできた。一応、改善が進んでいるらしい。もっとも、処理族度が遅すぎて、どうにも我慢がならないのは、相変わらずだが。

2007/05/20

単位

奇跡的に、未だに続けている通信制大学についてだが、4月のクソ繁忙期まっただ中に試験を受けに行ってきた。でもって、最近その結果が返ってきた。

俺の専門外の奴、それも必修科目?みたいな奴があるのだが、それは正直言って絶対落ちたと思ったのだが、どうやら受かっていたらしい。一応、結果の通知書には評価が書かれているが、それによれば問題の科目はCだった様だ。だが、それはどうでもいいことだ。要は単位が取れさえすればいいのであって、試験で何点とろうが、最終的な結果に変わりはないのだから。

4月の試験で、大体全体の内の4分の1ぐらいが終わったことになる。しかし、大学とやらに入ったのが昨年の10月であることを考えると、かなり進捗が悪いと言わざるを得ない。6月にもまた3科目ばかり片付ける予定だが、この調子では2年間での卒業は困難かと思われる。学費の事もあるので、できれば2年でけりを付けたいものだ。

とにかく、4月の受験結果から言えることは、余り得意ではないと思われる科目については、十分に試験勉強をしてから本番に望めと言うことだ。さもないと、単位を落とすことになりかねない。単位を落とすと後がやっかいだから、なんとしても受ける限りは取るようにしたいものだ。

2007/04/02

第18版の公開

 「主筆」第18版を公開した。公開したのはいいが、早速問題を見つけた。

まず一点は、文字列の検索時に、マッチする文字列が見つからなかったら、テキストの始めから検索し直すという機能を実装したのだが、このときに表示するメッセージが間違っていた。今までは「見つかりませんでした」という内容のメッセージを表示していたのだが、これを、機能に合わせて「見つからなかったから始めから再度検索するのか?」と、問い合わせるメッセージに変えなければならない。だが、その修正が漏れていた。

二点目は、おそらく前の物から潜在していたのだろうが、Undo機能にバグがあった。まず、何らかのファイルに対して編集を加えて、その次に別のファイルを開いて、そこでUndoを行うと、前のファイルに対して行った編集を、新しく開いたファイルに対してUndoしようとしてしまう。無論、そんなことをすれば何が起きるか判らない。最悪だ。

三点めは、これもおそらく潜在バグだろうが、発病する危険性はかなり低いと思われる。これはプラグインの管理に関わるバグだ。まず、プラグインの処理中にテキストを編集して、そのテキスト編集の後に(つまり一回の呼び出しの中で)、ファイルを開く、ないし、ファイルの保存を行い、さらに、プラグインの処理終了後にユーザが手動テキストを編集し、その上でUndoを行うと、ユーザが手動で編集したところのみならず、プラグインで行った編集内容もUndoされてしまう。バグが発病する条件が厳しいことを考えると、あまり大した影響はないと行われるが、やはりバグはバグである。

また、新しい機能も付けてみた。

まず、ファイルを保存した際にUndoを行うか否かを選択できるようにした。つまり、ファイルの保存時に、今までの編集内容を全て消すのか、あるいは残しておくのかを、リソースファイルにより設定できる。今までの挙動では、保存時にもUndoリストはそのまま残すようになっていたのだが、MS Office等を見ると、どうも一旦保存を行うと、それ以前には戻せないようになっているようなので、「主筆」でも一応そうすることができるようにしておいた。便利かどうかは判らないが。

2007/03/18

バグと機能拡張

主筆」第18版の機能拡張に着手する。とりあえず、変更が加わった行に印を付けて明示する機能を実装する。この機能には、拡張情報領域の機能を用いておいた。すなわち、更新されたら、所定のカラムの拡張情報領域にフラグを設定する。これにより、その行が更新されたのかを知ることができるようになる。

だが、その過程で幾多のバグがあることに気が付いた。まず一つは、行が追加・削除された時の、拡張情報領域の値の処理だ。今までは拡張情報領域に設定された値が、行の追加・削除に合わせて移動しなかった。例えば、10行目にフラグが設定されていたときに、5行目の行が削除されたとしたら、拡張情報領域のフラグが9行目に移動することが無く、そのまま10行目に残り続けていた。

始末の悪いことに、これは行の追加・削除が発生することにより、拡張情報領域の値として不正なメモリを参照していたことにより発生するバグだった。考えただけでも身の毛がよだつ。

プラグインの管理周辺でも、似たようなバグがあった。だが、これはまだ顕在化していなかった。しかし、おそらくおかしくなるのは時間の問題だっただろう。そのどちらも、対処しておいた。だが、似たような問題が他にもないとは、まだ言い切れない。確実に潰しておかなければならないだろう。

今ひとつのバグは、ファイルの排他制御に関するものだった。無名のファイル、すなわち新しいファイルを開いている「主筆」が複数ある状態で、二番目に起動された方で何らかのファイルを開こうとすると、初めに起動された方の「主筆」がアクティブになるだけで、目的のファイルを開くことができない。

これは、指定されたファイルがすでに開かれているか否かを判断する処理で、どちらかのファイル名が空白だった時には偽を返さなければならないところで、真を返していた事によるバグだった。

極めて単純なミスである。だが、なぜ今までこれで良いものだと思っていたのだろうか。思ったほど、ここのロジックが実行されることはなかったのだろうか。あるいは、正常に動作していないことに、気が付かないでいただけなのだろうか。それとも、存在して欲しくないものの存在を、無意識的に無視していただけなのだろうか。

このように考えていくと、プログラムを作ること難しさが、今更ながらに身にしみる。

2007/03/07

アクセス数の近況

このところWebサイトを更新していない。仕事が忙しくてそれどころではない。肝心要の「主筆」の開発が遅々として進んでいないのだ。Webページを追加したりしている余裕はない。

しかし、そのせいだろうか。アクセス数自体は、依然とさして変化していはないのだが、クリック数は極端に減少した。2月に至っては、クリック率は0.02%であった。

ここまで少ないと、ほとんど広告は存在している理由がないものと思われる。どっちにしろ糞忌々しいgoogleの商品なんだから、とっとと使うのをやめてしまうのも良いかも知れない。逆にその方が、Webページのアクセス数増加に貢献する可能性もある。

とは言っても、やっぱり地道にページを更新し続けるのが一番有効な方策なんだろうが。しかし、いくら何でも時間がなさ過ぎる。

今年は、5月の連休は無くなりそうだしな。

2007/03/06

用紙サイズの指定

諸般の障害を乗り越えて、ようやく「主筆」の印刷機能の実装を進められるようになったかと思いきや、今度はここのblogのアカウントを更新しろとぬかしやがる。

新機能が増えただの増えないなどの抜かしていたが、実際に更新処理をやってみると、いくつかの糞機能が追加されてますます重くなっていた。糞度充実。

日付と日付の表示形式のバグはようやくある程度対処されたようだが、それでもデフォルトの設定ではバグッたままのようだ。明示的に設定してやらなければまともに表示されない。結局、アメリカの連中は自分たちが世界だと思っているのだ。世界isアメリカ、アメリカis世界である。本当にクソクラエだ。

それはどうでもいいのだが、問題は印刷機能である。

PostScriptの仕様をちゃんと調べたわけではないのだが、どうもPostScriptでは用紙のサイズを直接的に指定する機能は無いような気がする。クリッピングの領域を指定することはできても、それと用紙サイズが一致するとは限らない。

だから、用紙を横向きにして出力する場合、用紙の向きやサイズを指定するのではなく、文字を横向きにして出力するのが手っ取り早い。だが、文字を横向きで出すとしたら、その為のPostScriptのコードを生成してやらなくてはならなくなる。

テキストを入力してPostScriptを生成するコマンドを実装するとき、用紙のサイズを指定するだけでは、上記の機能を実装する事はできない。すなわち、指定されたサイズの用紙をどう使うかという指定が抜けているからだ。

不足するのならその指定を追加してやれば良いだけの事ではあるが、それは何か冗長なような気がしてならない。だが、かといって、指定された用紙のサイズから向きを勝手に推定するのはありえないし、用紙のサイズを直接指定するのではなく、「A4」や「B5」といったサイズと向きを指定するのも考えにくい。なぜかというと、用紙のサイズは実は各国で微妙に異なるらしいからだ。特に、Bという大きさは日本独自らしい。そういうことで、用紙サイズは直接的な数値による指定から免れることはできない。

PostScriptに用紙の向きやサイズを指定する機能は、本当にないのだろうか? PostScriptの哲学を考えるとなさそうだが。

2007/03/05

日本語入力の問題

Solarisを入れ直して、パッチを当てて、「主筆」の第17版をインストールして、「主筆」第18版の印刷機能の実装に取りかかったときだった。

「主筆」で日本語が入力できないことに気が付いた。

原因は、入力された文字列を受け取るときに指定する、バッファの長さが1バイト足りないためであった。バッファが不足しているために、ステータスとしてバッファ不足を知らせる値が返ってくるだけで、肝心の文字列が取得できていなかったのだ。

だが、今までは正常に入力できていた。それは間違いないはずだ。何せ、今まで「主筆」の開発には「主筆」を利用してきたわけだし、そのソースコードには立派に日本語のコメントが記載されている。間違いなく、今までは入力できていたのだ。

ではなぜ入力できなくなったのか。

おそらく、パッチを当てたためだろう。Solaris8は、もうほとんど枯れたようなOSである。公開されるパッチも、大分数が少ない。そのため、このところパッチを当てる作業をさぼってきた。そんなときに再インストールして、全部のパッチをまとめて適用したのだ。おそらくそのときに、バッファ長を確実にチェックするように修正されたのだろう。

つまり、今までは指定したバッファの末尾1バイト分だけ、バッファ領域から溢れた部分にも書き込みが行われていたと言うことだ。通常この事が、それ程の悪影響をおよぼすというものでもないのだが、しかし、万々一ということもあるのだから、バッファ溢れは発生させてはいけないのだ。

バグが対処されたことはいいのだが、しかしそれでアプリケーションが動かなくなるのは辛い。とは言っても、既存のバグに依存したコードを書く方が悪いのだから、こればかりは文句を言うわけにはいかないのだが。

正直言って、第17版はバグが多い。もしかしたら、未だかつて無い粗悪な代物なのかも知れない。第18版であ、十分に注意するようにしたい。

2007/03/04

Solarisの再インストール

パッチを当てたらXが起動しなくなった。それ以外の部分は特に問題ない様なのだが、どうにもXが上がらなくて使いようがなくなってしまった。だから仕方がないから、Solarisを再インストールしておいた。

だが、再インストールしてパッチを当てたら、また同じ現象が発生した。これはどう考えても俺のせいではなく、パッチが悪いようだ。Solarisのパッチは時々環境を破壊してくれるから困る。

結局、XVR-100のドライバをアンインストールして、入れ直しておいたら元に戻ったからよかったものの、それでも直らなかったらどうしてくれるつもりだったのだろうか?

おかげで、このところの本業の忙しさと相まって、「主筆」の開発が大幅に遅れてしまった。正直言って、1月から開発は全く進んでいない。それもこれも仕事が忙しいからだ。生きるのに必要な時間すらも削って仕事をしているのだ。それ以外事に費やす時間などありはしない。

しかし、この調子でいくと、例の通信制の大学とかいう奴もやってられなくなるのではないだろうか? これは非常にまずい状況である。いつか会社を辞めるときのための保険なのに、会社の横暴のせいで保険料を払えなくなってしまうのだ。この状況は何とかしなくてはならない。

世の中一般では、仕事は程々に手を抜いて、忙しい振りをするという事が行われているらしい。俺も積極的にこの作戦を展開して、自分の心と体の健康と将来を守るための防衛戦に望まねばなるまい。

いずれにせよ、俺は命を張ってまでして仕事をするつもりはない。

2007/02/18

PostScript

PostScriptはスタックベースの言語らしい。

この手の言語は比較的種類が多く、親インタプリタな簡易言語みたいなものではよく採用されている方式だ。だが、実際にこの手の言語でまともにプログラムを作ることになるとは思わなかった。

「主筆」で印刷できるようにするにはPostScriptを生成できるようにしてやらなければならない。だが、単純にPostScriptを生成するとは言っても、プログラムでPostScriptのプログラムのロジックを考えて生成することはできないから、あらかじめ俺がPostScriptのプログラムの雛形を考えておいて、その雛形に印刷すべきデータを設定して、それを出力するという形を取らざるを得ない。

だから今俺は、印刷するデータをプログラム中に埋め込む方法や、設定可能な値の指定方法などを考えながら、PostScriptでプログラムを作っているのだ。

だが、これがなかなか大変だ。なにぶん、言語使用自体があまり人様が直接記述することを考慮して作られているものではない。そのため直感的にロジックを組むことができず、ひどく進捗が悪い。

その上、このところ本業の方がやたらと忙しく、まったく作業を進めることができなかった。何せうちに帰ってくる頃には12時を回っているし、ひどいときには始発で帰ることになる日もある。これでは他のことは何もできない。洗濯すらできない。

しかしこの激務もようやく脱したようだから、これからは少しずつでも作業を進められるようになるだろう。

2007/02/04

更新履歴

主筆」をバージョンアップすると、その都度更新履歴を書くようにしている。

別に、大した意味があるわけではない。だた、他のソフトでも大概にして更新履歴が書いてあるから、俺もそれに合わせているだけだ。俺自身としては、ほとんど何の意義も認めてはいないのだが。

しかし、この更新履歴という奴は、毎回書くときに結構苦労させられる。なぜならば、前の版からどこがどう変わったのが、案外覚えていないからだ。特に、バグの修正内容については、ほとんど何も覚えていない。

おそらく原因は、俺は常に作りかけの最新版を見ているからなのだろう。つまり、俺は今目の前にあるものを見慣れてしまっているから、前の版からの変更点に関する記憶が薄れてしまうのだろう。

この現象に対する対処法としては、ごく単純に、変更する都度メモを取っておけばいいだけなのだが、それは面倒だ。そもそも、こんな誰も使わないようなフリーソフトの更新履歴など、一体誰が見るというのだ。俺だって見ない。そんな、存在意義のほとんどない情報のために、なにがしかの手間をかけるのは、あまりにも馬鹿げている。

しかし、そうだとしたら、更新履歴を書くこと自体が馬鹿げているし、もっと言うなら、こんなくだらないものを作ることそのものが馬鹿げているといえる。

つまりここに、一つの葛藤を見ることができる。

「更新履歴を書くために、変更点のメモを取る」←→「主筆を開発する」。どちらも無意味な馬鹿げた行動だが、一方はやりたくなく、かつ、もう一方はやりたい。

俺の人生には、こういった矛盾がいくつかある。その中の一つに、破れたパンツを履くか否かという問題がある。

パンツというのは、ズボンの中に履くものであり、一般的に人に見せるものではない。むしろ、見せない方がいい。だから、パンツが破れていようが、いなかろうが、基本的には人にばれることはない。少なくとも、自分から人に向かってパンツが破れていることを告白するか、あるいは、パンツの破れているところを人に見せつけない限り、ばれることはない。

だから、破れたパンツを履いていたところで、社会道義的に問題となることはない。かつ、一枚のパンツを、できるだけ長く履き続けていた方が安上がりだ。だがしかし、何となく破れたパンツは履きたくない。

ここで一つの葛藤が生じる。

先ほどの、社会道義的な考えを延長すれば、パンツは履かなくても良いと言うことになる。つまり、たとえパンツを履いていなかったとしても、ばれることはないのだから、はかなくても良いと言うことになる。そして、パンツを履くことそのものをやめてしまえば、生活にかかるコストを削減することができる。

とはいっても、何となくパンツは履いていたい。しかし、破れたパンツは履きたくない。警察のやっかいにならない範囲内のことであれば、極限まで生活費を切りつめたい。だが、パンツは履いていたい。

結局、破れたパンツは履くべきなのか、履かざるべきなのか。

これについては、いくら考えたところで答えは出ない。どこかで線を引くしかないのだ。つまり、常に新品のパンツを履くようにするか、繊維の最後の一本になるまで履き続け、その後は一切パンツを履かないようにするか、その間のどこかで線を引かなければならないのだ。

俺に人生には、こういった葛藤、あるいは矛盾と言ってもいいかもしれないものが、いくつかある。普段は、出きる限り合理的に生きようとしてはいるのだが、しかし生きていることそのものが非合理の究極である都合上、人生そのものを完璧に合理化することはできない。

人生とは気持ちの悪いものだ。

2007/01/29

印刷機能の概要

実際にプリンタに出力する部分はおいておくものとする。とりあえずは、PostScriptを生成するところについて考えてみる。

まず、どういう機能が必要になるのだろうか。余り難しいことはやるつもりはない。だから、お手本として、Windowsのメモ帳を参考にしてみる。

ざっと機能を書き上げてみると、Windowsのメモ帳では、下記のような機能を提供しているようだ。
・上下左右の余白を指定する。
・紙の大きさを指定する。
・紙の向きを指定する。
・ヘッダとフッタを指定する。
・ヘッダとフッタを出力する位置を指定する。
・ヘッダとフッタには、通常のテキストの他にファイル名・ページ数・日付・時刻などを出力する事ができる。

また、PostScriptによる印刷の実行方式を考えると、フォントと文字の大きさを指定する機能も必要になるようだ。

(PostScriptで利用可能なフォントは、プリンタがプリンタ内に持っているフォントだけだ。だから、画面の描画に使用しているフォントを使って文字列を出力することはできないようだ。だから、印刷時用に別途フォントを指定する機能が必要になる。だが、あらかじめアプリケーション側で印刷後のイメージを生成しておいて、そのイメージを出力するPostScriptを生成してあげれば、任意のフォントを生成することもできるようだ。しかしそれは、俺にとっては余りにも負担の大きい手法だと思う。できればPoscScriptの持つ機能の範囲内で片付けたいものだ。)

では次に、実装の方法について考えてみる。

単純に考えれば、「主筆」本体にPostScriptを生成するロジックを組み込むことになる。しかし、そうすると「主筆」がますます肥大化することになる。だから、ここはプロセスを分割することを考える。ではどこで切断するか。

まず、PostScriptを生成する処理そのものは別プロセスの方に含まれるだろう。それと、できれば印刷時の設定を行うUI部分も切り離したい気もするが、それは難しいような気がする。つまり、モーダルとかモードレスとか、あるいは「主筆」が内部で保持しているデータをいつ別プロセスに渡すのか等と言ったことを考えると、切り離した別プロセスでUIを表示するのは利口とは言えないような気がする。

そういうことで、単純にPostScript生成処理だけを、独立したプロセスにすることにする。

では、そのプロセスのインターフェースはどうするのが良いか。用紙サイズや余白などの各種設定は引数で与えればいいだろう。印刷する文字列自体はどうするのがいいか。テキスト部分は量が増えることが予想されるから、引数というわけにもいかない。おそらく、別のファイルを読み込ませるか、あるいは標準入力から読み込ませることになるのだろう。

後は、エンコードの問題や、色を指定する機能に関する問題が残ってはいるが、当面はいいだろう。これだけ決まれば、何とか作ることができそうだ。

このところ、作業が一向にはかどっていないが、できるだけ時間を見つけて進めることにしよう。

2007/01/22

印刷機能

主筆」の第18版の機能として行番号を表示する機能を付けたり、あるいは第17版のバグの対策を行ったりしたところで、やる気が失せた。

行折り返しや、マネージャ機能・エンコードの自動認識など、実装しようと思ってはいるがやる気のでないものが沢山ある。だが、そういったものの中で、是非とも実装する必要があり、なおかつ今まで忘れ去られていたものが一つだけあった。

印刷機能だ。

今、俺が使用しているSolarisのマシンには、プリンタが接続されていない。何分、PostScriptに対応したプリンタは値段が高いのだ。だから、今まで印刷方面については、完全に放置していた。だが、今後はそうも行かないだろう。少しでも実用的なエディタを目指すのであれば、印刷する機能は必須であるといえる。

無論、Solarisで動作するエディタであるという必然から、印刷関係のデータは全てPostScriptで出力しなければならない。だから俺は、PostScriptの入門本のようなものを調達してきた。

それを読んで、とりあえずPostScriptの文法自体は理解したし、簡単な図形やテキストであれば出力できるようになった。だが、どうやって紙の大きさや紙の向きなどを指定すればいいのだろうか。その辺の具体的なロジックがいまいちよく分からない。

PostScriptの本によれば、PostScriptはデバイスには一切依存しないと書いてあるぐらいなのだから、おそらく紙のサイズや用紙の向きなどはSolarisとプリンタの間で決定されることなのだろう。だが、PostScriptを出力するアプリケーション側でも、ある程度は意識しなければならないはずだ。n-UPぐらいなやらデバイス側の処理でどうとでもなるのだろうが、横向きに印刷する場合や、不定型な紙に印刷する場合などは、デバイス側の小手先の処理ではどうにもならないはずだ。

そういったのは、どうやって処理したらいいのだろうか。

というよりも、実際に印刷できるプリンタがない状況で、アプリケーションに印刷機能を実装しようという時点で間違っているような気がする。

とりあえずは、プリンタなしでPostScriptを出力する機能を作り込んで、ある程度機能が実装できたら、中古でもいいのでプリンタを買ってみることにしよう。金はかかるが。

2007/01/21

減色アルゴリズムの並列化

減色するアルゴリズムのうち、各ピクセルにインデックス値を設定する処理を並列化することを考えてみる。

下記のようにピクセルがあるものとする。




ABC
BCD
CDE


誤差拡散法によって、各ピクセルに設定するインデックス値を決定する場合、上記の表におけるAのピクセルの値が決定しなければ、Bのピクセルを処理する事ができない。同様に、Bのピクセルの値が決定しなければCのピクセルの値は決定できない。

だが、逆に言えば、上記の表での同じアルファベットのピクセルは、並列に処理することができると言うことを意味している。つまり、Bのピクセルは右上にある奴を先に処理しても、左下にある奴を先に処理してもいいのだ。

だが、この知見をもとに、単純に並列処理を行うプログラムを実装したところで、処理速度は向上しない。なぜならば、並列化の粒度が小さすぎるからだ。1ピクセル単位の処理を並列化して、しかも必要に応じてロックや待ち合わせを行うようにしたら、シングルスレッドで処理したときよりも、大幅に処理速度が劣化することは目に見えている。

ではどうするのか。

粒度を大きくすればいいのだから、処理をブロック単位に分割することを考える。つまり、上記の表を、たとえば64×64のブロックとして考えるのだ。そして、一つのブロック内の処理は、シングルスレッドの場合と同じ方法で処理を行い、各部ロック間でのみ並列化を実施するようにする。そうすれば、同期や待ち合わせの負荷を相対的に小さくすることができるようになる。

だが、それにはいろいろといやな問題がつきまとう。一番難しいのは、ブロック間での誤差の伝播だ。一つのブロックを処理すると、そのブロックの右側と下側に、1列分の誤差が発生する。それを隣のブロックの左側と上側にピクセルを処理する際に、考慮に入れてあげなければならないのだ。

だがその難解さも、SMP構成のマシンで実行すれば、それに見合うだけの恩恵が得られる。ブロックの大きさにもよるのだろうが、うまくすれば処理時間を大幅に縮めることが可能となる。

俺はとりあえず、8192×4096・24bitカラーの画像を、16bitに減色する処理を、逐次と並列で実装してみた。そうしたら、逐次で約20秒程度かかっていた処理を、2CPU使って11秒程度に落とすことに成功した。

だがしかし、何が悲しいかって、8192×4096の画像は、ファイルサイズが96MBもあるため、それを読み込んで結果を出力するのに相当時間がかかると言うことだ。実は、減色処理自体よりも、そのファイル入出力にかかっている時間の方が長かったりもするので、並列化によるありがたみも半減してしまう。

ファイル入出力中のCPU利用率などを見ていると、結構CPUバウンドだったりもするから、ここの部分の並列化してあげれば、もっと早くなるかもしれない。

2007/01/14

背景画像用に画像を変換する

おもむろに、sigmarionIIIに背景画像を設定することを考えてみる。

こいつの画面の解像度は800×480、16bitカラーである。画像を800×480のサイズにすること自体は何の問題もない。何か適当なソフトで、画像のサイズを調節してやればいい。

問題は色の解像度である。単純にフルカラーの画像を背景に指定すると、色がなだらかに変化している部分に、かなり醜いしましまが発生することになる。まぁ、当然といえば当然だ。何分、16bitカラーなのだから。

通常、16bitカラーでは、赤に5bit、緑に6bit、青に5bitを割り当て、32段階・64段階・32段階の色の強さを表現するようにしている。緑が1bit多いのは、人間の目の特質によるものだそうだ。

そして、フルカラーの画像、例えば24bitカラーの画像が与えられた場合には、単純に下位のビットを無視することで画像表示を行うらしい。まぁ、余り金のかかっていないハードウェアで、高速に画像を表示しなければならないのだから、当然といえば当然の挙動だろう。

だがそのせいで、グラデーションのある画像の場合は、ありもしない縞模様が発生することになってしまう。そして、俺はこれが気に入らない。

ではどうすればいいのか。

そういう場合は、事前に画像の色数を削減しておいてあげればいいのだ。つまり、16bitカラーになることをあらかじめ判った上で、できる限り綺麗に見えるように変換しておいてあげればいいのだ。

ではどういう変換を行うのか。

それは、8bitカラーに削減するのと同じ処理をやってやればいい。ただ、唯一の違いは、任意のカラーテーブルを自前で生成するか、前もって与えられるかの違いだけである。つまり、16bitカラーでは、カラーテーブルは存在しないのだが、それを、65536色の固定的なカラーテーブルがあると考えればいいだけなのである。

そしてその上で、誤差拡散法で画像を変換してやればいい。そうすれば、16bitカラーに変換してもしましまの発生しない画像が得られる。

そういうことで、実際にやってみた。

本来であれば、ここで変換前の画像と変換後の画像を示して、ディスプレイの設定を24bitカラーと16bitカラーに変えることで、比較できるようにしてやるぐらいの事はしたかったのだが、しかし、ここの糞blogは、アップロードした画像を勝手にJPEGに変換するから、比較できなくなってしまう。だから、画像を示すのはやめる。

しかしいずれにせよ、ある程度は良好な結果が得られた。究極的には16bitカラーの制約を逃れることはできないが、それでも、極端な縞模様が発生することが無くなり、気分的には大分よくなった。

だが、シグマリオンIIIは、内部的な処理は16bitかも知れないが、ディスプレイの性能はそれ以下の様だ。古いから仕方がないといえばそれまでだが、しかし、変換後の画像をPCのディスプレイで見たときには目立たなくなっていた縞模様が、シグマリオンIIIに持ってくると結構目立つ。どうやら、もっと大胆に色数を削減するように変換してやる必要があるようだ。

また、真っ正面から見た場合、ディスプレイの真ん中と端の方とでは色が違って見えるから、それを考慮にいれた変換を行ってやっても良いかも知れない。

つまり、タコい液晶は、左右の方から見ると色が反転して見えてしまうのだが、シグマリオンIIIはその傾向がかなり酷い。使っているディスプレイが安物だからなのか、これが当時の最高だったのか、今となっては判らないが、いずれにせよ、酷い。

だから、その色の変化の仕方を定式化して、あらかじめ変化に備えて画像を変換しておいてあげれば、すこしは綺麗に見えるようになるだろうと考えられる。しかし、各ピクセル上における、画面と目線がなす角度の大きさは、顔の位置によって異なるから、この変換は一筋縄ではいかないと考えられる。

事前にできることと言えば、目玉がある位置をある程度推定した上で、目立たない程度に穏やかな変換を行ってやるぐらいだろう。

まぁ、これについても、今後時間があったら挑戦してみたいと思う。

2007/01/08

バグの修正

昨日気がついたバグを修正しておいた。

まず、カーソルがある行に表示する下線は、右端にちゃんと接するようにしておいた。また、拡張情報領域には引かないことにした。別に一番左側まできっちりと線を引いてもいいのだが、そうすると、拡張情報領域とテキスト描画領域を区切る線や、拡張情報領域に表示されたマークに、下線の跡が残ってしまうため、あえてやめておくことにした。

このバグの原因は、下線をどこからどこまで引くのか、という計算の間違いであった。線は、ウインドウの幅を取得して、一番左側(つまり0)から取得したウインドウ幅まで描画するようにしていた。しかし、取得したウインドウ幅というのが、すでに拡張情報領域の幅を差し引いた値であったため、結果として右側まで下線が届かなくなってしまった。

標準出力に引数が表示される問題は、その出力を行っていたデバッグ用のコードを消すことで対処した。

三つ目の致命的なバグだが、これは多少時間がかかったが、昨日のうちにつぶしておいた。

このバグの原因は、サーバ内で同一のファイルを開いているか否かを判断する処理に存在した。サーバ内で同じファイルが開かれているか否かを判断する処理は、単純にファイル名を比較する事で行っている。つまり、すでに開かれているファイルのファイル名を保持しているリストと、今度開こうとしているファイルのファイル名とを比較して、同じものが無いかどうかを比較しているだけなのだ。そのため、同一のファイルを指すファイル名であったとしても、ファイル名中に「.」や「..」が含まれていると、別のファイルとして判断してしまっていた。

しかも、たちの悪いことに、主筆内でファイルを開いたときには、ファイル名中の「.」や「..」を取り除く処理を行った後のファイル名を保持するようにしている。そして、その整形後のファイル名を主筆サーバに通知するようにしている。そのため、ファイル名中に「.」や「..」が含まれているファイルは、何度でも重複して開くことができてしまうという最悪の事態が発生していた。

そういうことで、主筆本体や主筆クライアントが、主筆サーバにファイル名を通知する際には、確実にファイル名の整形処理を行うようにしておいた。

単純に考えれば、ファイル名の整形処理は主筆サーバ側で行うべきだとおもうのだが、しかしこれはあえて行わなかった。なぜかというと、ファイル名の整形処理には、相対パスを絶対パスに変換するという処理も含まれているためだ。主筆クライアントや主筆本体のカレントディレクトリは、主筆サーバとは異なる可能性があるため、相対パスの解決は主筆本体や主筆クライアントではければできないのだ。そのため、結局呼び出し側で整形処理を行わなければならないのだ。

また、それに関連して、もっと根本的な対応策も導入しておいた。

そもそも、UNIXでは異なるファイル名で同一のファイルを参照することが可能なのである。「.」や「..」は単純なファイル名の操作で正規化を行うことにより、対応することができる。だが、ハードリンクやシンボリックリンクにより、同一のファイルに対して複数の名前が付けられた場合には、ファイル名の操作だけでは対処する事ができない。

そのため、直接的にファイルのI-Node番号とデバイスIDで比較を行う要に変更しておいた。これにより、ファイル名に依存しないでファイルの同一性を判断する事ができるようになった。

ただそうすると、ユーザが本当は同じファイルを参照している二つのファイルを、異なるファイルだと思って開こうとしたとき、主筆サーバのチェックに引っかかって開けなくなると言う問題が発生する。これは単純にユーザの問題ではあるのだが、しかし、だからといって何のアナウンスもなく開くことができないというのは不親切すぎるような気もする。

ここは、やはり何らかのメッセージを表示しておくか、あるいは新しいファイル名のファイルとして再度開き直すか否かユーザに問い合わせた方がいいのだろうか。

処理の実装は面倒だが、その方がいいだろう。

2007/01/07

行番号

前回、「主筆」の起動が遅いのはリソースを読み込んでいるからではないかと書いたが、実際はそうではなかったようだ。リソースの読み込み処理をスキップして起動するようにしてみたが、結局、起動時間はほとんど変わらなかった。

では、何が悪いのか。いろいろと調べてみたが、結局分からなかった。どうも全体的に処理が多いのが問題なようだ。これではどうしようもない。あきらめる他ないようだ。

だから仕方がない。起動処理の高速化はやめて、行番号を表示する機能を実装しておいた。行番号表示は前々から実装しようと思ってはいたが、ずっと後延ばしにしてきていた機能の一つだ。それを今回は思い切ってやってみた。しかし、実際やってみると案外あっさりと実装できてしまった。

現在まで行番号表示機能を実現してこなかったのは、それが表示処理周辺をいじることになるからだ。「主筆」では、テキストの描画はCTaEditDrawクラスで行っている。まぁ、それだけではないのだが、実際にXに対してどこに何という文字を描画しろ、と言っているのはこのクラスだ。

だが、このCTaEditDrawクラスはかなり肥大化してきている。やはり、実際にXlibで描画するとなると、どうしても「余分な詳細」が多くて、見通しが悪くなりがちなのだ。だから、俺的にはこれ以上いじりたくないと思っている。そのため、今までずっと放置してきたのだ。

ならば機能を分割すればいいだろうと思うかもしれないが、それもまた面倒だ。結局、いつかは手を着けることになるのだろうが、しかし、なかなか踏ん切りがつかない。まぁ、動いているものには手を出すなという原則もあるしなぁ。

それはいいとして、行番号表示を実装するときに、いくつかバグがあることに気がついてしまった。

まず一つ目は、カーソルがある行に引く下線だ。左側の拡張情報領域(ブックマークを設定すると赤い印が表示される領域のこと)を大きくすると、その分だけ下線が短くなる。拡張情報領域の部分に線が引かれないのならまだ分かる。だが、たちの悪いことに、右側が短くなるのだ。つまり、イメージとしては下線が左寄せで表示されているような状態なのだ。これでは言い訳のしようがない。

また二つ目は、「主筆」の起動時に引数を指定すると、与えた引数の一覧が標準出力に表示されることだ。これは、以前つけたデバッグ用のコードを消し忘れていたものだ。

三つ目は、メニューの「ツール」ー「同じ名前のファイル開く」のバグだ。これは、たとえば「a.c」というファイルを開いてきたときに、「a.h」というファイルを自動的に開くという機能なのだが、この機能を使ってファイルを開くと、ファイルの排他制御が効かなくなるという問題がある。つまり、「a.c」と「a.h」のファイルを両方とも開いている状態で、「同じ名前のファイル開く」の機能を使って「a.h」ファイルを開こうとすると、「a.h」を重複して開くことができてしまうのだ。

これは極めて都合の悪いバグだ。第18版では確実に対処しておかなければならない。

それにしても、なかなか安定しないなぁ。なんだかんだ偉そうなことを言っても、結局は常にテスト不足何だよな。これも、どこかでちゃんとしておかなければならないのは分かってはいるのだが。

2007/01/05

起動の高速化

主筆」第17版を公開してから数日の間放置していたが、昨日また少しいじり始めた。

最近、主筆の起動が遅くなってきたような気がするから、その辺りの高速化を図ろうかと思って、設定情報を読み込む処理をいじってみることにした。そして、とりあえずは、色名からPixel値を取得する処理に手を入れることにした。

Xで描画するには、色名からPixel型の値を取得しなければならない。だが、当然だが、この処理自体は描画する直前までに終わっていれば、それで問題ない。起動直後にやらなければならない必要性はどこにもない。だが、今までは設定情報を読み込む処理のところで、文字列の色名からPixel値に変換するところまでを片付けていたので、それをギリギリ必要になるところまで先延ばしするように変更した。

だがしかし、主筆で使用する色自体それ程たくさんあるわけでもないし、色名からPixel値に変換する処理がそれ程重いもではないため、結局の所、俺の努力はほとんど報われることはなかった。

今のところはまだ、正確に時間を計測したわけではないのだが、起動時における処理で処理時間を要するのは、おそらく主筆サーバの起動と設定情報すなわちリソースの読み込みではないかと考えている。

主筆サーバの起動は、ユーザーがログインした後一度だけ行えばいいことなので、ここではおいておくものとして、とりあえず対処しなければならないのはリソースの読み込み処理ではないだろうか。

しかし、この処理に要する時間の大部分はMotifないしはXt内の処理時間であって、俺がどうこうできるものとも思われない。つまり、対処するとしたら、設定情報を取得する元を、リソースから独自の設定情報ファイルに変更しなければならないと言うことだろう。

しかしそうすると、設定情報の記述形式を変更しなければならないと言うことになる。また、Xのリソースにはデータ型を変換してくれるという機能があるのだが、それが利用できなくなってしまうので、その処理を自前で作り込まなくてはならなくなる。そもそも、自前で作った読み込み処理が必ずしも高速であるとは限らない。よほど機能を落として、簡単な処理にするのであれば可能性はなくもないのだろうが。

ではどうするのが良いか。

変更を最小限に抑えつつ、リソースの読み込み処理を省略するには、一度読み込んだりソースをどこかに蓄積しておいて、二回目以降はそこから読み込むようにするという方法が考えられる。

蓄積する場所としては、どこかのテンポラリファイルでも良いし、あるいは主筆サーバに管理させても良いのだろうか。

だが、この方法にも問題がないわけではない。それはリソースが変更されたときの処理だ。参照先のリソースファイルが変更された場合には、環境変数の変化という形でそれと知ることができる。しかし、リソースファイルの内容が書き換えられた場合にはどうしたらいいのか。あるいは、起動時の引数としてリソースの値を指定されたらどうするのか。

リソースが更新されたら、コマンドなどでユーザが明示的にそれを通知するようにする、また、引数にリソースが指定されていたら、そのときは全ての設定情報をリソースファイルから取得する、という風にするという方式も考えられる。しかし、それを作りこむのが面倒そうだ。それに、ユーザの利便性を損なうのは避けがたいようだ。

どうするのが良いのだろうか。