I recommend you to use ruby-1.7.x.st.c.3.diff with -DUSE_ST_FOREACH_MACRO. Index: class.c =================================================================== RCS file: /src/ruby/class.c,v retrieving revision 1.51 diff -u -u -r1.51 class.c --- class.c 7 Nov 2002 19:18:10 -0000 1.51 +++ class.c 3 Dec 2002 20:53:41 -0000 @@ -77,7 +77,7 @@ } if (RCLASS(module)->m_tbl) { RCLASS(clone)->m_tbl = st_init_numtable(); - st_foreach(RCLASS(module)->m_tbl, clone_method, RCLASS(clone)->m_tbl); + st_foreach_cont(RCLASS(module)->m_tbl, clone_method, RCLASS(clone)->m_tbl); } return (VALUE)clone; @@ -566,7 +566,7 @@ ary = rb_ary_new(); for (klass = mod; klass; klass = RCLASS(klass)->super) { - st_foreach(RCLASS(klass)->m_tbl, func, ary); + st_foreach_cont(RCLASS(klass)->m_tbl, func, ary); if (!option) break; } p = q = RARRAY(ary)->ptr; pend = p + RARRAY(ary)->len; @@ -644,12 +644,12 @@ ary = rb_ary_new(); klass = CLASS_OF(obj); while (klass && FL_TEST(klass, FL_SINGLETON)) { - st_foreach(RCLASS(klass)->m_tbl, ins_methods_i, ary); + st_foreach_cont_with_label(RCLASS(klass)->m_tbl, ins_methods_i, ary, l1); klass = RCLASS(klass)->super; } if (RTEST(all)) { while (klass && TYPE(klass) == T_ICLASS) { - st_foreach(RCLASS(klass)->m_tbl, ins_methods_i, ary); + st_foreach_cont_with_label(RCLASS(klass)->m_tbl, ins_methods_i, ary, l2); klass = RCLASS(klass)->super; } } Index: dln.c =================================================================== RCS file: /src/ruby/dln.c,v retrieving revision 1.45 diff -u -u -r1.45 dln.c --- dln.c 2 Dec 2002 07:57:15 -0000 1.45 +++ dln.c 3 Dec 2002 20:53:41 -0000 @@ -476,7 +476,7 @@ dln_print_undef() { fprintf(stderr, " Undefined symbols:\n"); - st_foreach(undef_tbl, undef_print, NULL); + st_foreach_cont(undef_tbl, undef_print, NULL); } static void Index: gc.c =================================================================== RCS file: /src/ruby/gc.c,v retrieving revision 1.112 diff -u -u -r1.112 gc.c --- gc.c 29 Oct 2002 21:35:27 -0000 1.112 +++ gc.c 3 Dec 2002 20:53:42 -0000 @@ -561,7 +561,7 @@ st_table *tbl; { if (!tbl) return; - st_foreach(tbl, mark_entry, 0); + st_foreach_cont(tbl, mark_entry, 0); } static int Index: hash.c =================================================================== RCS file: /src/ruby/hash.c,v retrieving revision 1.82 diff -u -u -r1.82 hash.c --- hash.c 2 Dec 2002 07:57:16 -0000 1.82 +++ hash.c 3 Dec 2002 20:53:42 -0000 @@ -149,6 +149,15 @@ } static VALUE +rb_hash_foreach_cont_call(arg) + struct rb_hash_foreach_arg *arg; +{ + st_foreach_cont(RHASH(arg->hash)->tbl, rb_hash_foreach_iter, arg); + return Qnil; +} + + +static VALUE rb_hash_foreach_ensure(hash) VALUE hash; { @@ -178,6 +187,22 @@ return rb_ensure(rb_hash_foreach_call, (VALUE)&arg, rb_hash_foreach_ensure, hash); } +static int +rb_hash_foreach_cont(hash, func, farg) + VALUE hash; + enum st_retval (*func)(); + char *farg; +{ + struct rb_hash_foreach_arg arg; + + RHASH(hash)->iter_lev++; + arg.hash = hash; + arg.func = func; + arg.arg = farg; + return rb_ensure(rb_hash_foreach_cont_call, (VALUE)&arg, rb_hash_foreach_ensure, hash); +} + + static VALUE rb_hash_s_alloc(klass) VALUE klass; @@ -275,7 +300,7 @@ rb_hash_modify(hash); tbl = st_init_table_with_size(&objhash, RHASH(hash)->tbl->num_entries); - st_foreach(RHASH(hash)->tbl, rb_hash_rehash_i, tbl); + st_foreach_cont(RHASH(hash)->tbl, rb_hash_rehash_i, tbl); st_free_table(RHASH(hash)->tbl); RHASH(hash)->tbl = tbl; @@ -582,7 +607,7 @@ hash2 = to_hash(hash2); if (hash == hash2) return hash; rb_hash_clear(hash); - st_foreach(RHASH(hash2)->tbl, replace_i, hash); + st_foreach_cont(RHASH(hash2)->tbl, replace_i, hash); RHASH(hash)->ifnone = RHASH(hash2)->ifnone; if (FL_TEST(hash2, HASH_PROC_DEFAULT)) { FL_SET(hash, HASH_PROC_DEFAULT); @@ -623,7 +648,7 @@ rb_hash_each_value(hash) VALUE hash; { - rb_hash_foreach(hash, each_value_i, 0); + rb_hash_foreach_cont(hash, each_value_i, 0); return hash; } @@ -640,7 +665,7 @@ rb_hash_each_key(hash) VALUE hash; { - rb_hash_foreach(hash, each_key_i, 0); + rb_hash_foreach_cont(hash, each_key_i, 0); return hash; } @@ -657,7 +682,7 @@ rb_hash_each_pair(hash) VALUE hash; { - rb_hash_foreach(hash, each_pair_i, 0); + rb_hash_foreach_cont(hash, each_pair_i, 0); return hash; } @@ -677,7 +702,7 @@ VALUE ary; ary = rb_ary_new(); - st_foreach(RHASH(hash)->tbl, to_a_i, ary); + st_foreach_cont(RHASH(hash)->tbl, to_a_i, ary); if (OBJ_TAINTED(hash)) OBJ_TAINT(ary); return ary; @@ -720,7 +745,7 @@ VALUE str; str = rb_str_buf_new2("{"); - st_foreach(RHASH(hash)->tbl, inspect_i, str); + st_foreach_cont(RHASH(hash)->tbl, inspect_i, str); rb_str_buf_cat2(str, "}"); OBJ_INFECT(str, hash); @@ -775,7 +800,7 @@ VALUE ary; ary = rb_ary_new(); - st_foreach(RHASH(hash)->tbl, keys_i, ary); + st_foreach_cont(RHASH(hash)->tbl, keys_i, ary); return ary; } @@ -796,7 +821,7 @@ VALUE ary; ary = rb_ary_new(); - st_foreach(RHASH(hash)->tbl, values_i, ary); + st_foreach_cont(RHASH(hash)->tbl, values_i, ary); return ary; } @@ -898,7 +923,7 @@ { VALUE h = rb_hash_new(); - st_foreach(RHASH(hash)->tbl, rb_hash_invert_i, h); + st_foreach_cont(RHASH(hash)->tbl, rb_hash_invert_i, h); return h; } @@ -931,10 +956,10 @@ { hash2 = to_hash(hash2); if (rb_block_given_p()) { - st_foreach(RHASH(hash2)->tbl, rb_hash_update_block_i, hash1); + st_foreach_cont_with_label(RHASH(hash2)->tbl, rb_hash_update_block_i, hash1, l1); } else { - st_foreach(RHASH(hash2)->tbl, rb_hash_update_i, hash1); + st_foreach_cont_with_label(RHASH(hash2)->tbl, rb_hash_update_i, hash1, l2); } return hash1; } Index: object.c =================================================================== RCS file: /src/ruby/object.c,v retrieving revision 1.94 diff -u -u -r1.94 object.c --- object.c 3 Nov 2002 11:04:17 -0000 1.94 +++ object.c 3 Dec 2002 20:53:43 -0000 @@ -240,7 +240,7 @@ inspect_obj(obj, str) VALUE obj, str; { - st_foreach(ROBJECT(obj)->iv_tbl, inspect_i, str); + st_foreach_cont(ROBJECT(obj)->iv_tbl, inspect_i, str); rb_str_cat2(str, ">"); RSTRING(str)->ptr[0] = '#'; OBJ_INFECT(str, obj); Index: st.c =================================================================== RCS file: /src/ruby/st.c,v retrieving revision 1.23 diff -u -u -r1.23 st.c --- st.c 2 Dec 2002 07:57:16 -0000 1.23 +++ st.c 3 Dec 2002 20:53:43 -0000 @@ -11,15 +11,6 @@ #include #endif -typedef struct st_table_entry st_table_entry; - -struct st_table_entry { - unsigned int hash; - char *key; - char *record; - st_table_entry *next; -}; - #define ST_DEFAULT_MAX_DENSITY 5 #define ST_DEFAULT_INIT_TABLE_SIZE 11 @@ -478,6 +469,7 @@ table->num_entries = num_entries; } +#ifndef USE_ST_FOREACH_MACRO void st_foreach(table, func, arg) st_table *table; @@ -486,7 +478,7 @@ { st_table_entry *ptr, *last, *tmp; enum st_retval retval; - int i; + int i, num_bins; for(i = 0; i < table->num_bins; i++) { last = 0; @@ -514,6 +506,7 @@ } } } +#endif static int strhash(string) Index: st.h =================================================================== RCS file: /src/ruby/st.h,v retrieving revision 1.3 diff -u -u -r1.3 st.h --- st.h 5 Jan 2000 04:37:12 -0000 1.3 +++ st.h 3 Dec 2002 20:53:43 -0000 @@ -13,6 +13,15 @@ int (*hash)(); }; +typedef struct st_table_entry st_table_entry; + +struct st_table_entry { + unsigned int hash; + char *key; + char *record; + st_table_entry *next; +}; + struct st_table { struct st_hash_type *type; int num_bins; @@ -24,6 +33,55 @@ enum st_retval {ST_CONTINUE, ST_STOP, ST_DELETE}; +#define st_foreach_cont(table, func, arg) { \ + st_table_entry *ptr; \ + int i; \ + for( i=0; i < table->num_bins; i++ ){ \ + for(ptr = table->bins[i]; ptr != 0; ptr = ptr->next ) { \ + func(ptr->key, ptr->record, arg); \ + } \ + } \ +} +#define st_foreach_cont_with_label(t,f,a,l) st_foreach_cont(t,f,a) + +#define USE_ST_FOREACH_MACRO + +#ifdef USE_ST_FOREACH_MACRO +#define st_foreach_with_label(table, func, arg, label) { \ + st_table_entry *ptr, *last, *tmp; \ + enum st_retval retval; \ + int i, num_bins; \ + for( i = 0; i < table->num_bins; i++ ) { \ + last = 0; \ + for( ptr = table->bins[i]; ptr != 0; ) { \ + retval = func(ptr->key, ptr->record, arg); \ + switch (retval) { \ + case ST_CONTINUE: \ + last = ptr; \ + ptr = ptr->next; \ + break; \ + case ST_STOP: \ + goto label; \ + case ST_DELETE: \ + tmp = ptr; \ + if (last == 0) { \ + table->bins[i] = ptr->next; \ + } \ + else { \ + last->next = ptr->next; \ + } \ + ptr = ptr->next; \ + free(tmp); \ + table->num_entries--; \ + } \ + } \ + } \ +label: ; \ +} + +#define st_foreach(t,f,a) st_foreach_with_label(t,f,a,st_foreach_done) +#endif + st_table *st_init_table(); st_table *st_init_table_with_size(); st_table *st_init_numtable(); @@ -32,7 +90,10 @@ st_table *st_init_strtable_with_size(); int st_delete(), st_delete_safe(); int st_insert(), st_lookup(); -void st_foreach(), st_add_direct(), st_free_table(), st_cleanup_safe(); +void st_add_direct(), st_free_table(), st_cleanup_safe(); +#ifndef USE_ST_FOREACH_MACRO +void st_foreach(); +#endif st_table *st_copy(); #define ST_NUMCMP ((int (*)()) 0) Index: variable.c =================================================================== RCS file: /src/ruby/variable.c,v retrieving revision 1.73 diff -u -u -r1.73 variable.c --- variable.c 23 Oct 2002 08:20:35 -0000 1.73 +++ variable.c 3 Dec 2002 20:53:43 -0000 @@ -121,10 +121,10 @@ arg.track = rb_cObject; arg.prev = 0; if (RCLASS(rb_cObject)->iv_tbl) { - st_foreach(RCLASS(rb_cObject)->iv_tbl, fc_i, &arg); + st_foreach_with_label(RCLASS(rb_cObject)->iv_tbl, fc_i, &arg, l1); } if (arg.path == 0) { - st_foreach(rb_class_tbl, fc_i, &arg); + st_foreach_with_label(rb_class_tbl, fc_i, &arg, l2); } if (arg.path) { if (!ROBJECT(klass)->iv_tbl) { @@ -477,7 +477,7 @@ void rb_gc_mark_global_tbl() { - st_foreach(rb_global_tbl, mark_global_entry, 0); + st_foreach_cont(rb_global_tbl, mark_global_entry, 0); } static ID @@ -745,7 +745,7 @@ char buf[4]; char *s = "&`'+123456789"; - st_foreach(rb_global_tbl, gvar_i, ary); + st_foreach_cont(rb_global_tbl, gvar_i, ary); if (!NIL_P(rb_backref_get())) { while (*s) { sprintf(buf, "$%c", *s++); @@ -911,7 +911,7 @@ st_table *tbl; { if (rb_special_const_p(obj)) { - st_foreach(tbl, givar_mark_i, 0); + st_foreach_cont(tbl, givar_mark_i, 0); } return ST_CONTINUE; } @@ -921,7 +921,7 @@ { if (!generic_iv_tbl) return; if (special_generic_ivar == 0) return; - st_foreach(generic_iv_tbl, givar_i, 0); + st_foreach_cont(generic_iv_tbl, givar_i, 0); } void @@ -1045,7 +1045,7 @@ case T_CLASS: case T_MODULE: if (ROBJECT(obj)->iv_tbl) { - st_foreach(ROBJECT(obj)->iv_tbl, ivar_i, ary); + st_foreach_cont_with_label(ROBJECT(obj)->iv_tbl, ivar_i, ary, l1); } break; default: @@ -1054,7 +1054,7 @@ st_table *tbl; if (st_lookup(generic_iv_tbl, obj, &tbl)) { - st_foreach(tbl, ivar_i, ary); + st_foreach_cont_with_label(tbl, ivar_i, ary, l2); } } break; @@ -1247,12 +1247,12 @@ tbl = st_init_numtable(); } if (RCLASS(mod)->iv_tbl) { - st_foreach(RCLASS(mod)->iv_tbl, sv_i, tbl); + st_foreach_cont_with_label(RCLASS(mod)->iv_tbl, sv_i, tbl, l1); } if ((VALUE)mod == rb_cObject) { - st_foreach(rb_class_tbl, sv_i, tbl); + st_foreach_cont(rb_class_tbl, sv_i, tbl); if (autoload_tbl) { - st_foreach(autoload_tbl, autoload_i, tbl); + st_foreach_cont_with_label(autoload_tbl, autoload_i, tbl, l2); } } return tbl; @@ -1289,7 +1289,7 @@ if (!tbl) return rb_ary_new2(0); ary = rb_ary_new2(tbl->num_entries); - st_foreach(tbl, list_i, ary); + st_foreach_cont(tbl, list_i, ary); st_free_table(tbl); return ary; @@ -1609,7 +1609,7 @@ for (;;) { if (RCLASS(obj)->iv_tbl) { - st_foreach(RCLASS(obj)->iv_tbl, cv_i, ary); + st_foreach_cont(RCLASS(obj)->iv_tbl, cv_i, ary); } obj = RCLASS(obj)->super; if (!obj) break;