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' など) を見つけられます。 これも、主に辞書タイプの書籍で使います。
条件一致検索
  前方一致や完全一致検索とは異なり、複数の単語すべてにマッチするエント リを探し出すための検索方法として、条件検索 (keyword search) がありま す。 たとえば、英語辞典で入力した英単語すべてを用いた例文を探す機能を実現 するときなどに使用することができます。
外字
  書籍固有の字を定義して、使うこととができます。

なお、この一覧には「完全一致検索」(ユーザが入力した単語に対して、完全 に一致する単語の検索) はありません。 これは、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.pl` や `Jcode.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 つの引数が必要です。

- 登録する検索語自身
  (例:「たいさく」)
- その検索語の見出しの開始位置
  (`$fpwheading->entry_position()` で得られる位置)
- その検索語の本文の開始位置
  (`$fpwtext->entry_position()` で得られる位置)

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

## 読み込んだ本文の処理

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

         ## 次の一行 (説明) を読み込む。
         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

処理が正常に終了すると、カレントディレクトリには `word`、 `eword`、`head`、`text`、 `textref`、`texttag` というファイルが生成されま す。 これらのファイルは 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 で 生成し直す羽目になってしまいます。

## `ALLDEPS` と `CLEANEXTRA`ターゲット

もし 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 = $fpwtext->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 の文字 (補助漢字) は使用することができず、与えるとエ ラーになります。

## 検索語に関する注意点

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

- 検索語の長さは最長 255 バイトまでとなります。
  検索語内の文字はすべて JIS X 0208 の文字 (全角文字) に変換されてから登 録されますので、どの文字も一律 2 バイト消費することになります。 したがって、最長で 127 文字ということになります。
- 逆に、検索語は最低でも 1 バイト (1 文字) ないといけません。
  空の文字列は登録できないので注意して下さい。
- 検索語に「　」「’」「−」「・」「‐」という文字が入っていると、それ らは削除した上で登録されます。
  これらの文字だけからなる語は空文字列になってしまいますので、登録でき ません。
- 検索語内の英小文字は大文字に変換してから登録されます。
  また、検索ソフトウェアが検索する際は大文字と小文字は区別しません。 したがって、変換スクリプトでは小文字大文字の区別を意識する必要はありま せん。
- 検索語内にカタカナが含まれていた場合、ひらがなに変換した検索語も一緒に 登録されます。
  したがって、カタカナを含んだ語はひらがなでも引けるようになります。 ただし、反対にひらがなをカタカナに変換した検索語は登録されません。
- 同じ検索語は何度でも登録できます。
  逆に間違って重複して登録してしまうと、検索したときに同じエントリが何 個も見つかることになってしまいます。 気をつけましょう。

## 本文に関する注意点

本文の各エントリの冒頭では、以下のように `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.gz`、 `kokugo-fpw1.0.zip` になります。
`PACKAGEEXTRA`
  JIS X 4081 形式に変換した書籍データ一式 (`catalogs`、 `honmon` および外字ファイル) を収めたアーカイブを作る際に、 書籍データ以外に一緒に入れるファイルを書き並べます。 `ファイル名=ファイル名' という形で指定した場合は、左辺のファイルを右辺 のファイル名に改名してパッケージに入れることを意味します。
`PACKAGEDEPS`
  変換プログラム一式のアーカイブを作成する際に、ここに書かれたターゲット が前もって実行されます。 `PACKAGEEXTRA` で指定したファイルの中に、最初から用意されて いるファイルではなく、何らかの処理をして生成しなくてはならないファイル があった場合は、この `PACKAGEDEPS` に書き、生成方法を `Makefile` の中に記しておくと良いでしょう。
`ARCHIVEEXTRA`
  変換プログラム一式のアーカイブを作る際に、`README`、 `Makefile`、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.gz`、`kokugo-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

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

## 本文への外字の書き込み

外字を本文中で使用するには、あらかじめ `fpwhalfchar`、 `fpwfullchar` コマンドを実行して、定義された外字の参照ファ イルを用意しておかなければなりません。 つまり、`fpwhalfchar`、`fpwfullchar` は変換プロ グラムよりも前に実行する必要があります。 (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_entry_tag()` を呼び出します。

      $fpwtext->add_entry_tag("engine");

この他にもう一つ、`add_tag()` というメソッドも用意されてい ます。 こちらは、メソッドを呼び出した時点での本文の書き込み位置に対してタグが 割り当てます。 (書き込み位置が移動した後も、タグは常にその位置を指し続けます。)

      $fpwtext->add_tag("engine-2");

`add_tag()`を使えば、エントリの文章の途中の位置でタグを割り 当てることができます。 ただし、必ず本文の修飾指定が何も行われていない個所で割り当てるようにし て下さい。 修飾指定が行われている場所を指定してしまうと、本文の他の場所からそのタ グの位置を参照した場合、修飾指定が正しい入れ子になりません (修飾指定子 を参照のこと)。

また、タグがエントリの開始位置を指すようにしたい場合は、必ず `add_entry_tag()` メソッドのほうを使って下さい。 たとえ `new_entry()` メソッドを呼び出して新しいエントリを開 始した直後であっても、`add_tag()` メソッドは使ってはいけま せん。

`new_entry()` メソッドは新しくエントリを開始する際に、エント リの本文の先頭部分に何バイトかのデータを書き込みます。 `add_entry_tag()` メソッドを使うと、`new_entry()` が先頭に付加したデータの前にタグを割り当てますので、タグはエントリの正 確な開始位置を指すことになります。 それに対して、`add_tag()` メソッドは先頭部分に書き込まれたデー タの後にタグを割り振ってしまいます。

さて、ここまではタグの割り当て方の話です。 タグは参照先を示すものですので、タグを割り当てたら、そのタグの参照元で は参照情報を埋め込みます。

参照情報は語句に対して付加するので、開始指定と終了指定があります。 たとえば、先ほど割り当てた 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()` で「本文」を切り替えた後に和英辞 典の本文データを書き込む、という手順になります。

なお、相互参照 用のタグは、本文を切り 替えても共有されますので、タグ名は必ず `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::KeyWord` クラスのオブジェクトを用意 する必要があります。

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

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

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

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

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

使い方は `FreePWING::FPWUtils::Word2` クラスのオブジェクト まったくと同じで、エントリの追加は `add_entry` メソッドを 用います。

         ## かなの検索語を登録する。
         if (!$fpwkeyword->add_entry($kanaword, $heading_position,
             $text_position)) {
            die $fpwkeyword->error_message() . "\n";
         }

# リファレンスマニュアル

## `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::KeyWord` クラス

`FreePWING::FPWUtils::KeyWord` は、条件検索用の検索語一覧を 同時に生成するためのクラスです。 このクラスのオブジェクトが有するメソッドは、 `FreePWING::FPWUtils::Word2`クラス とまったく同じですので、そちらを参照して下さい。

## `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)`
`add_entry_tag($tag)`
  `add_tag($tag)` は本文の現在位置に対して、 `add_entry_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` クラスとだいたい同じメソッドを 持っていますが、次のメソッドは使用できなくなっています。

- new_context()
- add_tag()
- add_keyword_start()
- add_keyword_end()
- add_reference_start()
- add_reference_end()
- add_newline()
- add_indent_level()

その他のメソッドの使用方法については、 `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::FPWParser` は `Getopt::Long` モジュールを用いてコマンド行オプションの解析 を行います。 この解析処理は、モジュールを読み込みさえすれば自動的に行われますので、 ユーザ側で明示的にサブルーチンを呼ぶ必要はありません。 今のところ、コマンド行オプションには次のものが定義されています。

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

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

### 古い作業ファイルの削除

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

## `fpwmake` コマンド

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

たとえば、GNU make のコマンド名が `/usr/local/bin/gmake`、 `fpwutils.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` ファイルを直 接ご覧になって下さい。