FreeBSDの日本語マニュアル

以前、[FreeBSDで日本語マニュアル - PC日記](http://www.wizard-limit.net/mt/pc/archives/005138.html) と言う記事を書いたのだが、最近Cの関数のマニュアルを見るとおかしいことに気づいた。

```shell-session
% 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 でアドレス
```

書式のところがおかしい。
試しに、原文を見てみると、

```shell-session
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だと以下のようになる。

```shell-session
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 にある。

```select.2
.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`にあるようだ。

```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`等の定義があった。

```ja.eucJP
.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に条件分岐を追加して、日本語用のマクロファイルを読み込むようにすれば、やりたいことができそうなので、次回に送ることにする。