NKF 2.0.6 のその前に ― 2005年11月09日 23時46分01秒
ここのところ成瀬さんにNKF のUNICODEマッピングに関することをいろいろと 教えてもらっています。 ところで、JISX0208 の範囲の文字だけ各ツールで変換してみたところ
Perl
JIS EUC-JP JISX0208 Encode Iconv Iconv nkf
X208 *1 EUC-JP EUC-JP EUC-JP-MS 2.0.15
---------------------------------------------------------------
213D 0xa1bd ― U+2015 : U+2015 : U+2014 : U+2015 : U+2015
2140 0xa1c0 \ U+005c : U+ff3c : U+ff3c : U+ff3c : U+ff3c
2141 0xa1c1 ~ U+301c : U+301c : U+301c : U+ff5e : U+301c
2142 0xa1c2 ∥ U+2016 : U+2016 : U+2016 : U+2225 : U+2016
215D 0xa1dd - U+2212 : U+2212 : U+2212 : U+ff0d : U+2212
2171 0xa1f1 ¢ U+00a2 : U+00a2 : U+00a2 : U+ffe0 : U+00a2
2172 0xa1f2 £ U+00a3 : U+00a3 : U+00a3 : U+ffe1 : U+00a3
224C 0xa2cc ¬ U+00ac : U+00ac : U+00ac : U+ffe2 : U+00ac
*1
http://www.unicode.org/Public/MAPPINGS/OBSOLETE/EASTASIA/JIS/JIS0
208.TXT
のマッピングによる変換
という結果が得られました。 Perl Encode の EUC-JP や Iconv の EUC-JP は JIS0208.TXT のマッピングかと思っていましたが、違うのですね。 今頃知りました。 んー。こんなに違うと嫌ですね。 結局、mknmz では Text::Iconv を、namazu は libiconv(glibc の iconv) を 使うというようにツールを統一しないといけないかもしれません。 それにしても Perl の Encode のマッピングは結構謎です。 そのため、Encode を mknmz で使ってしまうと、namazu 側で困るかもしれません。 # あぁ、厄介。
テキスト整形に関して ― 2005年11月01日 14時38分18秒
> 前処理として分かち書きの前にテキストを整形します。
>
> また、
> ・行頭、行末の空白文字を削除
> ・改行は日本語の単語の区切とは見なさない。(改行を連結)
> ・空白行は単語の区切とする
> というようにしました。
という上記に関係する処理ですが、実は gfilter::line_adjust_filter と思想的には同じものでした。(処理は多少異なる)
gfilter::line_adjust_filter と重複するのは何ですので、将来的にはgfilter::line_adjust_filter を廃止し、mknmz 側で処理するようにしたいと思います。
これは、
- plain テキストでは処理が通らないのはまずい
- 全てのフィルタで処理するものを各フィルタから呼び出さないといけないのは面倒
という理由によるものです。
>
> また、
> ・行頭、行末の空白文字を削除
> ・改行は日本語の単語の区切とは見なさない。(改行を連結)
> ・空白行は単語の区切とする
> というようにしました。
という上記に関係する処理ですが、実は gfilter::line_adjust_filter と思想的には同じものでした。(処理は多少異なる)
gfilter::line_adjust_filter と重複するのは何ですので、将来的にはgfilter::line_adjust_filter を廃止し、mknmz 側で処理するようにしたいと思います。
これは、
- plain テキストでは処理が通らないのはまずい
- 全てのフィルタで処理するものを各フィルタから呼び出さないといけないのは面倒
という理由によるものです。
Re: ワイド文字のAPI ― 2005年10月25日 07時21分34秒
perlrun の -C を見ると
(In Perls earlier than 5.8.1 the -C switch was a Win32-only switch that enabled the use of Unicode-aware ``wide system call'' Win32 APIs. This feature was practically unused, however, and the command line switch was therefore ``recycled''.)
(5.8.1より前のperlでは-CスイッチはWin32 APIのunicodeを意識した「wide system call」の使用を有効にするwin32専用のスイッチだった。この機能は実質的に使われなかったので、その結果コマンドラインスイッチはリサイクルされた。)
となっており、-C が 5.8.1 以降変更になってしまっています。
${^WIDE_SYSTEM_CALLS} の方はそのまま使えるのかは、まだ確認していませんが、要注意です。
(In Perls earlier than 5.8.1 the -C switch was a Win32-only switch that enabled the use of Unicode-aware ``wide system call'' Win32 APIs. This feature was practically unused, however, and the command line switch was therefore ``recycled''.)
(5.8.1より前のperlでは-CスイッチはWin32 APIのunicodeを意識した「wide system call」の使用を有効にするwin32専用のスイッチだった。この機能は実質的に使われなかったので、その結果コマンドラインスイッチはリサイクルされた。)
となっており、-C が 5.8.1 以降変更になってしまっています。
${^WIDE_SYSTEM_CALLS} の方はそのまま使えるのかは、まだ確認していませんが、要注意です。
cmd.exe /d オプション ― 2005年10月25日 06時53分56秒
「Perl 5.8.1 では system(), バッククオート, 及び, 外部プログラムへのパイプ等で内部で使用する cmd.exe シェルの実行時に /d スイッチを使います. その他のスイッチは, 外部プログラムを実行するときに通常望まれていないと考えられるレジストリからの AutoRun コマンドの実行を無効化します. もし以前の振る舞いを維持したいのなら PERL5SHELL 環境変数に cmd /x/c と設定して下さい.」
とのことです。util::syscmd() の内部から cmd.exe を呼び出す際には /d オプションを付けた方が良いかもしれません。
しかし、cmd /x/c の /x とは何でしょう。
とのことです。util::syscmd() の内部から cmd.exe を呼び出す際には /d オプションを付けた方が良いかもしれません。
しかし、cmd /x/c の /x とは何でしょう。
Re: ワイド文字のAPI ― 2005年10月24日 19時57分40秒
Perl + Win32 環境で
${^WIDE_SYSTEM_CALLS} = 1;
とすると、ワイド文字の API (Unicode 版 Win32 API)を使います。
File::Find でも CP932の第二バイトが 0x5c の文字で終わるディレクトリも扱えますし、-f や -d も問題なく動作します。 (こっちは確認済み)
Win32 の $CodingSystem は全世界共通で UTF-8 として扱えば良いということになります。
この時、ディレクトリ名、ファイル名は UTF-8 になるという点だけは気にしなければなりません。
UTF-8 版 Namazu との親和性は高いと思います。
${^WIDE_SYSTEM_CALLS} = 1;
とすると、ワイド文字の API (Unicode 版 Win32 API)を使います。
File::Find でも CP932の第二バイトが 0x5c の文字で終わるディレクトリも扱えますし、-f や -d も問題なく動作します。 (こっちは確認済み)
Win32 の $CodingSystem は全世界共通で UTF-8 として扱えば良いということになります。
この時、ディレクトリ名、ファイル名は UTF-8 になるという点だけは気にしなければなりません。
UTF-8 版 Namazu との親和性は高いと思います。
ワイド文字のAPI ― 2005年10月24日 19時45分07秒
Perl のドキュメントを調べていると、「Windows プラットホームにおいては, -C コマンドラインスイッチが使われているか, ${^WIDE_SYSTEM_CALLS} グローバルフラグが 1 に設定されているのなら, すべてのシステムコールは対応するワイド文字の API を使います.」と書かれていました。
この機能を Windows で使うと、ワイド文字のAPIが使われるため、ファイル名の処理に直接ワイド文字が使えることになります。
FAT32,NTFS 共 ロングファイル名は Unicode で記録されますから、ANSI 文字でファイルのアクセスをするよりも直接ワイド文字でアクセスする方が安全です。
ANSI文字、日本語の場合 CP932 なら '\' 0x5c がいろいろと厄介な問題*1を起こしますが、ワイド文字で扱うならばそのような厄介な問題は避けられます。
*1 例えば、CP932 の 2バイト目が 0x5c の文字で終わるディレクトリ名の場合、パス区切りと誤認します。
Perl 5.6 以降で有効か?
この機能を Windows で使うと、ワイド文字のAPIが使われるため、ファイル名の処理に直接ワイド文字が使えることになります。
FAT32,NTFS 共 ロングファイル名は Unicode で記録されますから、ANSI 文字でファイルのアクセスをするよりも直接ワイド文字でアクセスする方が安全です。
ANSI文字、日本語の場合 CP932 なら '\' 0x5c がいろいろと厄介な問題*1を起こしますが、ワイド文字で扱うならばそのような厄介な問題は避けられます。
*1 例えば、CP932 の 2バイト目が 0x5c の文字で終わるディレクトリ名の場合、パス区切りと誤認します。
Perl 5.6 以降で有効か?
大文字と小文字 ― 2005年10月24日 08時31分59秒
libnmz には isalpha, isalnum 等のローケルに依存して動作が異なる関数が使われています。
これは、ローケルによって動作が異なるため、注意が必要です。
(ASCII 7bit 文字を引数に渡す場合は問題ありません。)
strcasecmp, strncasecmp もローケル依存のため、注意が必要です。
toupper, tolower は撲滅したはずです。もし、toupper, tolower が使われている箇所があれば、それはバグです。
strcasecmp, strncasecmp がないシステムのために strcasecmp.c, strncasecmp.c は nmz/ に含まれますが、ここでは tolower が使われる可能性があるので、注意が必要です。
これは、ローケルによって動作が異なるため、注意が必要です。
(ASCII 7bit 文字を引数に渡す場合は問題ありません。)
strcasecmp, strncasecmp もローケル依存のため、注意が必要です。
toupper, tolower は撲滅したはずです。もし、toupper, tolower が使われている箇所があれば、それはバグです。
strcasecmp, strncasecmp がないシステムのために strcasecmp.c, strncasecmp.c は nmz/ に含まれますが、ここでは tolower が使われる可能性があるので、注意が必要です。
壊れたインデックスを調査するには ― 2005年10月18日 13時19分04秒
Namazu はときより何らかの理由により、インデックスが壊れることがあります。
主に各種ソフトウェアの不具合によるものですが、具体的には分かりません。また、インデックスが壊れていても気づかないことも多々あります。
このため、インデックスが壊れているか否か検証する方法があるとよさそうです。
そうすれば、インデックスを壊す原因を突き止めやすくなるでしょう。
1. NMZ.i と NMZ.ii の整合性
NMZ.ii の値と、NMZ.i のデータの整合性は検証可能です。
- NMZ.ii のデータ(オフセット)は小さい順に並んでいます。
- NMZ.ii の最初の値は 0 です。
- NMZ.ii の最後の値をオフセットとした NMZ.i の値と先のオフセットを加算すると、NMZ.i のファイルサイズです。
- NMZ.i の単語データ長(+4)を累積していくと NMZ.ii の値と一致するかで検証可能です。(行区切りのチェック)
- NMZ.i の文書IDが小さいもの順に並んでいる。(ただし差分のため、チェックにはあまり有効ではない)
注意) BER 圧縮に注意すること
2. NMZ.w と NMZ.wi の整合性
- 単語ごとに改行が含まれるため、改行の個数が単語の個数です。
- NMZ.w の単語数と、NMZ.wi のデータ数は一致します。
- NMZ.wi のデータ(オフセット)は小さい順に並んでいます。
- NMZ.wi の指す位置はNMZ.wの単語の先頭文字です。 (行区切りのチェック)
- 単語の並びは昇順です。
- nul 文字や制御文字(改行を除く)は含まれません。
- EUC-JP 以外は含まれないはずですが、一部文字化けした単語がゴミとして含まれる可能性はあります。
3. NMZ.w* と NMZ.i* の整合性
- NMZ.i の単語数と NMZ.w の単語数は一致します。
4. NMZ.p と NMZ.pi の整合性
- NMZ.pi は必ず 262144 バイト(2^16 * sizeof(int))です。
- NMZ.pi のデータ(オフセット)は小さい順に並んでいます。
- NMZ.pi の最初の値は 0 です。
- NMZ.pi の最後の値をオフセットとした NMZ.p の値と先のオフセットを加算すると、NMZ.p のファイルサイズです。
- NMZ.p のデータ長(+4)を累積していくと NMZ.pi の値と一致するかで検証可能です。(行区切りのチェック)
5. NMZ.field.xxx と NMZ.field.xxx.i の整合性
- NMZ.w と NMZ.wi の整合性とほぼ同じ
6. 文書IDの整合性
- NMZ.i に含まれる文書IDは、最大文書IDまでです。
- NMZ.p に含まれる文書IDは、最大文書IDまでです。
- NMZ.t は全文書数分のデータです。
- NMZ.field.xxx は有効な全文書数分のデータです。
- NMZ.status の files は有効な全文書数です。
- NMZ.r は全文書数、有効な全文書数の両方の情報が含まれます。
7. 単語数の整合性
- NMZ.status の keys と NMZ.w の単語数は一致します。(文書削除後も)
8. テキストファイルの妥当性
- UNIX 改行
- EUC-JP (除く NMZ.r)
これらをきちんとチェックするツールがあるとインデックスが壊れているかどうか簡単に調べられて便利だと思います。
データのチェックのため、レコード単位でCRC 等をインデックスに含めるのが簡単で良いのかもしれません。
追記:
pnamazu に tool2/nmzcheck.pl がありました。
この文書は、不定期に更新します。
主に各種ソフトウェアの不具合によるものですが、具体的には分かりません。また、インデックスが壊れていても気づかないことも多々あります。
このため、インデックスが壊れているか否か検証する方法があるとよさそうです。
そうすれば、インデックスを壊す原因を突き止めやすくなるでしょう。
1. NMZ.i と NMZ.ii の整合性
NMZ.ii の値と、NMZ.i のデータの整合性は検証可能です。
- NMZ.ii のデータ(オフセット)は小さい順に並んでいます。
- NMZ.ii の最初の値は 0 です。
- NMZ.ii の最後の値をオフセットとした NMZ.i の値と先のオフセットを加算すると、NMZ.i のファイルサイズです。
- NMZ.i の単語データ長(+4)を累積していくと NMZ.ii の値と一致するかで検証可能です。(行区切りのチェック)
- NMZ.i の文書IDが小さいもの順に並んでいる。(ただし差分のため、チェックにはあまり有効ではない)
注意) BER 圧縮に注意すること
2. NMZ.w と NMZ.wi の整合性
- 単語ごとに改行が含まれるため、改行の個数が単語の個数です。
- NMZ.w の単語数と、NMZ.wi のデータ数は一致します。
- NMZ.wi のデータ(オフセット)は小さい順に並んでいます。
- NMZ.wi の指す位置はNMZ.wの単語の先頭文字です。 (行区切りのチェック)
- 単語の並びは昇順です。
- nul 文字や制御文字(改行を除く)は含まれません。
- EUC-JP 以外は含まれないはずですが、一部文字化けした単語がゴミとして含まれる可能性はあります。
3. NMZ.w* と NMZ.i* の整合性
- NMZ.i の単語数と NMZ.w の単語数は一致します。
4. NMZ.p と NMZ.pi の整合性
- NMZ.pi は必ず 262144 バイト(2^16 * sizeof(int))です。
- NMZ.pi のデータ(オフセット)は小さい順に並んでいます。
- NMZ.pi の最初の値は 0 です。
- NMZ.pi の最後の値をオフセットとした NMZ.p の値と先のオフセットを加算すると、NMZ.p のファイルサイズです。
- NMZ.p のデータ長(+4)を累積していくと NMZ.pi の値と一致するかで検証可能です。(行区切りのチェック)
5. NMZ.field.xxx と NMZ.field.xxx.i の整合性
- NMZ.w と NMZ.wi の整合性とほぼ同じ
6. 文書IDの整合性
- NMZ.i に含まれる文書IDは、最大文書IDまでです。
- NMZ.p に含まれる文書IDは、最大文書IDまでです。
- NMZ.t は全文書数分のデータです。
- NMZ.field.xxx は有効な全文書数分のデータです。
- NMZ.status の files は有効な全文書数です。
- NMZ.r は全文書数、有効な全文書数の両方の情報が含まれます。
7. 単語数の整合性
- NMZ.status の keys と NMZ.w の単語数は一致します。(文書削除後も)
8. テキストファイルの妥当性
- UNIX 改行
- EUC-JP (除く NMZ.r)
これらをきちんとチェックするツールがあるとインデックスが壊れているかどうか簡単に調べられて便利だと思います。
データのチェックのため、レコード単位でCRC 等をインデックスに含めるのが簡単で良いのかもしれません。
追記:
pnamazu に tool2/nmzcheck.pl がありました。
この文書は、不定期に更新します。
libnmz 関係の話 ― 2005年10月06日 06時00分38秒
libnmz (nmz.dll) を利用する場合、たくさんのヘッダーファイルをインクルードする必要があります。これは非常に不便です。
メインのヘッダ libnmz.h と、オプション的なものを後2つぐらいまでに整理するべきです。(内部でたくさんのヘッダを使うのは良いとしても)
また、struct nmz_names NMZ、struct nmz_files Nmz 構造体を extern するのはやめ、libnmz 内部でメモリを動的に確保、開放する外部関数を用意した方が良いでしょう。
libnmz は LGPL ではなく GPL なため、ライセンス的に利用しにくいライブラリとなっています。GPL のコードを利用していることもありますし、著者が沢山いらっしゃるので今更 LGPL にライセンスを変更するのは難しいと思われます。
そのためまずは libnmz を使った xmlnamazu コマンド(GPL)を新たに作り、それを呼び出す libnmz LGPL 版(libnmz GPL のラッパとなる)を作ることで、何とか LGPL として使用できるライブラリを用意したいと思います。
将来的には、新たに一から書き直して LGPL 版の libnmz を作りたいと思います。
メインのヘッダ libnmz.h と、オプション的なものを後2つぐらいまでに整理するべきです。(内部でたくさんのヘッダを使うのは良いとしても)
また、struct nmz_names NMZ、struct nmz_files Nmz 構造体を extern するのはやめ、libnmz 内部でメモリを動的に確保、開放する外部関数を用意した方が良いでしょう。
libnmz は LGPL ではなく GPL なため、ライセンス的に利用しにくいライブラリとなっています。GPL のコードを利用していることもありますし、著者が沢山いらっしゃるので今更 LGPL にライセンスを変更するのは難しいと思われます。
そのためまずは libnmz を使った xmlnamazu コマンド(GPL)を新たに作り、それを呼び出す libnmz LGPL 版(libnmz GPL のラッパとなる)を作ることで、何とか LGPL として使用できるライブラリを用意したいと思います。
将来的には、新たに一から書き直して LGPL 版の libnmz を作りたいと思います。
NG は Next Generation ― 2005年10月06日 05時56分26秒
新しいカテゴリ NG を作りました。
このNGは Next Generation の略で、No Good でも Nihongo micro Gnu emacs の略でもありません。
Namazu の次世代(バージョンは不明)に関して思いついたことを書こうと思います。
このNGは Next Generation の略で、No Good でも Nihongo micro Gnu emacs の略でもありません。
Namazu の次世代(バージョンは不明)に関して思いついたことを書こうと思います。
最近のコメント