diff options
author | matz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2005-03-07 02:05:08 +0000 |
---|---|---|
committer | matz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2005-03-07 02:05:08 +0000 |
commit | 6645b928266cf7f8139f58b6b260e82f291d8446 (patch) | |
tree | 79b669fd89b447f950a4faced7ceebcba65b8f8e /eval.c | |
parent | 57b3ed4cda8882429590f761f9d545eee88823a3 (diff) | |
download | ruby-6645b928266cf7f8139f58b6b260e82f291d8446.tar.gz |
* object.c (inspect_obj): unintended space removal.
[ruby-dev:25810]
* eval.c (rb_exec_recursive): should not use NODE in disclosed
context. [ruby-dev:25812]
* io.c (rb_f_open): need not to check if to_open value is a
T_FILE. [ruby-dev:25812]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@8098 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'eval.c')
-rw-r--r-- | eval.c | 84 |
1 files changed, 59 insertions, 25 deletions
@@ -12991,49 +12991,83 @@ rb_throw(tag, val) rb_f_throw(2, argv); } -VALUE -rb_exec_recursive(func, obj, arg) - VALUE (*func)(ANYARGS); /* VALUE obj, VALUE arg, int flag */ - VALUE obj, arg; +static VALUE +recursive_check(obj) + VALUE obj; { - VALUE list = rb_thread_local_aref(rb_thread_current(), recursive_key); - int found = Qfalse; + VALUE hash = rb_thread_local_aref(rb_thread_current(), recursive_key); + + if (NIL_P(hash) || TYPE(hash) != T_HASH) { + return Qfalse; + } + else { + VALUE list = rb_hash_aref(hash, ID2SYM(ruby_frame->this_func)); - if (NIL_P(list) || TYPE(list) != T_NODE) { + if (NIL_P(list)) return Qfalse; + return rb_ary_includes(list, rb_obj_id(obj)); + } +} + +static void +recursive_push(obj) + VALUE obj; +{ + VALUE hash = rb_thread_local_aref(rb_thread_current(), recursive_key); + VALUE list, sym; + + sym = ID2SYM(ruby_frame->this_func); + if (NIL_P(hash) || TYPE(hash) != T_HASH) { + hash = rb_hash_new(); + rb_thread_local_aset(rb_thread_current(), recursive_key, hash); list = Qnil; } else { - NODE *tmp = (NODE*)list; - - while (!NIL_P(tmp)) { - if (tmp->nd_cfnc == func && tmp->nd_tval == obj) { - found = Qtrue; - break; - } - tmp = tmp->nd_next; - } + list = rb_hash_aref(hash, sym); + } + if (NIL_P(list)) { + list = rb_ary_new(); + rb_hash_aset(hash, sym, list); + } + rb_ary_push(list, rb_obj_id(obj)); +} + +static void +recursive_pop() +{ + VALUE hash = rb_thread_local_aref(rb_thread_current(), recursive_key); + VALUE list, sym; + + sym = ID2SYM(ruby_frame->this_func); + if (NIL_P(hash) || TYPE(hash) != T_HASH) { + rb_bug("invalid inspect_tbl hash"); + } + list = rb_hash_aref(hash, sym); + if (NIL_P(list) || TYPE(list) != T_ARRAY) { + rb_bug("invalid inspect_tbl list"); } - if (found) { + rb_ary_pop(list); +} + +VALUE +rb_exec_recursive(func, obj, arg) + VALUE (*func)(ANYARGS); /* VALUE obj, VALUE arg, int flag */ + VALUE obj, arg; +{ + if (recursive_check(obj)) { return (*func)(obj, arg, Qtrue); } else { - NODE *node = rb_node_newnode(NODE_MEMO, (VALUE)func, obj, list); + recursive_push(obj); VALUE result; int state; - rb_thread_local_aset(rb_thread_current(), recursive_key, (VALUE)node); PUSH_TAG(PROT_NONE); if ((state = EXEC_TAG()) == 0) { result = (*func)(obj, arg, Qfalse); } POP_TAG(); + recursive_pop(); if (state) JUMP_TAG(state); - - /* remove pushed tag */ - list = rb_thread_local_aref(rb_thread_current(), recursive_key); - node = (NODE*)list; - - rb_thread_local_aset(rb_thread_current(), recursive_key, (VALUE)node->nd_next); return result; } } |