FreePWING プログラミングドキュメント
笠原 基之

はじめに

FreePWING は JIS X 4081 形式の書籍データを生成を行うソフトウェアです。 JIS X 4081 は EPWING V1 のサブセットですので、FreePWING によって生成し た JIS X 4081 形式の書籍データは、原理上 EPWING の検索ソフトウェアで検 索を行うことが可能です。

ただし、FreePWING で作成した JIS X4081 形式の書籍データが、お持ちの EPWING 検索ソフトウェアで正しく扱えなかったとしても、検索ソフトウェア の発売元や作者に対して問い合わせることはご遠慮下さい。 (Windows 向けの EPWING 検索ソフトウェアには、書籍データが CD-ROM 以外 の媒体上にあると検索できないようになっているものもあります。)

FreePWING のほとんどの部分は Perl 5 (バージョン 5.005 以上が必要) で書 かれていますが、現状では UNIX 系 OS および Cygwin のような UNIX 互換の 開発環境をインストールしてあるシステム上でないと動作しません。 生成した書籍データはシステムによらず共通なので、UNIX 以外でも使えます。

FreePWING はフリーソフトウェアです。 あなたは、Free Software Foundation が公表した GNU General Public License (GNU 一般公有使用許諾) バージョン 2 あるいはそれ以降の各バージョ ンの中からいずれかを選択し、そのバージョンが定める条項に従って本プログ ラムを再頒布または変更することができます。

FreePWING は有用とは思いますが、頒布にあたっては、市場性及び特定目的適 合性についての暗黙の保証を含めて、いかなる保証も行いません。 詳細については GNU General Public License をお読み下さい。

FreePWING で生成した JIS X 4081 形式のデータに関しては、使用許諾および その他の権利について、FreePWING の著作者は一切の主張をいたしません。 ただし、上述の GNU General Public License に従い、あなたの作成したデー タに対して、FreePWING はいかなる保証も行いません。

最新の FreePWING は ftp://ftp.sra.co.jp/pub/misc/freepwing/ から入手できます。

FreePWING に関する情報は http://www.sra.co.jp/people/m-kasahr/freepwing/ から得ることができます。

コメントやバグの報告は m-kasahr@sra.co.jp 宛にお送り下さい。

FreePWING の概要

あなたが既に FreePWING で変換してみたい書籍データをお持ちなら、その辞 書は JIS X 4081 以外の形式、たとえば、HTML、Texinfo、PDIC といった形式 で書かれていると思います。 しかしながら、FreePWING にはこうした特定のテキスト形式を解釈する機能は ありません。 もし、書籍データが HTML で書かれているとしたら、データを HTML として解 釈する処理プログラムはあなたが用意しなくてはなりません。

たとえば、HTML で書かれた書籍データに一節があったとします。

  FreePWING では<EM>できません</EM>!!!

HTML では <EM> と </EM> はそのまま文章として扱われるのでは なく、その間の文字列を強調するという意味を持ちます。 したがって、HTML を JIS X 4081 形式に変換するためには、<EM> や </EM> が特殊な意味を持つことを認識して、他の普通の文字列とは分け て処理しなくてはなりません。

けれども、繰り返しになりますが、FreePWING には HTML を解釈する機能は用 意されていません。 JIS X 4081 形式に変換するには、HTML を解釈するための HTML パーサ (構文 解析器) と、解釈したデータを FreePWING に渡すための橋渡し的なプログラ ムを用意する必要があります。

「<EM>できません</EM>」の部分を JIS X 4081 形式に変換する FreePWING プログラムを敢えて書くなら、次のようになります。

  ## $text は FreePWING::FPWUtils::Text クラスのオブジェクトで、
  ## 既に出力ファイルをオープンしているものとします。
  $text->add_emphasis_start();
  $text->add_text("できません");
  $text->add_emphasis_end();

このように、FreePWING を扱うには、プログラミング、特に Perl 5 でのプロ グラミングが常に付いて回ります。 FreePWING の実体は、「Perl 5 用のライブラリ」と言っても良いでしょう。

この文書は、FreePWING のプログラミングの仕方について解説します。 なお、あなたが既に Perl 5 のプログラミングの基本知識を身に付けている ものとしますので、あらためてこの文書の中で説明することは致しません。 ご了承下さい。

FreePWING が生成できるデータ要素

FreePWING が変換した書籍データには、次の機能を与えることができます。

本文データ
書籍の本文です。
メニュー表示用データ
階層構造になった、特殊な本文です。 詳しくは メニュー の節をご覧下さい。
著作権表示データ
書籍の著作権表示です。
前方一致検索
ユーザが入力した単語に対して、その先頭部分が一致する単語を検索します。 たとえば `ques' という単語を検索すると、先頭が `ques' で始まる語 (`quest', `question' など) を見つけられます。 主に、辞書タイプの書籍で使います。
後方一致検索
ユーザが入力した単語に対して、その末尾部分が一致する単語を検索します。 たとえば `lism' という単語を検索すると、末尾が `lism' で始まる語 (`realism', `nationalism' など) を見つけられます。 これも、主に辞書タイプの書籍で使います。
外字
書籍固有の字を定義して、使うこととができます。

なお、この一覧には「完全一致検索」(ユーザが入力した単語に対して、完全 に一致する単語の検索) はありません。 これは、FreePWING が対応していないからではなく、完全一致検索は前方一 致検索用のデータを使って行うからです。 したがって、書籍に前方一致検索の機能を持たせれば、完全一致検索も扱う ことができまるようになります。


FreePWING プログラムの作成例

ここからは、FreePWING の実際のプログラミングについて解説します。 JIS X 4081 は、辞典検索を得意とするデータ形式になっていますので、本章 でも辞典を対象にして、JIS X 4081 形式のデータを生成するまでの過程を記 すことにします。

例題「国語辞典」の仕様

すでに JIS X 4081 形式になった国語辞典があるとしましょう。 EPWING の検索ソフトウェアを用いて、この辞典で「たいさく」という語を引 いてみると、おそらく「大作」「対策」という語が見つかり、以下のような感 じで見出しが表示されると思います。

  たいさく 【大作】
  たいさく 【対策】

次に、このうちの「対策」の方を選ぶと、「対策」という語についての本文が 表示されます。

  たいさく 【対策】
  状況に応じてとる手段や策略。

通常、紙の辞典では、この本文の部分が「対策」という語に関する全データに なるでしょう。 それに対して、JIS X 4081 形式の辞典では、本文というデータに加えて、 「たいさく」が「対策」の検索語であるという情報や、検索したときに表示す る見出しをデータとして保持しています。 つまり、JIS X 4081 形式の辞書データでは、「検索語」、「見出し」、 「本文」の三つの成分に分けて保持するのです。

検索語
たいさく、対策
見出し
たいさく 【対策】
全文
たいさく 【対策】
状況に応じてとる手段や策略。

(JIS X 4081 形式は漢字を含んだ語も検索できますので、「たいさく」に加え て「対策」も検索語として挙げています。 つまり、見出し、本文は一つであるのに対し、検索語は複数個用意することが できます。)

あなたが紙の辞典と似た書式の辞典データを JIS X 4081 形式に変換しようと 思ったら、このようにデータを検索語、見出し、本文に分類する処理を行うこ とになります。 逆に分類さえ行えば、残る JIS X 4081 形式への変換処理の殆んどは FreePWING が自動的に行います。

プログラムの全容

では、前節の国語辞典のようなデータを JIS X 4081 形式に変換する FreePWING のプログラムを実際に作ることにしましょう。

まず、変換前の辞典データの形式について若干補足しておきます。 辞典データの形式は、次のように見出しと説明が一行ごとに交互に現れるとい う単純なものであるとします。

  たいさく 【大作】              (← 見出し)
  大掛かりな作品。               (← 説明)
  たいさく 【対策】              (← 見出し)
  状況に応じてとる手段や策略。   (← 説明)

見出し部分の正確な書式は、次のいずれかの形式であるものとします。

  形式 1:  <かな検索語>
  形式 2:  <かな検索語> <空白> "【" <漢字を含んだ検索語> "】"

さらに、元のデータは EUC-JP で書かれているもとします。 これは、FreePWING の取り扱う文字コードが EUC-JP だからです。 別のコードで書かれている場合は、jcode.plJcode.pm などで、EUC-JP に変換してから処理する必要があり ます。

この国語辞典データを処理する FreePWING プログラム例は、以下の通りです。 プログラムの細部の説明は、次節以降で行います。 なお、データと同様に、本プログラムも EUC-JP で書かれているものとします。

  use FreePWING::FPWUtils::FPWParser;

  ## インスタンスを生成する。
  $fpwword2   = FreePWING::FPWUtils::Word2->new();
  $fpwheading = FreePWING::FPWUtils::Heading->new();
  $fpwtext    = FreePWING::FPWUtils::Text->new();

  ## 書き込み用の作業ファイルを開く。
  $fpwword2->open()   || die $fpwword2->error_message() . "\n";
  $fpwheading->open() || die $fpwheading->error_message() . "\n";
  $fpwtext->open()    || die $fpwtext->error_message() . "\n";

  for (;;) {
     ## 次の一行 (見出し) を読み込む。
     last if (!defined($_ = <>));
     chomp;

     ## 本文と見出しを新しいエントリに切り替える。
     $fpwtext->new_entry()
        || die $fpwtext->error_message() . "\n";
     $fpwheading->new_entry()
        || die $fpwheading->error_message() . "\n";

     ## 見出しを書き込む。
     $fpwheading->add_text($_)
        || die $fpwheading->error_message() . "\n";

     ## 本文を書き込む。
     if (!$fpwtext->add_keyword_start()
        || !$fpwtext->add_text($_)
        || !$fpwtext->add_keyword_end()
        || !$fpwtext->add_newline()) {
        die $fpwtext->error_message() . "\n";
     }

     ## かなの検索語を登録する。
     ($kanaword = $_) =~ s/ 【.*$//;
     $heading_position = $fpwheading->entry_position();
     $text_position = $fpwtext->entry_position();
     if (!$fpwword2->add_entry($kanaword, $heading_position, 'head',
         $text_position, 'text')) {
        die $fpwword2->error_message() . "\n";
     }

     ## 漢字の検索語があれば、それも登録する。
     if (/ 【(.*)】$/) {
        $kanjiword = $1;
        if (!$fpwword2->add_entry($kanjiword, $heading_position, 'head',
            $text_position, 'text')) {
           die $fpwword2->error_message() . "\n";
        }
     }

     ## 次の一行 (説明) を読み込む。
     last if (!defined($_ = <>));

     ## 本文を書き込む。
     if (!$fpwtext->add_text($_)
        || !$fpwtext->add_newline()) {
        die $fpwtext->error_message() . "\n";
     }
  }

  ## 書き込み用の作業ファイルを閉じる。
  $fpwword2->close()   || die $fpwword2->error_message() . "\n";
  $fpwheading->close() || die $fpwheading->error_message() . "\n";
  $fpwtext->close()    || die $fpwtext->error_message() . "\n";

インスタンスの初期化

本節から数節に分けて、前節に示した FreePWING プログラムの解説を行いま す。

今回の国語辞典データの例では、FreePWING が用意している以下の 3 つのク ラスを使います。

FreePWING::FPWUtils::Word2
前方一致、後方一致検索のための検索語の登録
(`Word2' の `2' は、前方一致、後方一致を同時に扱えることからこの名前が 付いています。)
FreePWING::FPWUtils::Heading
見出しデータの登録
FreePWING::FPWUtils::Text
本文データの登録

これらのクラスを使うには、モジュールを直接読み込むのではなく、 FreePWING::FPWUtils::FPWParser というモジュールを読み込み ます。 このモジュールが、上記の 3 つのクラスと同名のモジュールを読み込みます。

  use FreePWING::FPWUtils::FPWParser;

次に各クラスのインスタンスを一つずつ生成します。

  ## インスタンスを生成する。
  $fpwword2   = FreePWING::FPWUtils::Word2->new();
  $fpwheading = FreePWING::FPWUtils::Heading->new();
  $fpwtext    = FreePWING::FPWUtils::Text->new();

さらに、それぞれのオブジェクトに対して open() メソッドを 呼び出して、作業用ファイルを開いておきます。 ファイル名は、あらかじめモジュール内部で決めてあるものが使用されます。

  ## 書き込み用の作業ファイルを開く。
  $fpwword2->open()   || die $fpwword2->error_message() . "\n";
  $fpwheading->open() || die $fpwheading->error_message() . "\n";
  $fpwtext->open()    || die $fpwtext->error_message() . "\n";

国語辞典データの読み込み

これより後はしばらく、for 文を用いた無限の繰り返しになっ ています。 この for ブロックが処理の中心部分です。

元の国語辞典データの読み込み方は自由ですが、今回は Perl のファイルハ ンドル <> から読み込むことにしました。 for ブロックの中で見出しと説明を一行ずつ交互に読んでいま す。 ファイルの終端まで呼んだら for ループから抜けます。 処理の概要を記すと、次のようになります。

  for (;;) {
     ## 次の一行 (見出し) を読み込む。
     last if (!defined($_ = <>));

     (読み込んだ見出しの処理...)

     ## 次の一行 (説明) を読み込む。
     last if (!defined($_ = <>));

     (読み込んだ説明の処理...)
  }

読み込んだ見出しの処理

続いて、for ブロックの中の処理について見ていきます。 見出し分のデータを一行読み込んだら、まず本文と見出しオブジェクトに対 してそれぞれ new_entry() を呼び、次に新しい 「エントリ (entry)」に切り替える処理を行ってから、本文 ($fpwtext)、見出し($fpwheading) に書き込み ます。

     ## 次の一行 (見出し) を読み込む。
     last if (!defined($_ = <>));
     chomp;

     ## 本文と見出しを新しいエントリに切り替える。
     $fpwtext->new_entry()
        || die $fpwtext->error_message() . "\n";
     $fpwheading->new_entry()
        || die $fpwheading->error_message() . "\n";

     ## 読み込んだ見出しを「本文部」に書き込む。
     if (!$fpwtext->add_keyword_start()
        || !$fpwtext->add_text($_)
        || !$fpwtext->add_keyword_end()
        || !$fpwtext->add_newline()) {
        die $fpwtext->error_message() . "\n";
     }

     ## 読み込んだ見出しを「見出し部」に書き込む。
     $fpwheading->add_text($_)
        || die $fpwheading->error_message() . "\n";

本文と見出しのエントリの切り替えとは、現在の検索語の見出し、本文の終端 を宣言し、新たな検索語に切り替えることを意味します。 たとえば、「大作」という検索語に対する書き込みが終わったら、そこでエン トリを切り替え、次に「対策」という検索語に対する書き込みを行う、といっ た手順で処理を行います。

辞書の元データの見出し分の行は、JIS X 4081 の見出し部と本文部の両方に 書き込んでいますが、これは辞書のデータの分類の仕方を思い出してみれば、 理解できると思います。

検索語
たいさく、対策
見出し
たいさく 【対策】   (←この部分)
全文
たいさく 【対策】   (←この部分)
状況に応じてとる手段や策略。
ただし、本文部では add_keyword_start()add_keyword_end() で囲っいるに注意して下さい。 これによって、囲った部分が「検索キー」であることを記す印が埋め込まれ ます。 EPWING の検索ソフトウェアによっては、この印を本文の切れ目を意味する印 として扱っているものもありますので、必ず埋め込むようにして下さい

また、見出しは必ず一行で完結するものなので、改行の書き込み (add_newline() の呼び出し) は行いませんが、本文に対しては 明示的に書き込む必要があります。 読み込んだデータ側に含まれている改行文字 ("\r""\n") は add_text() に渡しても無視されますの で、本文中で改行を行う には必ず add_newline() を呼び出す必要があります。

プログラムでは、次に検索語を登録しています。

     ## かなの検索語を登録する。
     ($kanaword = $_) =~ s/ 【.*$//;
     $heading_position = $fpwheading->entry_position();
     $text_position = $fpwtext->entry_position();
     if (!$fpwword2->add_entry($kanaword, $heading_position,
         $text_position)) {
        die $fpwword2->error_message() . "\n";
     }

検索語の登録は、検索用のオブジェクト ($fpwword2) に対して add_entry() メソッドを呼び出すことによって行います。 本文、見出しとは異なり、検索語の登録前に new_entry() を呼 ぶ必要はありません。 add_entry() には、次の 3 つの引数が必要です。

漢字の検索語の登録処理は、かなの検索語と変わりませんので、 説明は省略します。

読み込んだ本文の処理

ループ内の最後の部分です。 説明分の行を一行読み、それを本文として書き込みます。

     ## 次の一行 (説明) を読み込む。
     last if (!defined($_ = <>));
     chomp;

     ## 本文を書き込む。
     if (!$fpwtext->add_text($_)
        || !$fpwtext->add_newline()) {
        die $fpwtext->error_message() . "\n";
     }

インスタンスの最終処理

ループを抜けた後の部分の処理です。 生成したインスタンスの最終処理として、それぞれのインスタンスで開いて いた書き込み用の作業ファイルを閉じます。 これには、close() メソッドを用います。

  ## 書き込み用の作業ファイルを閉じる。
  $fpwword2->close()   || die $fpwword2->error_message() . "\n";
  $fpwheading->close() || die $fpwheading->error_message() . "\n";
  $fpwtext->close()    || die $fpwtext->error_message() . "\n";

以上でプログラムは終りです。

FreePWING プログラムの実行

では、この FreePWING プログラムを実行して、JIS X 4081 形式のデータを生 成してみます。 プログラム名が fpwkokugo、データファイル名が kokugo.dat だとすると、次のように実行します。

  % perl fpwkokugo kokugo.dat

処理が正常に終了すると、カレントディレクトリには wordewordheadtexttextreftexttag というファイルが生成されま す。 これらのファイルは JIS X 4081 形式のデータファイルではなく、中間生成ファ イルです。 JIS X 4081 形式のデータファイルを作成するには、さらに次のコマンドを実 行する必要があります。

  % perl /usr/local/libexec/freepwing/fpwsort
  % perl /usr/local/libexec/freepwing/fpwindex
  % perl /usr/local/libexec/freepwing/fpwcontrol
  % perl /usr/local/libexec/freepwing/fpwlink

(ここでは FreePWING を /usr/local 以下にインストールし、 libexecdir の位置を変更していないものとします。 他の場所にインストールしているときは、適宜読み替えて下さい。)

これらの処理をすべて行うと、カレントディレクトリにはさらにいくつかの中 間生成ファイルに加えて、honmon というファイルが生成される 筈です。この honmon というのが、JIS X 4081 形式のファイル になります。

しかし、毎回これらのコマンドを一つ一つ手で実行するのは大変ですので、自 動化を考えましょう。 それにはもちろん、コマンド行を書き並べた sh スクリプトを作って実行する ようにしても良いのですが、FreePWING では make に対応するための仕掛けを 用意しています。 これを使えば、データファイルの最終修正時刻が honmon より も後の場合だけ honmon を生成し直すといったことができます。

Makefile の作成

fpwmake 用の Makefile の記し方を説明していきます。

まず、この Makefile の文法は、必ず GNU make 向けのもので なければならないので注意して下さい。 つまり、make は必ず GNU make を用いる必要があります。 今回のプログラム用の Makefile は次のようになります。

FPWPARSER = fpwkokugo
FPWPARSERFLAGS = kokugo.txt

include fpwutils.mk

変数 FPWPARSER には作成した FreePWING プログラム名を、 変数 FPWPARSERFLAGS には FreePWING プログラムに渡すコマン ド行引数を設定します。 Makefile の末尾では include コマンドを用いて fpwutils.mk というファイルを読み込みます。 (このファイルの中に生成規則が書かれています。また、GNU make を用いる必 要があるのは、このファイルが GNU make 用に書かれているからに他なりませ ん。)

fpwmake

Makefile が準備できたら、make を実行します。 これには、専用の sh スクリプト fpwmake コマンドを使うと便利です。 fpwmake は GNU make に適切なオプションを与えて呼び出します。

カレントディレクトリを fpwkokugo のあるディレクトリに移して、次のよう にして fpwmake を実行します。

  % fpwmake

fpwmake を実行すると、カレントディレクトリには work とい うディレクトリができ、その下にいくつかのファイルが生成されます。

  % ls
  control.dep     eidxref1        idxref0         sort.dep
  ctrl            esort           idxref1         text
  ctrlref         eword           index.dep       textref
  eidx0           head            link.dep        texttag
  eidx1           idx0            parse.dep       word
  eidxref0        idx1            sort

正常に終了すれば、カレントディレクトリに honmon ファイル が生成されます。

作業ファイルの削除

fpwmake を実行すると、カレントディレクトリには work とい うディレクトリができ、その下にいくつかの中間ファイルが生成されます。 無事に honmon ファイルを生成し終り、中間ファイルおよび honmon ファイルが必要なくなった場合は、fpwmake clean を実 行すると、fpwmake 時に生成されたファイルがすべて消去されます。

  % fpwmake clean

くれぐれも消去する前に honmon ファイルを別の場所に移すこ とを忘れないで下さい。 そうしないと honmon も消えてしまい、もう一度 fpwmake で 生成し直す羽目になってしまいます。

ALLDEPSCLEANEXTRAターゲット

もし fpwmake を実行するにあたって前処理を行いことがあるときは、 ALLDEPS マクロを利用します。 いま、変換スクリプトを読み込むべき辞書データがもとは roff の ms マクロ を使用して書かれたファイル kokugo.ms に用意されているとし ましょう。 そして、nroff を使っていったん平文ファイル kokugo.txt を 生成して、変換スクリプトは平文のほうを読み込んで処理をするとしたら、次 のように書いておきます。

FPWPARSER = fpwkokugo
FPWPARSERFLAGS = kokugo.txt
ALLDEPS = kokugo.txt
CLEANEXTRA   = kokugo.txt

kokugo.txt: kokugo.ms
	rm -f $@
	tbl kokugo.ms | nroff -ms | col -b > kokugo.txt

include fpwutils.mk

ただし、ALLDEPS の仕組みを使って生成したファイル (ここで は kokugo.txt) は fpwmake clean を実行しても消去されませ ん。 そこで、CLEANEXTRA というファイルに fpwmake clean 実行時 に消して欲しいファイルを書いておきます。

ちょっとだけ改良

以上で作業は完了なのですが、ここで再びプログラムの記述に焦点を戻します。

変換プログラムの先頭は、必ず次のようにインスタンスの生成と書き込み用 の作業ファイルを開く動作になります。 これはどの変換プログラムでも同じです。

  ## インスタンスを生成する。
  $fpwword2   = FreePWING::FPWUtils::Word2->new();
  $fpwheading = FreePWING::FPWUtils::Heading->new();
  $fpwtext    = FreePWING::FPWUtils::Text->new();

  ## 書き込み用の作業ファイルを開く。
  $fpwword2->open()   || die $fpwword2->error_message() . "\n";
  $fpwheading->open() || die $fpwheading->error_message() . "\n";
  $fpwtext->open()    || die $fpwtext->error_message() . "\n";

実は、FreePWING にはこの部分と等価な処理をもう少し簡単に書くために、 initialize_fpwparser() というサブルーチンが FreePWING::FPWUtils::FPWParser パッケージに用意されてい ます。 initialize_fpwparser() を使うと、上のプログラムは次のよう に簡略化できます。

  initialize_fpwparser('text'    => \$fpwtext,
                       'heading' => \$fpwheading,
                       'word2'   => \$fpwword2);

ファイルを閉じる部分についても同様です。 これまでは、各オブジェクトに対して close() メソッドを呼び 出していました。

  ## 書き込み用の作業ファイルを閉じる。
  $fpwword2->close()   || die $fpwword2->error_message() . "\n";
  $fpwheading->close() || die $fpwheading->error_message() . "\n";
  $fpwtext->close()    || die $fpwtext->error_message() . "\n";

この部分は、次のように finalize_fpwparser() メソッドで置き 換えることができます。

  finalize_fpwparser('text'    => \$fpwtext,
                     'heading' => \$fpwheading,
                     'word2'   => \$fpwword2);

修正版プログラムの全容

前節に記した修正事項を反映すると、プログラムは次のようになります。 これで、本章で扱った変換プログラムは完成です。

  use FreePWING::FPWUtils:FPWParser;

  ## インスタンスを生成する。
  initialize_fpwparser('text'    => \$fpwtext,
                       'heading' => \$fpwheading,
                       'word2'    => \$fpwword2);

  for (;;) {
     ## 次の一行 (見出し) を読み込む。
     last if (!defined($_ = <>));
     chomp;

     ## 本文と見出しを新しいエントリに切り替える。
     $fpwtext->new_entry()
        || die $fpwtext->error_message() . "\n";
     $fpwheading->new_entry()
        || die $fpwheading->error_message() . "\n";

     ## 見出しを書き込む。
     $fpwheading->add_text($_)
        || die $fpwheading->error_message() . "\n";

     ## 本文を書き込む。
     if (!$fpwtext->add_keyword_start()
        || !$fpwtext->add_text($_)
        || !$fpwtext->add_keyword_end()
        || !$fpwtext->add_newline()) {
        die $fpwtext->error_message() . "\n";
     }

     ## かなの検索語を登録する。
     ($kanaword = $_) =~ s/ 【.*$//;
     $heading_position = $fpwheading->entry_position();
     $text_position = $fpwtest->entry_position();
     if (!$fpwword2->add_entry($kanaword,
         $heading_position, $text_position)) {
        die $fpwword2->error_message() . "\n";
     }

     ## 漢字の検索語があれば、それも登録する。
     if (/ 【(.*)】$/) {
        $kanjiword = $1;
        if (!$fpwword2->add_entry($kanjiword,
            $heading_position, $text_position)) {
           die $fpwword2->error_message() . "\n";
        }
     }

     ## 次の一行 (説明) を読み込む。
     last if (!defined($_ = <>));

     ## 本文を書き込む。
     if (!$fpwtext->add_text($_)
        || !$fpwtext->add_newline()) {
        die $fpwtext->error_message() . "\n";
     }
  }

  ## 書き込み用の作業ファイルを閉じる。
  finalize_fpwparser('text'    => \$fpwtext,
                     'heading' => \$fpwheading,
                     'word2'   => \$fpwword2);

諸々の細かな注意点

ここでは、前章で触れなかった諸々の細かな注意点をいくつか記しておきます。

文字コードに関する注意点

FreePWING では、文字コードに EUC-JP を使用していますが、正確には honmon ファイルの中では JIS X 0208 の文字 (全角文字) しか 使用できません。 このため、JIS X 0201 のカタカナおよび ASCII の文字 (半角文字) が与えら れると、FreePWING 側で 対応する JIS X 0208 の文字に置き換えられます。

また、JIS X 0212 の文字 (補助漢字) は使用することができず、与えるとエ ラーになります。

検索語に関する注意点

検索語に関する注意点は、次の通りです。

本文に関する注意点

本文の各エントリの冒頭では、以下のように add_keyword_start()add_keyword_end() で囲い、囲った部分が検索キーであると いう印を付けるようにすることは既に記しました。

     ## 読み込んだ見出しを「本文部」に書き込む。
     if (!$fpwtext->add_keyword_start()
        || !$fpwtext->add_text($_)
        || !$fpwtext->add_keyword_end()
        || !$fpwtext->add_newline()) {
        die $fpwtext->error_message() . "\n";
     }

EPWING の検索ソフトウェアによっては、この検索キーのを本文の切れ目を意 味する印として扱っているものもあります。 こうした検索ソフトウェアでは、2 度目の検索キー開始指定子が出現すると、 そこが次のエントリの開始位置であり、今のエントリが終了したのだと判断し て、そこで本文の表示、出力を止めるようになっています。 したがって、このような検索ソフトウェアで正しく書籍の本文が表示、出力さ れるように考慮して、検索キーの指定をエントリの冒頭で入れることが推奨さ れます。 さもないと、次のエントリ、次の次のエントリ、とどこまでも本文を表示、出 力してしまいます。

逆に、必要があればエントリの途中で検索キーを置いても構いませんが、むや みに置いてしまうと、エントリの本文の出力がそこで途切れてしまうことにな ります。 検索キーの配置は慎重に行って下さい。


パッケージ化

ここまでの説明で honmon ファイルは生成できるようになりま したが、これだけでは JIS X 4081 形式の書籍として完全なものではありませ ん。 この章では、JIS X 4081 形式の書籍としてパッケージ化する方法などについ て説明します。

catalogs

JIS X 4081 形式の書籍では、これまでに生成した honmon ファ イルの他に、catalogs というファイルが必ず必要です。 FreePWING には catalogs ファイルを生成する仕掛けが用意さ れていません。 生成には、EPWUTIL というソフトウェアに付属している catdump コマンドを 使用して下さい。 EPWUTIL は ftp://ftp.nerimadors.or.jp/pub/epwutil/ から入手できます。 EPWUTIL のインストール方法および catdump の使用方法については、 EPWUTIL 付属のドキュメントをお読み下さい。

なお、/usr/local/share/freepwing/catalogs ディレクトリに catdump 用の catalogs.txt のサンプルファイルと、 catdump で生成した catalogs ファイルがインストールされます (ただ し、FreePWING を /usr/local 以下にインストールして datadir を変更していない場合)。

パッケージ化のための Makefile の改良

用意した Makefile にいくつかのマクロを追加することで、パッ ケージ化を容易にすることができます。 以下に記述例を記します。

  PACKAGE = kokugo-fpw1.0
  PACKAGEEXTRA = README.pkg=README TODO VERSION
  PACKAGEDEPS  = VERSION
  ARCHIVEEXTRA = README.pkg TODO
  CLEANEXTRA   = VERSION
  DIR = kokugo

  VERSION:
  	rm -f $@
	date +'version %Y-%m-%d' > VERSION

各パラメタの意味は、次の通りです。

PACKAGE
このパッケージの名前です。 変換プログラム一式を、tar+gzip および zip 形式でアーカイブする際のトッ プディレクトリおよびファイル名の接頭辞に使われます。 上記の例ではトップディレクトリは kokugo-fpw1.0、ファイル 名は kokugo-fpw1.0-src.tar.gz になります。 また、JIS X 4081 形式に変換した書籍データ一式をパッケージ化して tar+gzip 形式や zip 形式でアーカイブする際のファイル名にも使われます。 上記の例では kokugo-fpw1.0.tar.gzkokugo-fpw1.0.zip になります。
PACKAGEEXTRA
JIS X 4081 形式に変換した書籍データ一式 (catalogshonmon および外字ファイル) を収めたアーカイブを作る際に、 書籍データ以外に一緒に入れるファイルを書き並べます。 `ファイル名=ファイル名' という形で指定した場合は、左辺のファイルを右辺 のファイル名に改名してパッケージに入れることを意味します。
PACKAGEDEPS
変換プログラム一式のアーカイブを作成する際に、ここに書かれたターゲット が前もって実行されます。 PACKAGEEXTRA で指定したファイルの中に、最初から用意されて いるファイルではなく、何らかの処理をして生成しなくてはならないファイル があった場合は、この PACKAGEDEPS に書き、生成方法を Makefile の中に記しておくと良いでしょう。
ARCHIVEEXTRA
変換プログラム一式のアーカイブを作る際に、READMEMakefile、catdump 用の catalogs.txt 以外に 一緒に入れるファイルを書き並べます。 `ファイル名=ファイル名' という形で指定した場合は、左辺のファイルを右辺 のファイル名に改名してパッケージに入れることを意味します。
DIR
honmon および外字ファイルを収めるサブディレクトリの名前 です。 catalogs.txt の中で Directory パラメタに書い た値を小文字化したものを指定する必要があります。 また、この DIR の値は、変換した書籍データ一式をパッケージ 化する際のトップディレクトリにも使われます。

インストール

前節で説明した改良を Makefile に施したら、fpwmake を実行 してみます。 まず、JIS X 4081 形式に変換した書籍データ一式をインストールしてみます。 これには、install ターゲットを使います。

  % fpwmake install

FreePWING を /usr/local 以下にインストールし、 datadir の位置を変更していなければ、 /usr/local/share/dict にインストールされます。 前節の例を使った場合、ディレクトリ以下は次のようになります。

kokugo/README
kokugo/TODO
kokugo/catalogs
kokugo/kokugo/data/honmon

別の場所にインストールしたい場合は、INSTALLDIR で指定しま す。

  % fpwmake install INSTALLDIR=/some/where

変換した書籍データのアーカイブ

次に、JIS X 4081 形式に変換した書籍データ一式をパッケージ化して tar+gzip 形式および zip 形式でアーカイブしてみます。 (インストールを実行しなくても、アーカイブの作成は可能です。) これには、package ターゲットを使います。

  % fpwmake package

先にも記しましたが、今回の例では、できあがるファイル名は kokugo-fpw1.0.tar.gzkokugo-fpw1.0.zip に なります。 これらのファイルに収められるファイルは、次の通りです。 基本的に、インストールのときの構成と同じです。ただし、zip 形式ではファ イル名およびディレクトリ名は大文字になります。

kokugo/README
kokugo/TODO
kokugo/catalogs
kokugo/kokugo/data/honmon

変換スクリプトのアーカイブ

最後に、変換プログラム一式をパッケージ化して tar+gzip 形式でアーカイ ブしてみます。 (honmon を作成していなくても、アーカイブの作成は可能です。) これには、archive ターゲットを使います。

  % fpwmake archive

今回の例では、できあがるファイル名は kokugo-fpw1.0-src.tar.gz になります。 これらのファイルに収められるファイルは、次の通りです。

kokugo-fpw1.0/README
kokugo-fpw1.0/catalogs.txt
kokugo-fpw1.0/Makefile
kokugo-fpw1.0/README.pkg
kokugo-fpw1.0/TODO

外字

FreePWING では、辞書に固有の字を外字として定義して利用することもでき ます。 ただし、外字を利用するには、外字定義ファイルと、各字のビットマップ データ (フォントデータ) を用意する必要があります。 以下、この章では外字を使用する方法を詳しく見ていきます。

外字の基礎知識

外字を定義する際は、各字のビットマップデータを用意しなくてはなりません。 ビットマップデータは、小さな長方形の点を縦横に何個も敷き詰めたもので構 成されます。 また、マップ自体はモノクロのデータで、色情報は持ちません。 ちょうど、XBM (X BitMap) 形式の画像データと同じです。

次は音楽のト音記号の外字ビットマップデータの例です。 (■が前景色の点、□が背景色の点です。)

  □□□□□■■■
  □□□□■□■□
  □□□■□■□□
  □□□■□■□□
  □□□■■□□□
  □□■□■□□□
  □□■□■■■□
  □■□■□■□■
  □■□■□■□■
  □■□□□■□■
  □□■□□■■□
  □□□■■■□□
  □□□□■□□□
  ■■□□■□□□
  ■■□■□□□□
  □■■□□□□□

JIS X 4081 では、「全角」「半角」という 2 種類の外字を定義しています。 全角外字はビットマップの縦と横の点の数がほぼ同じ外字で、それに対して半 角外字では横方向の点の数が縦の半分になります。 上のト音記号は、半角外字 (横 8、縦 16) です。

半角外字と全角外字はまったく独立しています。 辞書は、全角あるいは半角のどちらか一方の外字だけ定義することもできます し、両方とも定義することも可能です。 両方定義する場合でも、ある字を半角、全角の一方にだけ登録することも可能 です。

ビットマップデータは、全角、半角それぞれの外字に対して、以下のように 4 つずつサイズの違うものを用意することが可能です。

外字の種類 \ 高さ 高さ 16 高さ 24 高さ 30 高さ 48
半角外字 (横×縦) 8×16 16×24 16×30 24×48
全角外字 (横×縦) 16×16 24×24 32×30 48×48

このうち、縦方向の点が 16 個のビットマップ (半角の 8x16, 全角の 16x16) は必須です。 他のサイズは、大きなサイズのビットマップから順に省略することができます。 これはたとえば、縦の点の数が 48 と 30 の外字を省略して 16 と 24 だけ定 義することは可能ですが、48 と 24 を省略して 16 と 30 だけ定義すること はできない、ということです。

先ほど述べたように全角外字と半角外字は互いに独立していますが、サイズの 異なるビットマップ同士は独立したものではありません。 もしあなたが、16, 24, 30, 48 のすべてのサイズのビットマップを用意する と決めたら、定義した半角と全角の外字すべてに対して、必ず 4 つのサイズ のビットマップをそれぞれ用意しなければなりません。

ビットマップデータの用意

FreePWING では、外字のビットマップデータには XBM 形式のファイルを用い ます。 登録したい外字一字毎、サイズ毎に一つの XBM ファイルを用意します。 XBM ファイルは、UNIX の X の環境であれば bitmap コマンド等で作成できま す。 ビットマップエディタが XBM 形式を扱えるものでなければ、描画した後で画 像形式の変換ツールを使って XBM に変換して下さい。

外字定義ファイルの用意

ビットマップが用意できたら、次に外字定義ファイルを作成します。 半角外字、全角外字を両方とも定義する場合は、定義ファイルも 2 つに分け て用意します。

外字定義ファイルの記述形式は、次のようになります。

  外字名  XBMファイル名  XBMファイル名  XBMファイル名  XBMファイル名

以下は記述例です。

  g-clef    g-clef16.xbm  g-clef24.xbm  g-clef30.xbm  g-clef48.xbm
  f-clef    f-clef16.xbm  f-clef24.xbm  f-clef30.xbm  f-clef48.xbm

各パラメタは 1 個以上の空白かタブで区切ります。

「外字名」とは、その外字を利用するときに参照する名前です。全外字で一意 であれば好きな名前を付けることができます。 ただし、外字名には空白やタブ、改行文字は使用することができません。 外字名は半角と全角で独立していますので、同じ名前のものを定義しても、衝 突することはありません。 半角外字内、全角外字内で複数回同じ外字名を定義すると、エラーになります。

「XBMファイル名」は、外字のビットマップファイル名です。 左から順に高さが 16, 24, 30, 48 のものを並べます。 一部のサイズのビットマップを用意しない場合は、そのパラメタは指定しない で下さい。 ですから、実際は XBM ファイル名は 1 〜 4個の範囲で指定されることになり ます。 ただし、指定するファイル名の個数は、ファイル内で一定でなければなりませ ん。 途中で変化するとエラーになります。

なお、ファイル名はカレントディレクトリからの相対パス指定になります。 次のように、ディレクトリの区切りを入れることも可能です。

  g-clef        bitmap/g-clef16.xbm  bitmap/g-clef24.xbm
  f-clef        bitmap/f-clef16.xbm  bitmap/f-clef24.xbm

指定した XBM の画像サイズは、その外字のサイズと同一のものでなくてはな りません。 異なったサイズだと、エラーが発生します。

外字データの生成

前節までに書かれたことの準備ができたら、実際に外字データを生成します。 半角外字用には fpwhalfchar コマンド、全角外字用には fpwfullchar コマンドを実行します。 両方定義しているときは、両方実行します。 順番はどちらが先でも構いません。

たとえば、半角外字の外字定義ファイル名が halfchar.txt、 全角外字の外字定義ファイル名が fullchar.txt だとすると、 次のようなコマンド行を入力して下さい。

  % perl /usr/local/share/FreePWING/fpwutils/fpwhalfchar halfchar.txt
  % perl /usr/local/share/FreePWING/fpwutils/fpwfullchar fullchar.txt

(ここでは FreePWING を /usr/local 以下にインストールし、 libexecdir の位置を変更していないものとします。 他の場所にインストールしているときは、適宜読み替えて下さい。)

正常に終了すれば、次のビットマップデータファイルができ上がります。 ただし、用意しなかったサイズの分は作成されません。

外字の種類 \ 高さ 高さ 16 高さ 24 高さ 30 高さ 48
半角外字 gai16h gai24h gai30h gai48h
全角外字 gai16f gai24f gai30f gai48f

これらのファイルは honmon と同じく、最終的に辞書データパッ ケージの一部として使われます。 それ以外に中間ファイルも生成されますが、これらは本文の中で外字を参照す るときに使用されます。

fpwmake による外字データの生成

fpwhalfchar, fpwfullchar を直接実行する代わりに fpwmake を使って外字 データを生成することもできます。 通常は、こちらのほうが楽で良いでしょう。

前節と同様に、半角外字の外字定義ファイル名が halfchar.txt、 全角外字の外字定義ファイル名が fullchar.txt だと仮定する と、Makefile に以下の記述を追加します。

  HALFCHARS = halfchar.txt
  FULLCHARS = fullchar.txt

半角外字、全角外字の一方だけを生成する場合は、HALFCHARSFULLCHARS の一方だけを定義して下さい。

本文への外字の書き込み

外字を本文中で使用するには、あらかじめ fpwhalfcharfpwfullchar コマンドを実行して、定義された外字の参照ファ イルを用意しておかなければなりません。 つまり、fpwhalfcharfpwfullchar は変換プロ グラムよりも前に実行する必要があります。 (fpwmake を使用するのであれば、自動的に正しい順番で実行されますので、 実行順序を気にする必要はないでしょう。)

半角外字を本文中に書き込むには、本文書き込み用のクラス FreePWING::FPWUtils::Text のオブジェクトに対して add_half_user_character() を呼び出します。

  if (!$fpwtext-$gt;add_half_user_character('g-clef')) {
      die $fpwtext->error_message() . "\n";
  }

この例では、"g-clef" という名前の半角外字を書き込んでいます。 この外字名は、半角外字の外字定義ファイルに登録されているものでなけ ればなりません。 未登録の外字を使用すると、エラーになります。

全角外字については、代わりに add_full_user_character() メソッドを呼び出す点が異なる だけで、呼び出し方などはすべて同じです。


応用編

前章で JIS X 4081 形式のファイル生成における FreePWING の基本的な使用 方法を紹介しましたので、本章ではやや応用的な機能について説明します。

修飾指定子

本文および見出しには、文字に強調を施したり、ある区間内で折り返しを禁止 したりといった修飾の指定を挿入することができます。 ただし、これらの指示が JIS X 4081 検索ソフトウェア上でどのように表示さ れるかは、それぞれのソフトウェアによって異なります。

FreePWING で扱える修飾には、次のような種類があります。

下添え字開始指定と終了指定
開始から終了までの間の区間の文字列を下添え字表示にします。
上添え字開始指定と終了指定
開始から終了までの間の区間の文字列を上添え字表示にします。
分割禁止開始指定と終了指定
開始から終了までの間の区間の文字列を折り返し禁止にします。
強調開始指定と終了指定
開始から終了までの間の区間の文字列を強調表示にします。
別フォント開始指定と終了指定
開始から終了までの間の区間の文字列を別のフォントで表示します。

開始指定と終了指定は入れ子にすることで、複数の修飾を同時に行うことも可 能です。 たとえば、分割禁止と強調の両方の修飾を行いたい場合は、

  [分割禁止開始] ... [強調開始] ... [強調終了] ... [分割禁止終了]

という順序で指定子を挿入します。 強調開始と強調終了の間は、分割禁止と強調と両方が有効になります。 修飾の指定子は入れ子になっていれば良いので、次のように強調を外側、分割 禁止を内側にしても構いません。

  [強調開始] ... [分割禁止開始] ... [分割禁止終了] ... [強調終了]

しかし、次のような用法は入れ子になっていないので、誤りです。

  [分割禁止開始] ... [強調開始] ... [分割禁止終了] ... [強調終了]

開始指定子を指定したら、それと対になる終了指定子を必ずエントリの末尾ま でに呼ばなくてはなりません。 エントリ終端時点で終了指定子が呼ばれていない修飾があると、エラーになり ます。

また、入れ子の中で外側と同じ修飾を再度かけることはできません。これも行 おうとするとエラーになります。

相互参照

よく辞書では、本文中に別の箇所への参照情報を入れていることがあります。 JIS X 4081 形式のデータでは紙の辞書と違って、参照先の位置情報を入れま すので、(ちょうど HTML のリンクのように) 参照先に飛んでそこの本文を表 示することも可能です。

FreePWING でこのような参照を行うには、次の操作が必要になります。

タグ (tag) というのは、本文の特定の位置に対して名前を付けるものです。 たとえば、「エンジン」という語のエントリの開始位置に engine という名前 のタグを割り当てることができます。 タグの名前は必ず本文内で一意でなくてはなりません。

FreePWING で実際にタグを割り当てるには、 FreePWING::FPWUtils::Text クラスのオブジェクトに対して add_tag() メソッドを呼び出し ます。

  $fpwtext->add_tag("engine");

タグは、割り当てられた時点での本文の書き込み位置を常に指し続けます。 エントリの文章の途中の位置でタグを割り当てることも可能ですが、必ず本文 の修飾指定が何も行われていない個所で割り当てて下さい。 エントリの開始位置を指すようにする場合は、add_entry() メ ソッドを呼び出した直後に呼ぶようにします。

次に、参照元では割り当てたタグへの参照情報を埋め込むことになります。 参照情報は語句に対して付加するので、開始指定と終了指定があります。 たとえば、先ほど割り当てた engine という名前のタグへの参照を

  (参考: →「エンジン」も参照のこと)

という表現で行い、このうち『→「エンジン」』の部分だけに参照情報を入れ る場合は、次のような処理を行うことになります。

  $fpwtext->add_text("(参考: ");
  $fpwtext->add_reference_start();
  $fpwtext->add_text("→「エンジン」");
  $fpwtext->add_reference_end("engine");
  $fpwtext->add_text("も参照のこと)");

add_reference_start() が参照の開始指定、 add_reference_end() が終了指定になります。 終了指定時に参照先のタグを一緒に指定します。 (正確に言えば、参照情報は 修飾指定子 の一種になりますので、修飾指定子に関する規則がそのまますべて当てはまり ます。)

なお、参照情報を入れる時点でまだ定義されていないタグ名を指定することも 可能です。 (そうでないと、本文の後方への参照が行えないからです。) ただし、本文が終了したのにもかかわらずそのタグが未定義だった場合は、エ ラーが発生します。

複数の本文

紙の辞書で言うところの「本文」を複数個をまとめて JIS X 4081 の一個の honmon ファイルの中に入れてしまうことができます。 たとえば、EPWING の辞書には英和辞典と和英辞典を本文を一つにまとめて いるものがあります。 もちろん、英和辞典、和英辞典に対して一つずつ honmon を用 意しても良いのですが、一緒にしておくと辞書を切り替えずに英和、和英の両 方が検索できるという利点があります。

FreePWING でも、複数個の本文を入れるための仕掛けが用意されています。 FreePWING では FreePWING::FPWUtils::Text クラスのオブジェ クトを介して本文データを書き込みますが、 FreePWING::FPWUtils::Text クラスの new_context() メソッドを使うと、そこで新しい「本文」に切り替わります。 (FreePWING では、本文一個を「コンテキスト (context)」と呼ん でいます。)

  $fpwtext->new_context();

英和辞典と和英辞典を一体化させるなら、まず英和辞典の本文データを一通り 書き込み、new_context() で「本文」を切り替えた後に和英辞 典の本文データを書き込む、という手順になります。

英和辞典と和英辞典を一体化させるなら、まず英和辞典の本文データを一通り 書き込み、new_context() で「本文」を切り替えた後に和英辞 典の本文データを書き込む、という手順になります。

なお、相互参照 用のタグは、本文を切り 替えても共有されますので、タグ名は必ず honmon 全体で一 意でなくてはなりません。 逆にこのことは、複数の本文の間で相互参照が可能であることを意味します。

メニュー

JIS X 4081 形式のファイル honmon には、本文以外にも、 メニューという特殊な文章データを組み込むことができます。

メニューは主に、辞書の付録、序文、使い方をいった部分を収録するときに用 います。 通常、メニューは以下のような階層構造にします。

  * 序文
  * この辞書の使い方
    - 検索方法
    - 表記について
    - 発音について
  * 付録
    - 不規則変化動詞一覧表

この辞書のトップメニューは次のようになります。 検索ソフトウェアはこのメニューを表示する際に、メニューの各項目、つまり 「序文」や「この辞書の使い方」「付録」にそれぞれ参照先があることがユー ザに分かるように表示するでしょう。

  * 序文
  * この辞書の使い方
  * 付録

ユーザが「序文」を選べば序文の内容が表示され、「この辞書の使い方」を 選べば「検索方法」「表記について」「発音について」といった項目が並んだ サブメニューが表示されます。

FreePWING でこのようなメニューを扱うには、次のように FreePWING::FPWUtils::Menu クラスのオブジェクトを用意する 必要があります。

  ## インスタンスを生成する。
  $fpmenu = FreePWING::FPWUtils::Menu->new();

  ## 書き込み用の作業ファイルを開く。
  $fpmenu->open() || die $fpwmenu->error_message() . "\n";

initialize_fpwparser() を使う場合は、次のように 'menu' という項目を足します。

  initialize_fpwparser('text'    => \$fpwtext,
                       'heading' => \$fpwheading,
                       'word2'   => \$fpwword2,
                       'menu'    => \$fpwmenu);    # ←追加

finalize_fpwparser() の呼び出しでも同様の操作を行います。

FreePWING::FPWUtils::Menu クラスは、本文書き込み用のク ラスである FreePWING::FPWUtils::Text とまったく同じメソッ ド群を持ちます。 異なるのは、どの中間ファイルに書き出すかという点だけです。 つまり、FreePWING::FPWUtils::Text クラスで用意されてい るのと同名の書き込み用のメソッドを呼び出すことで、メニューに書き込み を行うことができます。

メニューの中の、トップメニュー、サブメニューおよび「序文」等の文章は それぞれ、独立した コンテキスト にします。 したがって、メニューでは参照情報の付加、タグの設定、コンテキストの切り 替えといった操作を多用することになります。 なお、メニューから本文への参照やその逆の参照を行うことも可能です。 ただし、タグ名はメニューと本文とで共有されますので、衝突しないようにし て下さい。

著作権表示

JIS X 4081 形式のファイル honmon には、 メニュー の他にもう一つ、著作権表示という特殊な文章データがあります。 これは、その名の通り書籍の著作権表示を文章化したものです。

FreePWING で著作権表示を扱うには、 FreePWING::FPWUtils::Copyright クラスのオブジェクトを 用意する必要があります。

  ## インスタンスを生成する。
  $fpwcopyright = FreePWING::FPWUtils::Copyright->new();

  ## 書き込み用の作業ファイルを開く。
  $fpwcopyright->open() || die $fpwcopyright->error_message() . "\n";

initialize_fpwparser() を使う場合は、次のように 'copyright' という項目を足します。

  initialize_fpwparser('text'      => \$fpwtext,
                       'heading'   => \$fpwheading,
                       'word2'     => \$fpwword2,
                       'menu'      => \$fpwmenu,
                       'copyright' => \$fpwcopyright);    # ←追加

finalize_fpwparser() の呼び出しでも同様の操作を行います。

メニューもそうでしたが、著作権表示のクラスである FreePWING::FPWUtils::Copyright クラスもまた、本文書き込 み用のクラスである FreePWING::FPWUtils::Text と完全に同 じメソッド群を持ちます。 異なるのは、どの中間ファイルに書き出すかという点だけです。 FreePWING::FPWUtils::Text クラスで用意されているのと同名 の書き込み用のメソッドを呼び出すことで、著作権表示に書き込みを行うこ とができます。


リファレンスマニュアル

FreePWING::FPWUtils::Word2 クラス

FreePWING::FPWUtils::Word2 は、前方一致および後方一致検索 用の検索語一覧を同時に生成するためのクラスです。 以下のメソッドを持っています。

new()
FreePWING::FPWUtils::Word2 クラスのオブジェクトを生成して、 そのリファレンスを返すクラスメソッドです。
open()
書き込み用に検索語ファイルを開きます。 ファイル名は、あらかじめモジュール内で指定されたものが使用されます。 成功すれば 1 を、失敗すれば 0 を返します。
close()
開いていた検索語ファイルを閉じます。 開いていなければ何もしません。 このメソッドは常に 1 を返します。
add_entry($word, $heading_position, $text_position)
検索語ファイルに検索語を一つ追加します。 $word が追加する検索語、 $heading_position が見出しの位置、 $text_position が本文の位置です。 見出しと本文の位置は、FreePWING::FPWUtils::Heading および FreePWING::FPWUtils::Text クラスのオブジェクトが持っている entry_position() メソッドを使って取得します。 このメソッドは成功すれば 1 を、失敗すれば 0 を返します。 追加する検索語の最大長は 255 バイトです。
file_name()
検索語ファイルを開いたときに指定したファイル名を返します。
entry_count()
現在までに書き込んだエントリ数を返します。
error_message()
このクラスのメソッドを呼び出して、処理結果が失敗に終わった場合 (0 を 返してきた場合)、エラーメッセージを返します。 エラーが発生していなければ、空の文字列が返ります。

FreePWING::FPWUtils::Text クラス

FreePWING::FPWUtils::Text は、本文を生成するためのクラス です。 以下のメソッドを持っています。

new()
FreePWING::FPWUtils::Text クラスのオブジェクトを生成して、その リファレンスを返すクラスメソッドです。 通常は直接このメソッドを呼び出さずに、fpwutils が提供する initialize_fpwparser() サブルーチンを用います。
open()
書き込み用に本文ファイルを開きます。 ファイル名は、あらかじめモジュール内で指定されたものが使用されます。 成功すれば 1 を、失敗すれば 0 を返します。 通常は直接このメソッドを呼び出さずに、fpwutils が提供する initialize_fpwparser() サブルーチンを用います。
close()
open() メソッドで開いたファイルをすべて閉じます。 成功すれば 1 を、失敗すれば 0 を返します。 開いていなければ何もせず、1 を返します。 通常は直接このメソッドを呼び出さずに、fpwutils が提供する finalize_fpwparser() サブルーチンを用います。
new_context()
現在のエントリおよびコンテキストを終端させ、新たなコンテキストを開始し ます。 成功すれば 1 を、失敗すれば 0 を返します。 このメソッドを呼び出すには、あらかじめ本文ファイルを開いていなければな りません。 本文ファイル開いた直後の一文字もデータを書き込んでいない状態で、このメ ソッドを呼んでも、新たなコンテキストを開始することはしません。 これにより、最初のコンテキストに対しては、明示的にこのメソッドを呼んで も呼ばなくてもどちらでも良いようになっています。
new_entry()
現在のエントリを終端させ、新たなエントリを開始します。 成功すれば 1 を、失敗すれば 0 を返します。 このメソッドを呼び出すには、あらかじめ本文ファイルを開いていなければな りません。 ファイル開いた直後および new_context() で新たなコンテキス トを開始した直後の一文字もデータを書き込んでいない状態で、このメソッド を呼んでも、さらに新たなエントリを開始することはしません。 これにより、先頭のエントリに対しては、明示的にこのメソッドを呼んでも呼 ばなくてもどちらでも良いようになっています。
add_text($text)
引数 $text で指定した文字列を本文に追加します。 文字列は、EUC-JP で書かれていなくてはなりません。 ただし、$text 中に出現する改行文字 (CR および LF) は無視 されます。 このメソッドを呼び出すには、あらかじめ本文ファイルを開いていなければな りません。 成功すれば 1 を、失敗すれば 0 を返します。
add_half_user_character($character_name)
add_full_user_character($character_name)
add_half_user_character() は引数 $character_name で指定した半角外字を本文に追加します。 同様に add_full_user_character() は、全角外字を追加します。 $character_name は、外字定義ファイルの中で定義されている 外字名でなければなりません。 成功すれば 1 を、失敗すれば 0 を返します。
add_tag($tag)
本文の現在位置に対して、$tag という名前のタグを設定します。 このメソッドを呼び出すには、あらかじめ本文ファイルと参照情報ファイル、 タグファイルを開いていなければなりません。 タグ名は本文、メニュー、著作権表示データ内で一意のものでなくてはなりま せん。 このメソッドは成功すれば 1 を、失敗すれば 0 を返します。
add_keyword_start()
add_keyword_end()
add_keyword_start() は検索キー開始指定子を、 add_keyword_end() は検索キー終了指定子を、それぞれ呼ばれた 時点での本文の現在位置に挿入します。 メソッドを呼び出すには、あらかじめ本文ファイルを開いていなければなりま せん。 いずれのメソッドも成功すれば 1 を、失敗すれば 0 を返します。 使用方法に関しては、 読み込んだ見出しの処理本文に関する注意点修飾指定子 の節もあわせてご覧下さい。
add_reference_start()
add_reference_end($position)
add_reference_start() は参照開始指定子を、 add_reference_end() は参照終了指定子を、それぞれ呼ばれた 時点での本文の現在位置に挿入します。 参照先の位置は $position で指定します。 メソッドを呼び出すには、あらかじめ本文ファイルを開いていなければなりま せん。 成功すれば 1 を、失敗すれば 0 を返します。 使用方法に関しては、 相互参照 の節もあわせてご覧下さい。
add_subscript_start()
add_subscript_end()
add_subscript_start() は下添え字開始指定子を、 add_subscript_end() は下添え字終了指定子を、それぞれ呼ば れた時点での本文の現在位置に挿入します。 メソッドを呼び出すには、あらかじめ本文ファイルを開いていなければなりま せん。 成功すれば 1 を、失敗すれば 0 を返します。 使用方法に関しては、 修飾指定子 の節もあわせてご覧下さい。
add_indent_level($level)
本文の行頭の字下げ量を $level に設定します。 指定できるのは、2 から 6 までの整数です。 また、各エントリ開始時に自動的に 1 に設定されます。 メソッドを呼び出すには、あらかじめ本文ファイルを開いていなければなりま せん。 成功すれば 1 を、失敗すれば 0 を返します。
add_newline()
本文の現在位置に改行を挿入します。 メソッドを呼び出すには、あらかじめ本文ファイルを開いていなければなりま せん。 成功すれば 1 を、失敗すれば 0 を返します。
add_superscript_start()
add_superscript_end()
add_superscript_start() は上添え字開始指定子を、 add_superscript_end() は上添え字終了指定子を、それぞれ呼 ばれた時点での本文の現在位置に挿入します。 メソッドを呼び出すには、あらかじめ本文ファイルを開いていなければなりま せん。 成功すれば 1 を、失敗すれば 0 を返します。 使用方法に関しては、 修飾指定子 の節もあわせてご覧下さい。
add_nowrap_start()
add_nowrap_end()
add_nowrap_start() は分割禁止開始指定子を、 add_nowrap_end() は分割禁止終了指定子を、それぞれ呼ばれた 時点での本文の現在位置に挿入します。 メソッドを呼び出すには、あらかじめ本文ファイルを開いていなければなりま せん。 成功すれば 1 を、失敗すれば 0 を返します。 使用方法に関しては、 修飾指定子 の節もあわせてご覧下さい。
add_emphasis_start()
add_emphasis_end()
add_emphasis_start() は強調開始指定子を、 add_emphasis_end() は強調終了指定子を、それぞれ呼ばれた時 点での本文の現在位置に挿入します。 メソッドを呼び出すには、あらかじめ本文ファイルを開いていなければなりま せん。 成功すれば 1 を、失敗すれば 0 を返します。 使用方法に関しては、 修飾指定子 の節もあわせてご覧下さい。
add_font_start($font_name)
add_font_end()
add_font_start() は別フォント開始指定子を、 add_font_end() は同終了指定子を、それぞれ呼ばれた時点での 本文の現在位置に挿入します。 引数の $font_name として有効な値は、'italic' (イタリック体を指定) および 'bold' (ボールド体を指定) の 2 種類です。 メソッドを呼び出すには、あらかじめ本文ファイルを開いていなければなりま せん。 成功すれば 1 を、失敗すれば 0 を返します。 使用方法に関しては、 修飾指定子 の節もあわせてご覧下さい。
file_name()
現在開いている本文のファイル名を返します。 本文のファイルを開いていなければ、空の文字列を返します。
reference_file_name()
現在開いている参照情報ファイル名を返します。 参照情報ファイルを開いていなければ、空の文字列を返します。
tag_file_name()
現在開いているタグファイル名を返します。 タグファイルを開いていなければ、空の文字列を返します。
context_position()
現在のコンテキストの先頭位置を返します。 ただし、本文のファイルを開いていない場合は 0 を返します。
entry_position()
現在のエントリの先頭位置を返します。 ただし、本文のファイルを開いていない場合は 0 を返します。
context_count()
現在のコンテキストが、何番目のコンテキストなのかを返します。
entry_count()
現在のエントリが、現在のコンテキストの中で何番目のコンテキストなのかを 返します。
total_entry_count()
現在のエントリが、本文ファイル全体の中で何番目のコンテキストなのかを返 します。
error_message()
このクラスのメソッドを呼び出して、処理結果が失敗に終わった場合 (0 を 返してきた場合)、エラーメッセージを返します。 エラーが発生していなければ、空の文字列が返ります。

FreePWING::FPWUtils::Heading クラス

FreePWING::FPWUtils::Heading は、見出しを生成するための クラスです。 FreePWING::FPWUtils::Text クラスとだいたい同じメソッドを 持っていますが、次のメソッドは使用できなくなっています。

その他のメソッドの使用方法については、 FreePWING::FPWUtils::Text クラス を参照して下さい。

FreePWING::FPWUtils::Menu クラス

FreePWING::FPWUtils::Menu は、メニューを生成するためのク ラスです。 FreePWING::FPWUtils::Text とまったく同じメソッド群を持っ ています。

FreePWING::FPWUtils::Copyright クラス

FreePWING::FPWUtils::Copyright は、著作権表示を生成するた めのクラスです。 FreePWING::FPWUtils::Text とまったく同じメソッド群を持っ ています。

FreePWING::FPWUtils::FPWParser モジュール

他の FreePWING 付属の Perl モジュールとは異なり、 FreePWING::FPWUTils::FPWParser モジュールではクラスを定義 しません。 代わりに、main パッケージに対してサブルーチンや変数を定義 し、コマンド行のオプションの解析処理を行います。

サブルーチン

FreePWING::FPWUTils::FPWParser モジュールが定義するサブルー チンには initialize_fpwparser()finalize_fpwparser() があります。

initialize_fpwparser() は FreePWING 関係のクラスのオブジェ クトを初期化するためのサブルーチンで、次のように 2 つの要素を組にして 並べたものを引数にとります。

  initialize_fpwparser('word2' => \$w, 'text' => \$t);

要素の組はそれぞれ、1 番目の引数には 'word', 'endword' のような名前を示す文字列をとり、2 番目の引数に は変数へのリファレンスを取るようにします。 1 番目のパラメタとして認識される文字列とその用途は、次の通りです。

word2
前方一致、後方一致検索ための検索語の登録用に FreePWING::FPWUtils::Word2 クラスのオブジェクトを生成し、 初期化します。
heading
見出しデータ登録用に FreePWING::FPWUtils::Heading クラス のオブジェクトを生成し、初期化します。
text
本文データ登録用に FreePWING::FPWUtils::Text クラスのオブ ジェクトを生成し、初期化します。
menu
メニューのデータ登録用に FreePWING::FPWUtils::Text クラス のオブジェクトを生成し、初期化します。
copyright
著作権表示データ登録用に FreePWING::FPWUtils::Text クラス のオブジェクトを生成し、初期化します。

生成して初期化されたオブジェクトは、要素の各組の 2 番目の引数にリファ レンスの参照先としてセットされます。 このサブルーチンは、処理に成功すると 1 を、失敗すると 0 を返します。

finalize_fpwparser()initialize_fpwparser() で生成したオブジェクトを使い終わっ たときに呼び出すサブルーチンで、各オブジェクトに対して後処理を行います。 引数の書式は initialize_fpwparser() とまったく同じです。 このサブルーチンも、処理に成功すると 1 を、失敗すると 0 を返します。

initialize_fpwparser(), finalize_fpwparser() の具体的な使用例については fpwutils 対応 をご覧下さい。

変数

FreePWING::FPWUtils::FPWParser モジュールによって定義され る変数には以下のものがあります。

$work_directory
作業ディレクトリ名
(コマンド行オプションの解析 を参照 のこと)
$text_file_name
本文を記録するファイル名
(値: "$work_directory/text")
通常、FreePWING::FPWUtils::Word2::add_entry() を呼び出す 際に、第 2 引数として渡します。
$text_ref_file_name
本文用の参照情報ファイルを記録するファイル名
(値: "$work_directory/textref")
$text_tag_file_name
本文用のタグファイルを記録するファイル名
(値: "$work_directory/texttag")
$menu_file_name
メニューを記録するファイル名
(値: "$work_directory/menu")
$menu_ref_file_name
メニュー用の参照情報ファイルを記録するファイル名
(値: "$work_directory/menuref")
$menu_tag_file_name
メニュー用のタグファイルを記録するファイル名
(値: "$work_directory/menutag")
$copyright_file_name
著作権表示を記録するファイル名
(値: "$work_directory/copy")
$copyright_ref_file_name
著作権表示用の参照情報ファイルを記録するファイル名
(値: "$work_directory/copyref")
$copyright_tag_file_name
著作権表示用のタグファイルを記録するファイル名
(値: "$work_directory/copytag")
$heading_file_name
見出しを記録するファイル名
(値: "$work_directory/head")
通常、FreePWING::Word2::add_entry() を呼び出す際に、第 3 引数として渡します。
$word_file_name
前方一致検索用の検索語一覧を記録するファイル名
(値: "$work_directory/word")
$endword_file_name
後方一致検索用の検索語一覧を記録するファイル名
(値: "$work_directory/eword")
$sort_file_name
前方一致検索用のソート済み検索語一覧を記録するファイル名
(値: "$work_directory/sort")
$endsort_file_name
後方一致検索用のソート済み検索語一覧を記録するファイル名
(値: "$work_directory/esort")
$index_file_name
前方一致検索インデックスを記録するファイル名の接頭辞
(値: "$work_directory/idx")
$index_ref_file_name
前方一致検索インデックス用の参照情報を記録するファイル名の接頭辞
(値: "$work_directory/idxref")
$endindex_file_name
後方一致検索インデックスを記録するファイル名
(値: "$work_directory/eidx")
$endindex_ref_file_name
後方一致検索インデックス用の参照情報を記録するファイル名
(値: "$work_directory/eidxref")
$control_file_name
書籍管理情報を記録するファイル名
(値: "$work_directory/ctrl")
$control_ref_file_name
書籍管理情報用の参照情報を記録するファイル名
(値: "$work_directory/ctrlref")
$honmon_file_name
JIS X 4081 形式の最終生成ファイル名
(値: "honmon")
$half_char_name_file_name
半角外字の名前と文字番号の割り当ての対応表を記録するファイル名
(値: "$work_directory/halfchar")
$full_char_name_file_name
全角外字の名前と文字番号の割り当ての対応表を記録するファイル名
(値: "$work_directory/fullchar")
$half_char_bitmap_16_file_name
$half_char_bitmap_24_file_name
$half_char_bitmap_30_file_name
$half_char_bitmap_48_file_name
半角外字のビットマップファイル名
(値: "gai16h""gai24h""gai30h""gai48h")
$full_char_bitmap_16_file_name
$full_char_bitmap_24_file_name
$full_char_bitmap_30_file_name
$full_char_bitmap_48_file_name
全角外字のビットマップファイル名
(値: "gai16f""gai24f""gai30f""gai48f")

コマンド行オプションの解析

FreePWING::FPWUTils::FPWParserGetopt::Long モジュールを用いてコマンド行オプションの解析 を行います。 この解析処理は、モジュールを読み込みさえすれば自動的に行われますので、 ユーザ側で明示的にサブルーチンを呼ぶ必要はありません。 今のところ、コマンド行オプションには次のものが定義されています。

-workdir directory
作業ディレクトリの位置を指定します。 指定しなければ 'work' が使われます。 プログラム内では、変数$work_directory で参照できます。

解析後、指定されたオプションは @ARGV から取り除かれます。 残りの引数をどう解釈するかは、ユーザの処理プログラムに任されます。 未知のオプションが指定された場合はエラーとなり、その時点でプログラムを 強制的に終了します。

古い作業ファイルの削除

FreePWING::FPWUtils::FPWParser は古い作業ファイルが作業ディ レクトリに残っていると、それを削除します。 削除に失敗しても、エラーとして報告することはしません。

fpwmake コマンド

fpwmake コマンドの実体は sh スクリプトで、中で GNU make を呼び出します。

たとえば、GNU make のコマンド名が /usr/local/bin/gmakefpwutils.mk ファイルがインストールされているディレクトリ が /usr/local/share/freepwing だとすると、

  % fpwmake 引数...

という呼び出しは、実際には

  % /usr/local/bin/gmake -I/usr/local/share/freepwing 引数...

という処理を手動で実行するのとまったく同じことです。

GNU make について詳しく知りたい方は、GNU make のドキュメントをお読み下 さい。

fpwutils.mk ファイル

fpwutils.mk ファイルの中で、いくつかのマクロ、生成規則を 定義していますが、詳細については fpwutils.mk ファイルを直 接ご覧になって下さい。