この連載でも紹介してきたように、現在、手元ではPlamo Linuxの64ビット化作業を進めています。hot plugやネットワーク回りなど、調整しなければならない部分は多数残っているものの、年末年始の集中作業の結果、とりあえずこの原稿を64ビット版Emacs上で書ける程度には環境が整いました。
先に紹介したように、Core i7などx86-64機能に対応したCPUでは、32ビット用のバイナリを互換モードでそのまま動かすことができるので、32ビット用と64ビット用のバイナリが混在した環境で運用することも可能です。しかし、ディストリビューションの作成といった立場からすると、64ビット版は全て64ビット用のパッケージで揃えなければ格好がつかないので、一部の設定ファイルやスクリプト類を除き、既存のパッケージを全てビルドし直しています。
全パッケージの再ビルドというのは面倒な作業ではあるものの、ライブラリへの依存関係なども全て作り直すことになるので、メンテナンスレベルの更新では手を出しにくい、基盤的なソフトウェアのバージョンアップなどを行うことができます。
Plamoの場合、人手不足を口実に「壊れてないものは直さない」という立場でやっているので、セキュリティフィックス等の重要な更新が無い限り、「枯れた」ソフトウェアのバージョンアップは滞りがちです。今回の全面的な再ビルドは、そのようなソフトウェアの埃を払ういい機会ですが、実際にやってみたら使い慣れているはずのソフトウェアの新機能に戸惑うことがありました。今回はそのような事例を紹介してみましょう。
groffの更新
groffは、UNIX上で開発されたroffと呼ばれる組版ソフトをフリーソフトウェアとして再実装したソフトウェアです。
UNIX/Linux上で動く組版ソフトウェアとしてはDonald Knuth氏が開発したTeXが広く知られていますが、roffはTeXよりも古く、UNIXの開発元であるAT&Tベル研究所で開発された由緒あるソフトウェアです。roffはTeX同様のマークアップ方式の組版ソフトウェアで、1つのソースコードから画面表示用や印刷用などさまざまな形式の出力を得ることができます。
組版ソフトとは言うものの、pLaTeX等と比べると使い勝手はよくないので、最近ではわざわざroffを使って文書を書く人はいないでしょうが、UNIXのマニュアルページ(manページ)は伝統的にroffの書式で書くことになっており、現在のLinuxでもmanページはroff形式で書かれているので、表示するためにはGNU版のroffであるgroffコマンドが必要になります。
Plamo Linuxにもgroffのパッケージはありますが、manページの整形くらいにしか使わないので、Plamo-4.73まではgroff-1.17.2を使い続けていました。一方、groffの開発元であるGNUプロジェクトのサイトを見ると、groffの最新版は1.21になっています。そこでさっそく最新版をビルドして入れ替えてみましたが、日本語のmanページが表示できません。
groffは組版ソフトという特徴上、文字コードの扱いが重要になるため、従来は1バイト文字しか扱えないgroffに日本語を通すようなパッチを当てて使っていたのですが、調べてみると、groff-1.19以降ではgroff自身がUTF-8形式の文字コードを受けつけ、自身で日本語も含めたマルチバイト文字を処理できるようになったため、従来の日本語用パッチは廃止されたようです。
ざっとイジった感じでは、出力先をUTF-8(-Tutf8)に指定すれば日本語も整形してくれるようですが、行の折り返しや1バイト文字とマルチバイト文字の組み合わせの間隔調整などがうまく行かずに、ずいぶん間延びした表示になってしまうようです。
これらの不具合は将来のバージョンでは解決していくとは思うものの、日本語のmanページがきちんと表示できなくなるとgroffを更新する意味がないので、今回の更新は日本語パッチが用意されている最終バージョンである1.18.1.1にとどめておくことにしました。
謎のESCコード
ところが、groff-1.18.1.1では日本語manページも表示できるものの、表示結果はESCコードが多数混じった見苦しいものになってしまいます(図1)。
安定環境のマシンにログインして、同じmanページをgroff-1.17.2で見ると正しく表示されます。
おかしいなぁ……、と思って両者の違いを見るために、それぞれの出力結果をファイルに書き出してEmacsで読み込んでみると、groff-1.17.2(図2の下側のターミナル)では強調文字が^Hを使って表現されている(たとえば「名^H^H名称^H^H称」)のに対して、groff-1.18.1(図2の上側のターミナル)では強調文字がESCシーケンスを使って表現されている(たとえば「^[[1m名称^[[0m」)ようです。
強調や背景色などの文字飾りをESCシーケンスを使って実現するのはコンソールでは常套手段ですが、lessはそれらのESCシーケンスを文字飾りとは認識せず、ESCシーケンスをそのまま出力してしまうようです。一方、moreだとESCシーケンスを文字飾りとして表示するので、PAGER='more'とすればmanページは読めるようになりますが、スクロールバックや検索といったlessの便利な機能に欠けるmoreでは何かと不便です。
文字飾りの表示方法を古い形式にするような機能は無いのだろうか。。とgroff-1.18.1.1に付属のドキュメント類を眺めていたら、NEWSファイルに以下のような記載がありました。
なるほど、GROFF_NO_SGRという環境変数があるのか、と思ってこの環境変数をセットしてみたところ、画面がESCコードまみれになる状況は改善しましたが、強調部分には何か変な文字が表示されています(図3)。
おかしいなぁ……、と思って、出力結果をファイルに落しEmacsで開いてみると、2バイト文字を強調する場合、本来は^Hを2度出して2バイト分戻らないといけない(名^H^H名称^H^H称)のに、1度しか出していない(名^H名称^H称)ことがわかりました。これだと文字コードが途中で壊れておかしな表示になってしまうのでしょう。
これは明らかにバグですが、さすがにこのためにgroffのデバッグをするのも大変なので、何か別の方法が無いかしらん……と、しばらくドキュメントやmanページを調べてみました。
発見! SGRモード
先にNEWSファイルに紹介されていたTTY端末用のGROTTYの日本語manページを読んでみたけど、特にSGRなる機能についての記述は見当りません……と、そこで気がついたのが、このページが日本語なことです! 先にビルドしたgroff-1.18.1.1には英語版のmanページしかなく、参照している日本語のmanページは別途翻訳プロジェクトから配布されているgroff-1.17用のままでした。
そこでexport LANG=Cとして英語版のgrottyのmanページを見ると、SGRについての解説がしっかり記述されていました。
なるほど、これだ、ということで、さっそくGROFF_NO_SGR環境変数を無効にして、PAGER環境変数を'less -R'と指定してみると、日本語manページが正しく表示できるようになりました。
こんな機能があったのか、と思って、改めてlessの側のmanページを調べると、-rと-Rの2つのオプションが説明してありました。
なるほど、lessの側でもエスケープシーケンスは理解していて、むしろそれらが画面表示に悪影響を及ぼすことを防ぐために^[に変換してから表示するようになっていたようです。そして-Rはその変換を抑制するオプションでした。
個人的には、groffはmanページ整形用の「枯れた」ソフトと考えていましたが、実際に調べてみると、現在でもさまざまな新機能が追加され、定期的に新しいバージョンがリリースされているようです。また、lessも昔からずいぶんお世話になっているソフトなものの、-Rや-rというオプションは使ったことがなかったので、あらためてlessのソースコードに付属のNEWSファイルを調べたところ、-Rオプションは1999年にリリースされたless-346で採用された、かなり以前からある機能だったようです。
昔から使っているソフトウェアは、決まった使い方しかしていないことが多いのですが、64ビット化のために棚下しして埃を払ってみると「へぇ、こんなこともできたんだ」と気づくことがあって、まさに「古きを温(たず)ねて、新しきを知る」といった心境です。