こんにちは、なかむら(う)です。

talkやlistで話題になったsprintf.cの"%08b"の話ですが、そもそも
あの部分のコードがややこしいのがバグの原因だろう、というわけで
ちょっと整理してみました。
# 負数に対する幅指定時の..の話についてはまだ手付かずです。

if (!bignum) とそうでない部分、それぞれの中での if (sign) とそ
うでない部分は本来は対称構造であるべきだと思うので、素直に else
を追加しました。
これでラベル format_integer へのgotoが不要になったのでそれを
削除し、ついでに無駄なコードも削除しました。
また、tsが導入した変数tmpは実は関数の冒頭で宣言されている(マク
ロGETASTERが使用しています)ので、追加された宣言は削除しました。

以下のパッチは-wなのでインデントがおかしくなりますが、インデ
ントの変更も残した版を
 http://rrr.jin.gr.jp/~usa/ruby/sprintf.diff
に置いてあります。

Index: sprintf.c =================================================================== RCS file: /home/cvs/ruby/sprintf.c,v retrieving revision 1.36 diff -u -1 -p -w -r1.36 sprintf.c --- sprintf.c 17 Feb 2004 15:26:01 -0000 1.36 +++ sprintf.c 18 Feb 2004 00:45:40 -0000 @@ -446,3 +446,2 @@ rb_f_sprintf(argc, argv) int len, pos; - VALUE tmp; @@ -516,2 +515,3 @@ rb_f_sprintf(argc, argv) } + if (!bignum) { @@ -539,5 +539,4 @@ rb_f_sprintf(argc, argv) sprintf(nbuf, fbuf, v); - s = nbuf; - goto format_integer; } + else { s = nbuf; @@ -569,6 +568,6 @@ rb_f_sprintf(argc, argv) } + } s = nbuf; - goto format_integer; } - + else { if (sign) { @@ -589,4 +588,4 @@ rb_f_sprintf(argc, argv) } - goto format_integer; } + else { if (!RBIGNUM(val)->sign) { @@ -600,3 +599,2 @@ rb_f_sprintf(argc, argv) rb_warning("negative number for %%u specifier"); - s++; } @@ -619,8 +617,8 @@ rb_f_sprintf(argc, argv) strcpy(t, s); - bignum = 2; + s = RSTRING(tmp)->ptr; + } + } } } - s = RSTRING(tmp)->ptr; - format_integer: pos = -1;
それでは。 -- U.Nakamura <usa / garbagecollect.jp> というのを昨日投げるつもりで忘れてた