永井@知能.九工大です.

From: "Nobuyasu Hoshino" <n-hoshino / oose.co.jp>
Subject: [ruby-list:40625] Re: 安定版より安定しているバージョンでのTkでエラー
Date: Wed, 16 Feb 2005 14:59:21 +0900
Message-ID: <000c01c513ea$215ac900$3201a8c0@pc10>
> >  (2) Ruby/Tk だけの問題であれば,ext/tk, ext/tcltklib 以下を
> >      12/25 版のものと置き換えて試す.
> やってみましたがダメでした。
> 逆に 12/25版の ruby に、2/10版の上記を置き換えたのはOKでした。

報告をありがとうございます.確認しました.

原因は 2/8 に commit された st.c の st_foreach の変更に
tkutil.c の一部が追随できていなかったためでした.

この修正に加え,SJIS 文字列の配列を Tcl/Tk のリスト文字列に
自動変換させた場合に一部の SJIS 文字を含んでいると適切に
変換されない (特殊文字を含んだリスト要素として { } で囲まれてしまう)
という問題の修正も含めて commit しておきました.

# ちょっとした問題 (バグとは言えないレベルも含みます) や希望も
# 気軽に報告して頂けると本当に助かります.
# 隅々までもチェックしきれている訳ではないので,
# 報告さえあれば簡単に直せるバグがそのままになっているケースも
# ありますので.

差分は以下の通りです.お試しください.

Index: tkutil.c
===================================================================
RCS file: /var/cvs/src/ruby/ext/tk/Attic/tkutil.c,v
retrieving revision 1.4.2.15
diff -u -r1.4.2.15 tkutil.c
--- tkutil.c	25 Jan 2005 05:08:23 -0000	1.4.2.15
+++ tkutil.c	16 Feb 2005 07:59:53 -0000
@@ -8,7 +8,7 @@
 
 ************************************************/
 
-#define TKUTIL_RELEASE_DATE "2005-01-25"
+#define TKUTIL_RELEASE_DATE "2005-02-16"
 
 #include "ruby.h"
 #include "rubysig.h"
@@ -199,24 +199,12 @@
     return tk_fromUTF8(1, argv, self);
 }
 
-
-static void
-hash_check(err)
-    int err;
-{
-    if (err) {
-        rb_raise(rb_eRuntimeError, "hash modified");
-    }
-}
-
 static int
-to_strkey(key, value, hash, err)
+to_strkey(key, value, hash)
     VALUE key;
     VALUE value;
     VALUE hash;
-    int err;
 {
-    hash_check(err);
     if (key == Qundef) return ST_CONTINUE;
     rb_hash_aset(hash, rb_funcall(key, ID_to_s, 0, 0), value);
     return ST_CHECK;
@@ -231,19 +219,23 @@
 
     if NIL_P(keys) return new_keys;
     keys = rb_convert_type(keys, T_HASH, "Hash", "to_hash");
-    st_foreach(RHASH(keys)->tbl, to_strkey, new_keys);
+    if (st_foreach(RHASH(keys)->tbl, to_strkey, new_keys)) {
+	rb_raise(rb_eRuntimeError, "hash modified during iteration");
+    }
     return new_keys;
 }
 
 static VALUE get_eval_string_core _((VALUE, VALUE, VALUE));
-static VALUE ary2list _((VALUE, VALUE));
-static VALUE ary2list2 _((VALUE, VALUE));
+static VALUE ary2list _((VALUE, VALUE, VALUE));
+static VALUE ary2list2 _((VALUE, VALUE, VALUE));
 static VALUE hash2list _((VALUE, VALUE));
+static VALUE hash2list_enc _((VALUE, VALUE));
 static VALUE hash2kv _((VALUE, VALUE, VALUE));
 
 static VALUE
-ary2list(ary, self)
+ary2list(ary, enc_flag, self)
     VALUE ary;
+    VALUE enc_flag;
     VALUE self;
 {
     int idx, idx2, size, size2;
@@ -266,29 +258,36 @@
         val = RARRAY(ary)->ptr[idx];
         switch(TYPE(val)) {
         case T_ARRAY:
-            RARRAY(dst)->ptr[RARRAY(dst)->len++] = ary2list(val, self);
+            RARRAY(dst)->ptr[RARRAY(dst)->len++] 
+              = ary2list(val, enc_flag, self);
             break;
 
         case T_HASH:
             /* RARRAY(dst)->ptr[RARRAY(dst)->len++] = hash2list(val, self); */
-            val = hash2kv(val, Qnil, self);
+            val = hash2kv(val, enc_flag, self);
             size2 = RARRAY(val)->len;
             for(idx2 = 0; idx2 < size2; idx2++) {
                 val2 = RARRAY(val)->ptr[idx2];
                 switch(TYPE(val2)) {
                 case T_ARRAY:
                     RARRAY(dst)->ptr[RARRAY(dst)->len++] 
-                        = ary2list(val2, self);
+                        = ary2list(val2, enc_flag, self);
                     break;
 
                 case T_HASH:
-                    RARRAY(dst)->ptr[RARRAY(dst)->len++] 
-                        = hash2list(val2, self);
+                    if (RTEST(enc_flag)) {
+                        RARRAY(dst)->ptr[RARRAY(dst)->len++] 
+                            = hash2list_enc(val2, self);
+                    } else {
+                        RARRAY(dst)->ptr[RARRAY(dst)->len++] 
+                            = hash2list(val2, self);
+                    }
+                    break;
 
                 default:
                     if (val2 != TK_None) {
                         RARRAY(dst)->ptr[RARRAY(dst)->len++] 
-                            = get_eval_string_core(val2, Qnil, self);
+                            = get_eval_string_core(val2, enc_flag, self);
                     }
                 }
             }
@@ -297,7 +296,7 @@
         default:
             if (val != TK_None) {
                 RARRAY(dst)->ptr[RARRAY(dst)->len++] 
-                    = get_eval_string_core(val, Qnil, self);
+                    = get_eval_string_core(val, enc_flag, self);
             }
         }
     }
@@ -305,8 +304,9 @@
 }
 
 static VALUE
-ary2list2(ary, self)
+ary2list2(ary, enc_flag, self)
     VALUE ary;
+    VALUE enc_flag;
     VALUE self;
 {
     int idx, size;
@@ -320,17 +320,23 @@
         val = RARRAY(ary)->ptr[idx];
         switch(TYPE(val)) {
         case T_ARRAY:
-            RARRAY(dst)->ptr[RARRAY(dst)->len++] = ary2list(val, self);
+            RARRAY(dst)->ptr[RARRAY(dst)->len++] 
+              = ary2list(val, enc_flag, self);
             break;
 
         case T_HASH:
-            RARRAY(dst)->ptr[RARRAY(dst)->len++] = hash2list(val, self);
+            if (RTEST(enc_flag)) {
+                RARRAY(dst)->ptr[RARRAY(dst)->len++] = hash2list(val, self);
+            } else {
+                RARRAY(dst)->ptr[RARRAY(dst)->len++] 
+                    = hash2list_enc(val, self);
+            }
             break;
 
         default:
             if (val != TK_None) {
                 RARRAY(dst)->ptr[RARRAY(dst)->len++] 
-                    = get_eval_string_core(val, Qnil, self);
+                    = get_eval_string_core(val, enc_flag, self);
             }
         }
     }
@@ -449,15 +455,13 @@
 }
 
 static int
-push_kv(key, val, args, err)
+push_kv(key, val, args)
     VALUE key;
     VALUE val;
     VALUE args;
-    int err;
 {
     volatile VALUE ary;
 
-    hash_check(err);
     ary = RARRAY(args)->ptr[0];
 
     if (key == Qundef) return ST_CONTINUE;
@@ -489,7 +493,9 @@
     RARRAY(args)->ptr[0] = dst;
     RARRAY(args)->ptr[1] = self;
     RARRAY(args)->len = 2;
-    st_foreach(RHASH(hash)->tbl, push_kv, args);
+    if (st_foreach(RHASH(hash)->tbl, push_kv, args)) {
+	rb_raise(rb_eRuntimeError, "hash modified during iteration");
+    }
 
     if (NIL_P(ary)) {
         return dst;
@@ -499,15 +505,13 @@
 }
 
 static int
-push_kv_enc(key, val, args, err)
+push_kv_enc(key, val, args)
     VALUE key;
     VALUE val;
     VALUE args;
-    int err;
 {
     volatile VALUE ary;
 
-    hash_check(err);
     ary = RARRAY(args)->ptr[0];
 
     if (key == Qundef) return ST_CONTINUE;
@@ -542,7 +546,9 @@
     RARRAY(args)->ptr[0] = dst;
     RARRAY(args)->ptr[1] = self;
     RARRAY(args)->len = 2;
-    st_foreach(RHASH(hash)->tbl, push_kv_enc, args);
+    if (st_foreach(RHASH(hash)->tbl, push_kv_enc, args)) {
+	rb_raise(rb_eRuntimeError, "hash modified during iteration");
+    }
 
     if (NIL_P(ary)) {
         return dst;
@@ -556,7 +562,7 @@
     VALUE hash;
     VALUE self;
 {
-    return ary2list2(hash2kv(hash, Qnil, self), self);
+    return ary2list2(hash2kv(hash, Qnil, self), Qfalse, self);
 }
 
 
@@ -565,7 +571,7 @@
     VALUE hash;
     VALUE self;
 {
-    return ary2list2(hash2kv_enc(hash, Qnil, self), self);
+    return ary2list2(hash2kv_enc(hash, Qnil, self), Qfalse, self);
 }
 
 static VALUE
@@ -669,11 +675,7 @@
         }
 
     case T_ARRAY:
-        if (RTEST(enc_flag)) {
-            return fromDefaultEnc_toUTF8(ary2list(obj, self), self);
-        } else {
-            return ary2list(obj, self);
-        }
+        return ary2list(obj, enc_flag, self);
 
     case T_FALSE:
         return rb_str_new2("0");

-- 
                                       永井 秀利 (九工大 知能情報)
                                           nagai / ai.kyutech.ac.jp