Forums: 公開討議 (Thread #24912)

utf-16からの変換 (2009-12-22 19:49 by 森島 #47545)

ShiftJISで"日本語"という3文字だけ書かれたファイルa1-sjis.txtを
> nkf -w16L a1-sjis.txt > a1-utf16.txt
としていわゆるUNICODE(UTF-16LE)に変換すると問題なく変換されます。
バイトならびは FF FE E5 65 2C 67 9E 8Aで全く問題が無いように見えます。

今度は、これを
>nkf -W16Ls a1-utf16.txt
としても全くなにも出力されません。これはバグでしょうか?

OSはWindowsXP、nkfは2.0.9(Vectorに上がっているもの、nkf32とnkfwinで試しました)でも
2.1.0(VC 2008 Expressでコンパイル)でも同じでした。

また-eや-jオプションも-sと同様、全くなにも出力されないようです。

Reply to #47545×

You can not use Wiki syntax
You are not logged in. To discriminate your posts from the rest, you need to pick a nickname. (The uniqueness of nickname is not reserved. It is possible that someone else could use the exactly same nickname. If you want assurance of your identity, you are recommended to login before posting.) Login

RE: utf-16からの変換 (2009-12-24 11:00 by morishima #47564)

自己フォローです。

Visual Studio 2008 Express EditionのVC++(MSCとしてはver.15)にて
コンパイルした場合のnkf.exeが -W16などの動作がしない件ですが、
取りあえず、-O2オプションがついているとだめであることが分かりました。

VisualStudioは2005から、Express Editionでも最適化機能がついたはずなのですが
なぜかここでは最適化させると問題が生じるようです。どこで問題が生じるのかは
フォローしていませんが。

公開されているファイル(tar)の中に、VC++用のnkf32.makがあり、この中にCFLAGSが
-O2 オプションと共に設定されていますが、これは外しておいた方がよいのではないでしょうか。

それから、KONOさんの作られたtestに、-W16系への変換のテストが入っていないので、
うまく行かなくても見逃されているのかも知れません。UTF-16のテキストはWindowsでは
typeコマンドやnotepadで一発表示が可能なもので、私が思うには結構標準の1つに近いので、
できることなら、テストに加えていただければありがたいと思います。

VC++のStandard version以上をお持ちの方は一度テストしていただけないでしょうか。
tarボールを解凍して、
> nmake -f nkf32.mak all
とするだけです。

Reply to #47545

Reply to #47564×

You can not use Wiki syntax
You are not logged in. To discriminate your posts from the rest, you need to pick a nickname. (The uniqueness of nickname is not reserved. It is possible that someone else could use the exactly same nickname. If you want assurance of your identity, you are recommended to login before posting.) Login

RE: utf-16からの変換 (2009-12-24 16:02 by sava #47567)

こんにちは。
VC は使っていないので外しているかもしれませんが、
関係ありそうなところとしては、このあたりが考えられます。

--- nkf.c.orig 2009-11-17 09:33:04 +0900
+++ nkf.c 2009-12-24 15:41:52 +0900
@@ -5403,7 +5403,7 @@
else if (iconv == w_iconv16) {
while ((c1 = (*i_getc)(f)) != EOF &&
(c2 = (*i_getc)(f)) != EOF) {
- if (nkf_iconv_utf_16(c1, c2, 0, 0) == -2 &&
+ if (nkf_iconv_utf_16(c1, c2, 0, 0) == (size_t)(NKF_ICONV_NEED_TWO_MORE_BYTES) &&
(c3 = (*i_getc)(f)) != EOF &&
(c4 = (*i_getc)(f)) != EOF) {
nkf_iconv_utf_16(c1, c2, c3, c4);

nkf_iconv_utf_16 は size_t を返すので、「マイナスになんか
なるわけねーよ」ということで最適化でこの部分がごっそり
なかったことにされる可能性があります。
ちなみに mingw の gcc-4.4.0 では、無変更でも -O3 で期待通りに
動作しました。
Reply to #47564

Reply to #47567×

You can not use Wiki syntax
You are not logged in. To discriminate your posts from the rest, you need to pick a nickname. (The uniqueness of nickname is not reserved. It is possible that someone else could use the exactly same nickname. If you want assurance of your identity, you are recommended to login before posting.) Login

RE: utf-16からの変換:解決 (2009-12-24 21:11 by morishima #47570)

savaさん、お返事大変有難うございました。

お返事に勇気を得て、調べて見たところ、同じような箇所ですが、ちょっと違っていました。
w_iconv32もw_iconv16も0を返す関数で、その関数ポインタの値そのものが、
関数ポインタiconvによって利用されていて、入力がUTF-16かUTF-32かを判定する基準として使われています。

VCでは、最適化すると、こんな関数は1つにまとめてしまうことが分かりました。それで5396行目あたりの
iconvがw_iconv32かどうかを判定するところで、本当は、iconv == w_iconv16であるにも関わらず。
最適化のため、w_iconv32 == w_iconv16 とされているので、おかしくなってしまったというのが
真相のようです。

関数レベルのリンクの有効化を無効にするように、/O2 /Gy- というように
コンパイラーオプションに /Gy-を付加すると問題が無くなりました。

tarと一緒に配布されるnkf.makファイルのCFLAGにこのオプションを付加していただければ幸いです。

どうもお騒がせいたしました。

Reply to #47545

Reply to #47570×

You can not use Wiki syntax
You are not logged in. To discriminate your posts from the rest, you need to pick a nickname. (The uniqueness of nickname is not reserved. It is possible that someone else could use the exactly same nickname. If you want assurance of your identity, you are recommended to login before posting.) Login

RE: utf-16からの変換:解決 (2009-12-25 13:34 by sava #47577)

やはり外していたようで…どうも失礼いたました。
なるほど、w_iconv16 も w_iconv32 も中味が完全に同じ(return 0 のみ)なので最適化でひとつにされてしまったということなのでしょうか。

こういうことがあるんですね。個人的には有意義な情報でした。
Reply to #47570

Reply to #47577×

You can not use Wiki syntax
You are not logged in. To discriminate your posts from the rest, you need to pick a nickname. (The uniqueness of nickname is not reserved. It is possible that someone else could use the exactly same nickname. If you want assurance of your identity, you are recommended to login before posting.) Login

RE: utf-16からの変換:解決 (2010-01-06 13:13 by naruse #47755)

あー、なるほど。
戻り値を変えてみました。
commit 022375581dc0961d6f2fcb18bcaf7bd1afd5617b
Reply to #47570

Reply to #47755×

You can not use Wiki syntax
You are not logged in. To discriminate your posts from the rest, you need to pick a nickname. (The uniqueness of nickname is not reserved. It is possible that someone else could use the exactly same nickname. If you want assurance of your identity, you are recommended to login before posting.) Login