Ruby1.9.1(じゃなくてtrunkだから1.9.2dev)と格闘してみる

ほんとは格闘するんじゃなくて仲良くなれればいいと思うのだが。


なかださんがr23729で修正したとのコメントをくれたので試してみた。
が、まだエラーが出る。
なんだかややこしいことになってしまっているので、俺もできるだけ協力しようと思って調べたり実験したりしてみた。
以下がその記録。


r23729で変更されているのはこの1行。

        rb_enc_associate_index(result, rb_usascii_encindex());

これをコンパイルして実行すると、

D:\tmp>あ\bin\ruby
:3:in `require': incompatible character encodings: ASCII-8BIT
and US-ASCII (Encoding::CompatibilityError)
from :3:in `block in '
from :1:in `each'
from :1:in `'

というエラーになった。
前のんと違う所はエンコードの名前だ。
相変わらず「あ」という名前を英語名に直すと動く。
ふむー。
エラーが出てるのはfile.cのfile_expand_path関数内の最後、

    rb_enc_check(fname, result);

で、
この関数は

rb_encoding*
rb_enc_check(VALUE str1, VALUE str2)
{
    rb_encoding *enc = rb_enc_compatible(str1, str2);
    if (!enc)
	rb_raise(rb_eEncCompatError, "incompatible character encodings: %s and %s",
		 rb_enc_name(rb_enc_get(str1)),
		 rb_enc_name(rb_enc_get(str2)));
    return enc;
}

となっている。
つまり、取得したパスfnameがASCII-8BITなのに、エンコードを変更したUS-ASCIIと互換性が無い、と言っているらしい。
変更されたところを

//        rb_enc_associate_index(result, rb_usascii_encindex());
        rb_enc_associate_index(result, rb_ascii8bit_encindex());

とすると一致するはずだから、正しく動くかどうかはさて置きとりあえず動くようになるんだろーか、と思ったところ

D:\tmp>あ\bin\ruby
:3:in `require': incompatible character encodings: Windows-31J
and ASCII-8BIT (Encoding::CompatibilityError)
from :3:in `block in '
from :1:in `each'
from :1:in `'

こうなった。
つまり、取得したパスがfnameのWindows-31Jで、俺が変更したresultがASCII-8BITになってて、
こいつらに互換性がありませんよ、と言っているらしい。
えーっと・・・これはどーいうことかというと・・・?
fname側のエンコードが違うつーことは、この2つのコードで、エラーが出ているタイミングが違うということか?


検索したら出てきたcocoamix氏のブログなどを参考にしつつ、
http://d.hatena.ne.jp/cocoamix/20090612/1244795297
デバッガを動かしてたら、確かにfile_expand_pathは何度も呼ばれているようだ。
str1とかの中身を見ようとしてもやりかたがわからんから、

rb_encoding*
rb_enc_check(VALUE str1, VALUE str2)
{
	const char *s;
    rb_encoding *enc = rb_enc_compatible(str1, str2);
	s = StringValuePtr(str1);
	printf("%s\n", s);
	s = StringValuePtr(str2);
	printf("%s\n", s);
    if (!enc)
	rb_raise(rb_eEncCompatError, "incompatible character encodings: %s and %s",
		 rb_enc_name(rb_enc_get(str1)),
		 rb_enc_name(rb_enc_get(str2)));
    return enc;
}

っつー感じにprintfを突っ込んで両方を試してみた。
結果はあまりにも長いためにDXRubyのサイトにこっそり置く。
ついでにデバッガの呼び出し履歴も下にくっつけておいた。
非常に見にくいがヒントになるかもしれない。
US-ASCIIのほう
http://dxruby.sourceforge.jp/kossori/data1.txt
ASCII-8BITのほう
http://dxruby.sourceforge.jp/kossori/data2.txt


んで、これをどう読み解くか、という話なのだが。
なにがなんだかさっぱりわからない。
Rubyの起動時の流れを知らないとダメなのだろう。
それがわかるようになるためには、地道に追いかけていくしかないと思う。
ところで、Windows-31JとASCII-8BITで互換性がないってエラーになるのは、
これはこれで正しいんだろうか。
変換はできなくても、互換性はあってもいいような気がするのだけど。