summaryrefslogtreecommitdiff
path: root/eval.c
diff options
context:
space:
mode:
authormatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2005-03-07 02:05:08 +0000
committermatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2005-03-07 02:05:08 +0000
commit6645b928266cf7f8139f58b6b260e82f291d8446 (patch)
tree79b669fd89b447f950a4faced7ceebcba65b8f8e /eval.c
parent57b3ed4cda8882429590f761f9d545eee88823a3 (diff)
* 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.c84
1 files changed, 59 insertions, 25 deletions
diff --git a/eval.c b/eval.c
index df2487febb..92925b1dd5 100644
--- a/eval.c
+++ b/eval.c
@@ -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;
}
}