以前、FreeBSDで日本語マニュアル - PC日記 と言う記事を書いたのだが、最近Cの関数のマニュアルを見るとおかしいことに気づいた。
% man select
名称
select — 同期的な入出力の多重化
ライブラリ
Standard C Library (libc, -lc)
書式
<sys/select.h> int select(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout) FD_SET(fd, &fdset) FD_CLR(fd,
&fdset) FD_ISSET(fd, &fdset) FD_ZERO(&fdset)
解説
select() システムコールは、 readfds, writefds および exceptfds でアドレス
書式のところがおかしい。
試しに、原文を見てみると、
SELECT(2) FreeBSD System Calls Manual SELECT(2)
NAME
select -- synchronous I/O multiplexing
LIBRARY
Standard C Library (libc, -lc)
SYNOPSIS
#include <sys/select.h>
int
select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
struct timeval *timeout);
FD_SET(fd, &fdset);
FD_CLR(fd, &fdset);
FD_ISSET(fd, &fdset);
FD_ZERO(&fdset);
DESCRIPTION
The select() system call examines the I/O descriptor sets whose addresses
書式のところだけでなく、最初のページヘッダも出ていないことに気づいた。
ちなみに、jmanだと以下のようになる。
SELECT(2) FreeBSD システムコールマニュアル SELECT(2)
名称
select - 同期的な入出力の多重化
ライブラリ
標準 C ライブラリ (libc, -lc)
書式
#include <sys/select.h>
int
select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
struct timeval *timeout);
FD_SET(fd, &fdset);
FD_CLR(fd, &fdset);
FD_ISSET(fd, &fdset);
FD_ZERO(&fdset);
解説
select() システムコールは、 readfds, writefds および exceptfds でアドレス
何もかも正しい。
とりあえず、マニュアルのソースを見てみる。selectのマニュアルは、/usr/share/man/ja/man2/select.2.gz にある。
.Dd November 17, 2002
.Dt SELECT 2
.Os
.Sh 名称
.Nm select
.Nd 同期的な入出力の多重化
.Sh ライブラリ
.Lb libc
.Sh 書式
.In sys/select.h
.Ft int
.Fn select "int nfds" "fd_set *readfds" "fd_set *writefds" "fd_set *exceptfds" "struct timeval *timeout"
.Fn FD_SET fd &fdset
.Fn FD_CLR fd &fdset
.Fn FD_ISSET fd &fdset
.Fn FD_ZERO &fdset
.Sh 解説
.Fn select
システムコールは、
.Sh
にセクション名が書いてあって、.Fn
に関数名と引数が並んでいるらしい。
これを処理するgroffのマクロがどこにあるかと、/usr/local/share/groff/current/tmac を探してみたら、doc.tmac
にたどり着いた。
どうも、in-synopsis-section
の値によって、.Fn
のフォーマット方法を変えているらしい。それでは、in-synopsis-section
はどこで決まるかと探してみると、mdoc/doc-common
にあるようだ。
.ds section-name NAME
.ds section-synopsis SYNOPSIS
.ds section-library LIBRARY
.ds section-description DESCRIPTION
.ds section-see-also SEE
.ds section-files FILES
.ds section-authors AUTHORS
ここで、マニュアルのセクション名が決め打ちされているようで、同じファイル内で.Sh
リクエストの引数によって場合分けがされ、in-synopsis-section
等が設定されるらしい。
試しに、select.2.gz を書き換えて、「書式」を「SYNOPSIS」にしてみたところ、正しく表示された。
じゃあ、jmanが使っているjgroffはどうしているのだろうと思って見てみたら、tmacディレクトリのmdocの中に、docj-nroff
やja.eucJP
等のファイルがあった。
ja.eucJP
を見てみると、上記のsection-name
等の定義があった。
.ds section-name 名称
.ds section-synopsis 書式
.ds section-description 解説
.ds section-see-also 関連項目
.ds section-files 関連ファイル
.ds section-authors 作者
これを真似すれば良いのではないかと思って、mdoc/doc-common
の該当箇所をja.eucJP
を真似して修正し、UTF-8
で保存してみた。
が、結果は変わらず。
最近のgroffはUTF-8には対応していると思うんだけど、マクロファイルには直接書いてはいけないのだろうか?
そこで、groffのソースを読んでみたところ、マニュアルには書いていない-D
, -K
, -k
のオプションがあること、これらのオプションはpreconv
と言うコマンドに渡されることがわかった。
preconv
が何をするコマンドが調べたところ、どうも非ASCIIの文字を\[uxxxx]
のように置き換えるようだ。(Javaのnative2asciiのようなもの)
ここまでわかれば、tmacファイルに直接UTF-8で書かずに、\[uxxxx]
の形式で書けば良いことがわかる。
試しに、doc-commonを直接書き換えたところ、うまく行くことがわかった。
しかし、doc-commonを書き換えてしまうと、今度はオリジナルの英語のマニュアルを見るときにおかしくなってしまう。日本語のときだけなんとかしたい。
portsがインストールするファイルを見ると、/usr/local/share/groff/current/tmac の他に、/usr/local/share/groff/site-tmac と言うディレクトリに、mdoc.local等のファイルを置くことがわかった。
試しに doc-common の代わりに mdoc.local に書いてみたところ、同じように動作した。
しかし、別のファイルを作成して、groffの-mオプションで読み込ませてみたところ、うまくいかなかった。
どうも、.ds
の有効範囲は、同じマクロか、そこから.mso
で読んでいるファイルに限られるらしい。
とりあえず、mdoc.localに条件分岐を追加して、日本語用のマクロファイルを読み込むようにすれば、やりたいことができそうなので、次回に送ることにする。