shell bypass 403
diff -rux '*.o' ruby-1.8.7-p72/ChangeLog ruby-1.8.7-mbari/ChangeLog
--- ruby-1.8.7-p72/ChangeLog 2008-12-16 00:47:25.000000000 -0800
+++ ruby-1.8.7-mbari/ChangeLog 2008-12-16 23:06:21.000000000 -0800
@@ -1,3 +1,11 @@
+Tue Dec 15 9:15:36 2008 Brent Roman <brent@mbari.org>
+
+ * eval.c: factored rb_eval() into many separate non-inlined
+ functions to reduce the size of its stack frame when
+ compiled with gcc.
+ Factored callcc into 2 functions.
+
+
Tue Dec 13 6:10:36 2008 Brent Roman <brent@mbari.org>
* eval.c: update stack extent just before and after every setjmp
diff -rux '*.o' ruby-1.8.7-p72/eval.c ruby-1.8.7-mbari/eval.c
--- ruby-1.8.7-p72/eval.c 2008-12-16 00:47:25.000000000 -0800
+++ ruby-1.8.7-mbari/eval.c 2008-12-16 23:28:08.000000000 -0800
@@ -3,7 +3,7 @@
eval.c -
$Author: brent $
- $Date: 2008/12/14 07:23:06 $
+ $Date: 2008/12/17 07:28:08 $
created at: Thu Jun 10 14:22:17 JST 1993
Copyright (C) 1993-2003 Yukihiro Matsumoto
@@ -219,7 +219,7 @@
VALUE rb_cBinding;
static VALUE proc_invoke _((VALUE,VALUE,VALUE,VALUE));
static VALUE rb_f_binding _((VALUE));
-static void rb_f_END _((void));
+NOINLINE(static void rb_f_END _((void)));
static VALUE rb_f_block_given_p _((void));
static VALUE block_pass _((VALUE,NODE*));
@@ -1240,12 +1240,7 @@
if (NIL_P(ruby_errinfo)) return;
PUSH_TAG(PROT_NONE);
- if (EXEC_TAG() == 0) {
- errat = get_backtrace(ruby_errinfo);
- }
- else {
- errat = Qnil;
- }
+ errat = EXEC_TAG() == 0 ? get_backtrace(ruby_errinfo) : Qnil;
if (EXEC_TAG()) goto error;
if (NIL_P(errat)){
ruby_set_current_source();
@@ -1926,8 +1921,8 @@
return rb_const_defined(cref->nd_clss, id);
}
-static VALUE
-ev_const_get(cref, id, self)
+NOINLINE(static VALUE
+ev_const_get(cref, id, self))
NODE *cref;
ID id;
VALUE self;
@@ -2942,40 +2937,960 @@
}
}
-static VALUE
-rb_eval(self, n)
- VALUE self;
- NODE *n;
+
+/*
+ functions factored out of rb_eval() to reduce its stack frame size
+*/
+NOINLINE(static VALUE eval_match2(self, node))
+ VALUE self;
+ NODE *node;
+{
+ VALUE l = rb_eval(self,node->nd_recv);
+ VALUE r = rb_eval(self,node->nd_value);
+ return rb_reg_match(l, r);
+}
+
+NOINLINE(static VALUE
+eval_match3(self, node))
+ VALUE self;
+ NODE *node;
+{
+ VALUE r = rb_eval(self,node->nd_recv);
+ VALUE l = rb_eval(self,node->nd_value);
+ return TYPE(l) == T_STRING ? rb_reg_match(r, l) : rb_funcall(l, match, 1, r);
+}
+
+
+NOINLINE(static void
+eval_opt_n(self, node))
+ VALUE self;
+ NODE *node;
+{
+ int state;
+ PUSH_TAG(PROT_LOOP);
+ switch (state = EXEC_TAG()) {
+ case 0:
+ opt_n_next:
+ while (!NIL_P(rb_gets())) {
+ opt_n_redo:
+ rb_eval(self, node->nd_body);
+ }
+ break;
+
+ case TAG_REDO:
+ state = 0;
+ goto opt_n_redo;
+ case TAG_NEXT:
+ state = 0;
+ goto opt_n_next;
+ case TAG_BREAK:
+ state = 0;
+ default:
+ break;
+ }
+ POP_TAG();
+ if (state) JUMP_TAG(state);
+}
+
+
+NOINLINE(static NODE *
+eval_when(self, node))
+ VALUE self;
+ NODE *node;
+{
+ do {
+ NODE *tag = node->nd_head;
+ while (tag) {
+ EXEC_EVENT_HOOK(RUBY_EVENT_LINE, tag, self,
+ ruby_frame->last_func,
+ ruby_frame->last_class);
+ if (tag->nd_head && nd_type(tag->nd_head) == NODE_WHEN) {
+ VALUE v = rb_eval(self, tag->nd_head->nd_head);
+ long i;
+
+ if (TYPE(v) != T_ARRAY) v = rb_ary_to_ary(v);
+ for (i=0; i<RARRAY(v)->len; i++) {
+ if (RTEST(RARRAY(v)->ptr[i])) return node->nd_body;
+ }
+ tag = tag->nd_next;
+ continue;
+ }
+ if (RTEST(rb_eval(self, tag->nd_head))) return node->nd_body;
+ tag = tag->nd_next;
+ }
+ } while ((node = node->nd_next) && nd_type(node) == NODE_WHEN);
+ return node;
+}
+
+
+NOINLINE (static NODE *
+eval_case(self, node))
+ VALUE self;
+ NODE *node;
+{
+ VALUE val = rb_eval(self, node->nd_head);
+ node = node->nd_body;
+ while (node) {
+ NODE *tag;
+
+ if (nd_type(node) != NODE_WHEN) break;
+ tag = node->nd_head;
+ while (tag) {
+ EXEC_EVENT_HOOK(RUBY_EVENT_LINE, tag, self,
+ ruby_frame->last_func,
+ ruby_frame->last_class);
+ if (tag->nd_head && nd_type(tag->nd_head) == NODE_WHEN) {
+ VALUE v = rb_eval(self, tag->nd_head->nd_head);
+ long i;
+
+ if (TYPE(v) != T_ARRAY) v = rb_ary_to_ary(v);
+ for (i=0; i<RARRAY(v)->len; i++) {
+ if (RTEST(rb_funcall2(RARRAY(v)->ptr[i], eqq, 1, &val)))
+ return node->nd_body;
+ }
+ tag = tag->nd_next;
+ continue;
+ }
+ if (RTEST(rb_funcall2(rb_eval(self, tag->nd_head), eqq, 1, &val)))
+ return node->nd_body;
+ tag = tag->nd_next;
+ }
+ node = node->nd_next;
+ }
+ return node;
+}
+
+
+NOINLINE (static VALUE
+eval_while(self, node))
+ VALUE self;
+ NODE *node;
+{
+ int state;
+ volatile VALUE result = Qnil;
+ PUSH_TAG(PROT_LOOP);
+ switch (state = EXEC_TAG()) {
+ case 0:
+ if (node->nd_state && !RTEST(rb_eval(self, node->nd_cond)))
+ goto while_out;
+ do {
+ while_redo:
+ rb_eval(self, node->nd_body);
+ while_next:
+ ;
+ } while (RTEST(rb_eval(self, node->nd_cond)));
+ break;
+
+ case TAG_REDO:
+ state = 0;
+ goto while_redo;
+ case TAG_NEXT:
+ state = 0;
+ goto while_next;
+ case TAG_BREAK:
+ if (TAG_DST()) {
+ state = 0;
+ result = prot_tag->retval;
+ }
+ /* fall through */
+ default:
+ break;
+ }
+while_out:
+ POP_TAG();
+ if (state) JUMP_TAG(state);
+ return result;
+}
+
+
+NOINLINE (static VALUE
+eval_until(self, node))
+ VALUE self;
+ NODE *node;
+{
+ int state;
+ volatile VALUE result = Qnil;
+ PUSH_TAG(PROT_LOOP);
+ switch (state = EXEC_TAG()) {
+ case 0:
+ if (node->nd_state && RTEST(rb_eval(self, node->nd_cond)))
+ goto until_out;
+ do {
+ until_redo:
+ rb_eval(self, node->nd_body);
+ until_next:
+ ;
+ } while (!RTEST(rb_eval(self, node->nd_cond)));
+ break;
+
+ case TAG_REDO:
+ state = 0;
+ goto until_redo;
+ case TAG_NEXT:
+ state = 0;
+ goto until_next;
+ case TAG_BREAK:
+ if (TAG_DST()) {
+ state = 0;
+ result = prot_tag->retval;
+ }
+ /* fall through */
+ default:
+ break;
+ }
+ until_out:
+ POP_TAG();
+ if (state) JUMP_TAG(state);
+ return result;
+}
+
+
+NOINLINE (static VALUE
+eval_iter(self, node))
+ VALUE self;
+ NODE *node;
+{
+ int state;
+ volatile VALUE result = Qnil;
+
+ PUSH_TAG(PROT_LOOP);
+ PUSH_BLOCK(node->nd_var, node->nd_body);
+
+ state = EXEC_TAG();
+ switch (state) {
+ case TAG_RETRY:
+ state = 0; /* fall thru to case 0 */
+ case 0:
+ PUSH_ITER(ITER_PRE);
+ if (nd_type(node) == NODE_ITER) {
+ result = rb_eval(self, node->nd_iter);
+ }
+ else {
+ VALUE recv;
+
+ _block.flags &= ~BLOCK_D_SCOPE;
+ BEGIN_CALLARGS;
+ recv = rb_eval(self, node->nd_iter);
+ END_CALLARGS;
+ ruby_current_node = node;
+ SET_CURRENT_SOURCE();
+ result = rb_call(CLASS_OF(recv),recv,each,0,0,0,self);
+ }
+ POP_ITER();
+ break;
+
+ case TAG_BREAK:
+ if (TAG_DST()) {
+ result = prot_tag->retval;
+ state = 0;
+ }
+ }
+ POP_BLOCK();
+ POP_TAG();
+ if (state) JUMP_TAG(state);
+ return result;
+}
+
+
+NOINLINE (static VALUE
+eval_rescue(self, node))
+ VALUE self;
+ NODE *node;
{
- NODE * volatile contnode = 0;
- NODE * volatile node = n;
+ volatile VALUE e_info = ruby_errinfo;
+ volatile int rescuing = 0;
int state;
volatile VALUE result = Qnil;
- st_data_t data;
-#define RETURN(v) do { \
- result = (v); \
- goto finish; \
-} while (0)
+ PUSH_TAG(PROT_NONE);
+ if ((state = EXEC_TAG()) == 0) {
+ retry_entry:
+ result = rb_eval(self, node->nd_head);
+ }
+ else if (rescuing) {
+ if (rescuing < 0) {
+ /* in rescue argument, just reraise */
+ }
+ else if (state == TAG_RETRY) {
+ rescuing = state = 0;
+ ruby_errinfo = e_info;
+ goto retry_entry;
+ }
+ else if (state != TAG_RAISE) {
+ result = prot_tag->retval;
+ }
+ }
+ else if (state == TAG_RAISE) {
+ NODE *resq = node->nd_resq;
- again:
- if (!node) RETURN(Qnil);
+ rescuing = -1;
+ while (resq) {
+ ruby_current_node = resq;
+ if (handle_rescue(self, resq)) {
+ state = 0;
+ rescuing = 1;
+ result = rb_eval(self, resq->nd_body);
+ break;
+ }
+ resq = resq->nd_head; /* next rescue */
+ }
+ }
+ else {
+ result = prot_tag->retval;
+ }
+ POP_TAG();
+ if (state != TAG_RAISE) ruby_errinfo = e_info;
+ if (state) {
+ JUMP_TAG(state);
+ }
+ /* no exception raised */
+ if (!rescuing && node->nd_else) { /* else clause given */
+ result = Qundef; /* caller must eval this! */
+ }
+ return result;
+}
+
+NOINLINE (static VALUE
+eval_ensure(self, node))
+ VALUE self;
+ NODE *node;
+{
+ int state;
+ volatile VALUE result = Qnil;
+
+ PUSH_TAG(PROT_NONE);
+ if ((state = EXEC_TAG()) == 0) {
+ result = rb_eval(self, node->nd_head);
+ }
+ POP_TAG();
+ if (node->nd_ensr && !thread_no_ensure()) {
+ VALUE retval = prot_tag->retval; /* save retval */
+ VALUE errinfo = ruby_errinfo;
+
+ rb_eval(self, node->nd_ensr);
+ return_value(retval);
+ ruby_errinfo = errinfo;
+ }
+ if (state) JUMP_TAG(state);
+ return result;
+}
+
+
+NOINLINE (static VALUE
+eval_dot(self, node))
+ VALUE self;
+ NODE *node;
+{
+ VALUE beg = rb_eval(self, node->nd_beg);
+ VALUE end = rb_eval(self, node->nd_end);
+ return rb_range_new(beg, end, nd_type(node) == NODE_DOT3);
+}
+
+
+NOINLINE (static VALUE
+eval_flip2(self, node))
+ VALUE self;
+ NODE *node;
+{
+ VALUE *flip = rb_svar(node->nd_cnt);
+ if (!flip) rb_bug("unexpected local variable");
+ if (!RTEST(*flip)) {
+ if (!RTEST(rb_eval(self, node->nd_beg)))
+ return Qfalse;
+ *flip = RTEST(rb_eval(self, node->nd_end))?Qfalse:Qtrue;
+ }
+ else if (RTEST(rb_eval(self, node->nd_end)))
+ *flip = Qfalse;
+ return Qtrue;
+}
+
+
+NOINLINE (static VALUE
+eval_flip3(self, node))
+ VALUE self;
+ NODE *node;
+{
+ VALUE *flip = rb_svar(node->nd_cnt);
+ if (!flip) rb_bug("unexpected local variable");
+ if (!RTEST(*flip))
+ return *flip = (RTEST(rb_eval(self, node->nd_beg)) ? Qtrue : Qfalse);
+ if (RTEST(rb_eval(self, node->nd_end)))
+ *flip = Qfalse;
+ return Qtrue;
+}
+
+
+NOINLINE (static VALUE
+eval_attrasgn(self, node))
+ VALUE self;
+ NODE *node;
+{
+ VALUE recv;
+ int argc; VALUE *argv; /* used in SETUP_ARGS */
+ int scope;
+ TMP_PROTECT;
+
+ BEGIN_CALLARGS;
+ if (node->nd_recv == (NODE *)1) {
+ recv = self;
+ scope = 1;
+ }
+ else {
+ recv = rb_eval(self, node->nd_recv);
+ scope = 0;
+ }
+ SETUP_ARGS(node->nd_args);
+ END_CALLARGS;
+
+ ruby_current_node = node;
+ SET_CURRENT_SOURCE();
+ rb_call(CLASS_OF(recv),recv,node->nd_mid,argc,argv,scope,self);
+ return argv[argc-1];
+}
+
+
+NOINLINE (static VALUE
+eval_call(self, node))
+ VALUE self;
+ NODE *node;
+{
+ VALUE recv;
+ int argc; VALUE *argv; /* used in SETUP_ARGS */
+ TMP_PROTECT;
+
+ BEGIN_CALLARGS;
+ recv = rb_eval(self, node->nd_recv);
+ SETUP_ARGS(node->nd_args);
+ END_CALLARGS;
+
+ ruby_current_node = node;
+ SET_CURRENT_SOURCE();
+ return rb_call(CLASS_OF(recv),recv,node->nd_mid,argc,argv,0,self);
+}
+
+
+NOINLINE (static VALUE
+eval_fcall(self, node))
+ VALUE self;
+ NODE *node;
+{
+ int argc; VALUE *argv; /* used in SETUP_ARGS */
+ TMP_PROTECT;
+
+ BEGIN_CALLARGS;
+ SETUP_ARGS(node->nd_args);
+ END_CALLARGS;
+
+ ruby_current_node = node;
+ SET_CURRENT_SOURCE();
+ return rb_call(CLASS_OF(self),self,node->nd_mid,argc,argv,1,self);
+}
+
+NOINLINE (static VALUE
+eval_super(self, node))
+ VALUE self;
+ NODE *node;
+{
+ int argc; VALUE *argv; /* used in SETUP_ARGS */
+ TMP_PROTECT;
+
+ if (ruby_frame->last_class == 0) {
+ if (ruby_frame->last_func) {
+ rb_name_error(ruby_frame->last_func,
+ "superclass method `%s' disabled",
+ rb_id2name(ruby_frame->orig_func));
+ }
+ else {
+ rb_raise(rb_eNoMethodError, "super called outside of method");
+ }
+ }
+ if (nd_type(node) == NODE_ZSUPER) {
+ argc = ruby_frame->argc;
+ if (argc && DMETHOD_P()) {
+ if (TYPE(RBASIC(ruby_scope)->klass) != T_ARRAY ||
+ RARRAY(RBASIC(ruby_scope)->klass)->len != argc) {
+ rb_raise(rb_eRuntimeError,
+ "super: specify arguments explicitly");
+ }
+ argv = RARRAY(RBASIC(ruby_scope)->klass)->ptr;
+ }
+ else if (!ruby_scope->local_vars) {
+ argc = 0;
+ argv = 0;
+ }
+ else {
+ argv = ruby_scope->local_vars + 2;
+ }
+ }
+ else {
+ BEGIN_CALLARGS;
+ SETUP_ARGS(node->nd_args);
+ END_CALLARGS;
+ ruby_current_node = node;
+ }
+
+ SET_CURRENT_SOURCE();
+ return rb_call_super(argc, argv);
+}
+
+
+NOINLINE (static VALUE
+eval_scope(self, node))
+ VALUE self;
+ NODE *node;
+{
+ int state;
+ volatile VALUE result = Qnil;
+ struct FRAME frame;
+ NODE *saved_cref = 0;
+
+ frame = *ruby_frame;
+ frame.tmp = ruby_frame;
+ ruby_frame = &frame;
+
+ PUSH_SCOPE();
+ PUSH_TAG(PROT_NONE);
+ if (node->nd_rval) {
+ saved_cref = ruby_cref;
+ ruby_cref = (NODE*)node->nd_rval;
+ }
+ if (node->nd_tbl) {
+ VALUE *vars = ALLOCA_N(VALUE, node->nd_tbl[0]+1);
+ *vars++ = (VALUE)node;
+ ruby_scope->local_vars = vars;
+ rb_mem_clear(ruby_scope->local_vars, node->nd_tbl[0]);
+ ruby_scope->local_tbl = node->nd_tbl;
+ }
+ else {
+ ruby_scope->local_vars = 0;
+ ruby_scope->local_tbl = 0;
+ }
+ if ((state = EXEC_TAG()) == 0) {
+ result = rb_eval(self, node->nd_next);
+ }
+ POP_TAG();
+ POP_SCOPE();
+ ruby_frame = frame.tmp;
+ if (saved_cref)
+ ruby_cref = saved_cref;
+ if (state) JUMP_TAG(state);
+ return result;
+}
+
+NOINLINE (static VALUE
+eval_op_asgn1(self, node))
+ VALUE self;
+ NODE *node;
+{
+ int argc; VALUE *argv; /* used in SETUP_ARGS */
+ VALUE recv, val, tmp;
+ NODE *rval;
+ TMP_PROTECT;
+
+ recv = rb_eval(self, node->nd_recv);
+ rval = node->nd_args->nd_head;
+ SETUP_ARGS0(node->nd_args->nd_body, 1);
+ val = rb_funcall3(recv, aref, argc, argv);
+ switch (node->nd_mid) {
+ case 0: /* OR */
+ if (RTEST(val)) return val;
+ val = rb_eval(self, rval);
+ break;
+ case 1: /* AND */
+ if (!RTEST(val)) return val;
+ val = rb_eval(self, rval);
+ break;
+ default:
+ tmp = rb_eval(self, rval);
+ val = rb_funcall3(val, node->nd_mid, 1, &tmp);
+ }
+ argv[argc] = val;
+ rb_funcall2(recv, aset, argc+1, argv);
+ return val;
+}
+
+
+NOINLINE (static VALUE
+eval_op_asgn2(self, node))
+ VALUE self;
+ NODE *node;
+{
+ ID id = node->nd_next->nd_vid;
+ VALUE recv, val, tmp;
+
+ recv = rb_eval(self, node->nd_recv);
+ val = rb_funcall3(recv, id, 0, 0);
+ switch (node->nd_next->nd_mid) {
+ case 0: /* OR */
+ if (RTEST(val)) return val;
+ val = rb_eval(self, node->nd_value);
+ break;
+ case 1: /* AND */
+ if (!RTEST(val)) return val;
+ val = rb_eval(self, node->nd_value);
+ break;
+ default:
+ tmp = rb_eval(self, node->nd_value);
+ val = rb_funcall3(val, node->nd_next->nd_mid, 1, &tmp);
+ }
+
+ rb_funcall2(recv, node->nd_next->nd_aid, 1, &val);
+ return val;
+}
+
+
+NOINLINE (static VALUE
+eval_hash(self, node))
+ VALUE self;
+ NODE *node;
+{
+ NODE *list;
+ VALUE hash = rb_hash_new();
+ VALUE key, val;
+
+ list = node->nd_head;
+ while (list) {
+ key = rb_eval(self, list->nd_head);
+ list = list->nd_next;
+ if (list == 0)
+ rb_bug("odd number list for Hash");
+ val = rb_eval(self, list->nd_head);
+ list = list->nd_next;
+ rb_hash_aset(hash, key, val);
+ }
+ return hash;
+}
+
+
+NOINLINE (static VALUE
+eval_array(self, node))
+ VALUE self;
+ NODE *node;
+{
+ VALUE ary;
+ long i;
+
+ i = node->nd_alen;
+ ary = rb_ary_new2(i);
+ for (i=0;node;node=node->nd_next) {
+ RARRAY(ary)->ptr[i++] = rb_eval(self, node->nd_head);
+ RARRAY(ary)->len = i;
+ }
+ return ary;
+}
+
+
+NOINLINE (static VALUE
+eval_slit(self, node))
+ VALUE self;
+ NODE *node;
+{
+ VALUE str, str2;
+ NODE *list = node->nd_next;
+
+ str = rb_str_new3(node->nd_lit);
+ while (list) {
+ if (list->nd_head) {
+ switch (nd_type(list->nd_head)) {
+ case NODE_STR:
+ str2 = list->nd_head->nd_lit;
+ break;
+ default:
+ str2 = rb_eval(self, list->nd_head);
+ break;
+ }
+ rb_str_append(str, str2);
+ OBJ_INFECT(str, str2);
+ }
+ list = list->nd_next;
+ }
+ switch (nd_type(node)) {
+ case NODE_DREGX:
+ return rb_reg_new(RSTRING(str)->ptr, RSTRING(str)->len,
+ node->nd_cflag);
+ case NODE_DREGX_ONCE: /* regexp expand once */
+ str2 = rb_reg_new(RSTRING(str)->ptr, RSTRING(str)->len,
+ node->nd_cflag);
+ nd_set_type(node, NODE_LIT);
+ return node->nd_lit = str2;
+ case NODE_LIT:
+ /* other thread may replace NODE_DREGX_ONCE to NODE_LIT */
+ return Qundef;
+ case NODE_DXSTR:
+ return rb_funcall(self, '`', 1, str);
+ case NODE_DSYM:
+ return rb_str_intern(str);
+ }
+ return str;
+}
+
+
+NOINLINE (static void
+eval_defn(self, node))
+ VALUE self;
+ NODE *node;
+{
+ NODE *body, *defn;
+ VALUE origin = 0;
+ int noex;
+
+ if (NIL_P(ruby_class)) {
+ rb_raise(rb_eTypeError, "no class/module to add method");
+ }
+ if (ruby_class == rb_cObject && node->nd_mid == init) {
+ rb_warn("redefining Object#initialize may cause infinite loop");
+ }
+ if (node->nd_mid == __id__ || node->nd_mid == __send__) {
+ rb_warn("redefining `%s' may cause serious problem",
+ rb_id2name(node->nd_mid));
+ }
+ rb_frozen_class_p(ruby_class);
+ body = search_method(ruby_class, node->nd_mid, &origin);
+ if (body){
+ if (RTEST(ruby_verbose) && ruby_class == origin && body->nd_cnt == 0 && body->nd_body) {
+ rb_warning("method redefined; discarding old %s", rb_id2name(node->nd_mid));
+ }
+ }
+
+ if (SCOPE_TEST(SCOPE_PRIVATE) || node->nd_mid == init) {
+ noex = NOEX_PRIVATE;
+ }
+ else if (SCOPE_TEST(SCOPE_PROTECTED)) {
+ noex = NOEX_PROTECTED;
+ }
+ else {
+ noex = NOEX_PUBLIC;
+ }
+ if (body && origin == ruby_class && body->nd_body == 0) {
+ noex |= NOEX_NOSUPER;
+ }
+
+ defn = rb_copy_node_scope(node->nd_defn, ruby_cref);
+ rb_add_method(ruby_class, node->nd_mid, defn, noex);
+ if (scope_vmode == SCOPE_MODFUNC) {
+ rb_add_method(rb_singleton_class(ruby_class),
+ node->nd_mid, defn, NOEX_PUBLIC);
+ }
+}
+
+
+NOINLINE (static void
+eval_defs(self, node))
+ VALUE self;
+ NODE *node;
+{
+ VALUE recv = rb_eval(self, node->nd_recv);
+ VALUE klass;
+ NODE *body = 0, *defn;
+ st_data_t data;
+
+ if (ruby_safe_level >= 4 && !OBJ_TAINTED(recv)) {
+ rb_raise(rb_eSecurityError, "Insecure: can't define singleton method");
+ }
+ if (FIXNUM_P(recv) || SYMBOL_P(recv)) {
+ rb_raise(rb_eTypeError,
+ "can't define singleton method \"%s\" for %s",
+ rb_id2name(node->nd_mid),
+ rb_obj_classname(recv));
+ }
+
+ if (OBJ_FROZEN(recv)) rb_error_frozen("object");
+ klass = rb_singleton_class(recv);
+ if (st_lookup(RCLASS(klass)->m_tbl, node->nd_mid, &data)) {
+ body = (NODE *)data;
+ if (ruby_safe_level >= 4) {
+ rb_raise(rb_eSecurityError, "redefining method prohibited");
+ }
+ if (RTEST(ruby_verbose)) {
+ rb_warning("redefine %s", rb_id2name(node->nd_mid));
+ }
+ }
+ defn = rb_copy_node_scope(node->nd_defn, ruby_cref);
+ rb_add_method(klass, node->nd_mid, defn,
+ NOEX_PUBLIC|(body?body->nd_noex&NOEX_UNDEF:0));
+}
+
+
+NOINLINE (static VALUE
+eval_class(self, node))
+ VALUE self;
+ NODE *node;
+{
+ VALUE super, klass, tmp, cbase;
+ ID cname;
+ int gen = Qfalse;
+
+ cbase = class_prefix(self, node->nd_cpath);
+ cname = node->nd_cpath->nd_mid;
+
+ if (NIL_P(ruby_cbase)) {
+ rb_raise(rb_eTypeError, "no outer class/module");
+ }
+ if (node->nd_super) {
+ super = rb_eval(self, node->nd_super);
+ rb_check_inheritable(super);
+ }
+ else {
+ super = 0;
+ }
+
+ if (rb_const_defined_at(cbase, cname)) {
+ klass = rb_const_get_at(cbase, cname);
+ if (TYPE(klass) != T_CLASS) {
+ rb_raise(rb_eTypeError, "%s is not a class",
+ rb_id2name(cname));
+ }
+ if (super) {
+ tmp = rb_class_real(RCLASS(klass)->super);
+ if (tmp != super) {
+ rb_raise(rb_eTypeError, "superclass mismatch for class %s",
+ rb_id2name(cname));
+ }
+ super = 0;
+ }
+ if (ruby_safe_level >= 4) {
+ rb_raise(rb_eSecurityError, "extending class prohibited");
+ }
+ }
+ else {
+ if (!super) super = rb_cObject;
+ klass = rb_define_class_id(cname, super);
+ rb_set_class_path(klass, cbase, rb_id2name(cname));
+ rb_const_set(cbase, cname, klass);
+ gen = Qtrue;
+ }
+ if (ruby_wrapper) {
+ rb_extend_object(klass, ruby_wrapper);
+ rb_include_module(klass, ruby_wrapper);
+ }
+ if (super && gen) {
+ rb_class_inherited(super, klass);
+ }
+ return module_setup(klass, node);
+}
+
+
+NOINLINE (static VALUE
+eval_module(self, node))
+ VALUE self;
+ NODE *node;
+{
+ VALUE module, cbase;
+ ID cname;
+
+ if (NIL_P(ruby_cbase)) {
+ rb_raise(rb_eTypeError, "no outer class/module");
+ }
+ cbase = class_prefix(self, node->nd_cpath);
+ cname = node->nd_cpath->nd_mid;
+ if (rb_const_defined_at(cbase, cname)) {
+ module = rb_const_get_at(cbase, cname);
+ if (TYPE(module) != T_MODULE) {
+ rb_raise(rb_eTypeError, "%s is not a module",
+ rb_id2name(cname));
+ }
+ if (ruby_safe_level >= 4) {
+ rb_raise(rb_eSecurityError, "extending module prohibited");
+ }
+ }
+ else {
+ module = rb_define_module_id(cname);
+ rb_set_class_path(module, cbase, rb_id2name(cname));
+ rb_const_set(cbase, cname, module);
+ }
+ if (ruby_wrapper) {
+ rb_extend_object(module, ruby_wrapper);
+ rb_include_module(module, ruby_wrapper);
+ }
+
+ return module_setup(module, node);
+}
+
+
+NOINLINE (static VALUE
+eval_sclass(self, node))
+ VALUE self;
+ NODE *node;
+{
+ VALUE klass, result;
+
+ result = rb_eval(self, node->nd_recv);
+ if (FIXNUM_P(result) || SYMBOL_P(result)) {
+ rb_raise(rb_eTypeError, "no virtual class for %s",
+ rb_obj_classname(result));
+ }
+ if (ruby_safe_level >= 4 && !OBJ_TAINTED(result))
+ rb_raise(rb_eSecurityError, "Insecure: can't extend object");
+ klass = rb_singleton_class(result);
+
+ if (ruby_wrapper) {
+ rb_extend_object(klass, ruby_wrapper);
+ rb_include_module(klass, ruby_wrapper);
+ }
+
+ return module_setup(klass, node);
+}
+
+
+NOINLINE (static VALUE
+eval_defined(self, node))
+ VALUE self;
+ NODE *node;
+{
+ char buf[20];
+ const char *desc = is_defined(self, node->nd_head, buf);
+ return desc ? rb_str_new2(desc) : Qnil;
+}
+
+
+NOINLINE (static void
+eval_cvar_set(result, node, bool))
+ VALUE result, bool;
+ NODE *node;
+{
+ rb_cvar_set(cvar_cbase(), node->nd_vid, result, bool);
+}
+
+
+NOINLINE (static void
+eval_cdecl(self, node, result))
+ VALUE self, result;
+ NODE *node;
+{
+ if (node->nd_vid == 0)
+ rb_const_set(class_prefix(self, node->nd_else),
+ node->nd_else->nd_mid, result);
+ else
+ rb_const_set(ruby_cbase, node->nd_vid, result);
+}
+
+
+static VALUE
+rb_eval(self, node)
+ VALUE self;
+ NODE *node;
+{
+ VALUE result;
+
+again:
+ CHECK_INTS;
+ result = Qnil;
+ if (node) {
ruby_current_node = node;
+
switch (nd_type(node)) {
case NODE_BLOCK:
- if (contnode) {
- result = rb_eval(self, node);
- break;
+ while (node->nd_next) {
+ rb_eval(self, node->nd_head);
+ node = node->nd_next;
}
- contnode = node->nd_next;
node = node->nd_head;
goto again;
case NODE_POSTEXE:
rb_f_END();
nd_set_type(node, NODE_NIL); /* exec just once */
- result = Qnil;
break;
/* begin .. end without clauses */
@@ -2990,65 +3905,33 @@
/* nodes for speed-up(literal match) */
case NODE_MATCH2:
- {
- VALUE l = rb_eval(self,node->nd_recv);
- VALUE r = rb_eval(self,node->nd_value);
- result = rb_reg_match(l, r);
- }
+ result = eval_match2(self, node);
break;
/* nodes for speed-up(literal match) */
case NODE_MATCH3:
- {
- VALUE r = rb_eval(self,node->nd_recv);
- VALUE l = rb_eval(self,node->nd_value);
- if (TYPE(l) == T_STRING) {
- result = rb_reg_match(r, l);
- }
- else {
- result = rb_funcall(l, match, 1, r);
- }
- }
+ result = eval_match3(self,node);
break;
/* node for speed-up(top-level loop for -n/-p) */
case NODE_OPT_N:
- PUSH_TAG(PROT_LOOP);
- switch (state = EXEC_TAG()) {
- case 0:
- opt_n_next:
- while (!NIL_P(rb_gets())) {
- opt_n_redo:
- rb_eval(self, node->nd_body);
- }
- break;
-
- case TAG_REDO:
- state = 0;
- goto opt_n_redo;
- case TAG_NEXT:
- state = 0;
- goto opt_n_next;
- case TAG_BREAK:
- state = 0;
- default:
- break;
- }
- POP_TAG();
- if (state) JUMP_TAG(state);
- RETURN(Qnil);
+ eval_opt_n(self, node);
+ break;
case NODE_SELF:
- RETURN(self);
+ result = self;
+ break;
case NODE_NIL:
- RETURN(Qnil);
+ break;
case NODE_TRUE:
- RETURN(Qtrue);
+ result = Qtrue;
+ break;
case NODE_FALSE:
- RETURN(Qfalse);
+ result = Qfalse;
+ break;
case NODE_IF:
if (RTEST(rb_eval(self, node->nd_cond))) {
@@ -3066,150 +3949,20 @@
goto again;
case NODE_WHEN:
- while (node) {
- NODE *tag;
-
- if (nd_type(node) != NODE_WHEN) goto again;
- tag = node->nd_head;
- while (tag) {
- EXEC_EVENT_HOOK(RUBY_EVENT_LINE, tag, self,
- ruby_frame->last_func,
- ruby_frame->last_class);
- if (tag->nd_head && nd_type(tag->nd_head) == NODE_WHEN) {
- VALUE v = rb_eval(self, tag->nd_head->nd_head);
- long i;
-
- if (TYPE(v) != T_ARRAY) v = rb_ary_to_ary(v);
- for (i=0; i<RARRAY(v)->len; i++) {
- if (RTEST(RARRAY(v)->ptr[i])) {
- node = node->nd_body;
- goto again;
- }
- }
- tag = tag->nd_next;
- continue;
- }
- if (RTEST(rb_eval(self, tag->nd_head))) {
- node = node->nd_body;
- goto again;
- }
- tag = tag->nd_next;
- }
- node = node->nd_next;
- }
- RETURN(Qnil);
+ if (node = eval_when(self, node)) goto again;
+ break;
case NODE_CASE:
- {
- VALUE val;
-
- val = rb_eval(self, node->nd_head);
- node = node->nd_body;
- while (node) {
- NODE *tag;
-
- if (nd_type(node) != NODE_WHEN) {
- goto again;
- }
- tag = node->nd_head;
- while (tag) {
- EXEC_EVENT_HOOK(RUBY_EVENT_LINE, tag, self,
- ruby_frame->last_func,
- ruby_frame->last_class);
- if (tag->nd_head && nd_type(tag->nd_head) == NODE_WHEN) {
- VALUE v = rb_eval(self, tag->nd_head->nd_head);
- long i;
-
- if (TYPE(v) != T_ARRAY) v = rb_ary_to_ary(v);
- for (i=0; i<RARRAY(v)->len; i++) {
- if (RTEST(rb_funcall2(RARRAY(v)->ptr[i], eqq, 1, &val))){
- node = node->nd_body;
- goto again;
- }
- }
- tag = tag->nd_next;
- continue;
- }
- if (RTEST(rb_funcall2(rb_eval(self, tag->nd_head), eqq, 1, &val))) {
- node = node->nd_body;
- goto again;
- }
- tag = tag->nd_next;
- }
- node = node->nd_next;
- }
- }
- RETURN(Qnil);
+ if (node = eval_case(self, node)) goto again;
+ break;
case NODE_WHILE:
- PUSH_TAG(PROT_LOOP);
- result = Qnil;
- switch (state = EXEC_TAG()) {
- case 0:
- if (node->nd_state && !RTEST(rb_eval(self, node->nd_cond)))
- goto while_out;
- do {
- while_redo:
- rb_eval(self, node->nd_body);
- while_next:
- ;
- } while (RTEST(rb_eval(self, node->nd_cond)));
- break;
-
- case TAG_REDO:
- state = 0;
- goto while_redo;
- case TAG_NEXT:
- state = 0;
- goto while_next;
- case TAG_BREAK:
- if (TAG_DST()) {
- state = 0;
- result = prot_tag->retval;
- }
- /* fall through */
- default:
- break;
- }
- while_out:
- POP_TAG();
- if (state) JUMP_TAG(state);
- RETURN(result);
+ result = eval_while(self,node);
+ break;
case NODE_UNTIL:
- PUSH_TAG(PROT_LOOP);
- result = Qnil;
- switch (state = EXEC_TAG()) {
- case 0:
- if (node->nd_state && RTEST(rb_eval(self, node->nd_cond)))
- goto until_out;
- do {
- until_redo:
- rb_eval(self, node->nd_body);
- until_next:
- ;
- } while (!RTEST(rb_eval(self, node->nd_cond)));
- break;
-
- case TAG_REDO:
- state = 0;
- goto until_redo;
- case TAG_NEXT:
- state = 0;
- goto until_next;
- case TAG_BREAK:
- if (TAG_DST()) {
- state = 0;
- result = prot_tag->retval;
- }
- /* fall through */
- default:
- break;
- }
- until_out:
- POP_TAG();
- if (state) JUMP_TAG(state);
- RETURN(result);
+ result = eval_until(self,node);
+ break;
case NODE_BLOCK_PASS:
result = block_pass(self, node);
@@ -3217,47 +3970,7 @@
case NODE_ITER:
case NODE_FOR:
- {
- PUSH_TAG(PROT_LOOP);
- PUSH_BLOCK(node->nd_var, node->nd_body);
-
- state = EXEC_TAG();
- if (state == 0) {
- iter_retry:
- PUSH_ITER(ITER_PRE);
- if (nd_type(node) == NODE_ITER) {
- result = rb_eval(self, node->nd_iter);
- }
- else {
- VALUE recv;
-
- _block.flags &= ~BLOCK_D_SCOPE;
- BEGIN_CALLARGS;
- recv = rb_eval(self, node->nd_iter);
- END_CALLARGS;
- ruby_current_node = node;
- SET_CURRENT_SOURCE();
- result = rb_call(CLASS_OF(recv),recv,each,0,0,0,self);
- }
- POP_ITER();
- }
- else if (state == TAG_BREAK && TAG_DST()) {
- result = prot_tag->retval;
- state = 0;
- }
- else if (state == TAG_RETRY) {
- state = 0;
- goto iter_retry;
- }
- POP_BLOCK();
- POP_TAG();
- switch (state) {
- case 0:
- break;
- default:
- JUMP_TAG(state);
- }
- }
+ result = eval_iter(self, node);
break;
case NODE_BREAK:
@@ -3265,17 +3978,14 @@
break;
case NODE_NEXT:
- CHECK_INTS;
next_jump(rb_eval(self, node->nd_stts));
break;
case NODE_REDO:
- CHECK_INTS;
JUMP_TAG(TAG_REDO);
break;
case NODE_RETRY:
- CHECK_INTS;
JUMP_TAG(TAG_RETRY);
break;
@@ -3305,73 +4015,15 @@
break;
case NODE_RESCUE:
- {
- volatile VALUE e_info = ruby_errinfo;
- volatile int rescuing = 0;
-
- PUSH_TAG(PROT_NONE);
- if ((state = EXEC_TAG()) == 0) {
- retry_entry:
- result = rb_eval(self, node->nd_head);
- }
- else if (rescuing) {
- if (rescuing < 0) {
- /* in rescue argument, just reraise */
- }
- else if (state == TAG_RETRY) {
- rescuing = state = 0;
- ruby_errinfo = e_info;
- goto retry_entry;
- }
- else if (state != TAG_RAISE) {
- result = prot_tag->retval;
- }
- }
- else if (state == TAG_RAISE) {
- NODE *resq = node->nd_resq;
-
- rescuing = -1;
- while (resq) {
- ruby_current_node = resq;
- if (handle_rescue(self, resq)) {
- state = 0;
- rescuing = 1;
- result = rb_eval(self, resq->nd_body);
- break;
- }
- resq = resq->nd_head; /* next rescue */
- }
- }
- else {
- result = prot_tag->retval;
- }
- POP_TAG();
- if (state != TAG_RAISE) ruby_errinfo = e_info;
- if (state) {
- JUMP_TAG(state);
- }
- /* no exception raised */
- if (!rescuing && (node = node->nd_else)) { /* else clause given */
- goto again;
- }
- }
+ result = eval_rescue(self,node);
+ if (result == Qundef) { /* handle else clause w/o recursion */
+ node = node->nd_else;
+ goto again;
+ }
break;
case NODE_ENSURE:
- PUSH_TAG(PROT_NONE);
- if ((state = EXEC_TAG()) == 0) {
- result = rb_eval(self, node->nd_head);
- }
- POP_TAG();
- if (node->nd_ensr && !thread_no_ensure()) {
- VALUE retval = prot_tag->retval; /* save retval */
- VALUE errinfo = ruby_errinfo;
-
- rb_eval(self, node->nd_ensr);
- return_value(retval);
- ruby_errinfo = errinfo;
- }
- if (state) JUMP_TAG(state);
+ result = eval_ensure(self,node);
break;
case NODE_AND:
@@ -3387,56 +4039,20 @@
goto again;
case NODE_NOT:
- if (RTEST(rb_eval(self, node->nd_body))) result = Qfalse;
- else result = Qtrue;
+ result = RTEST(rb_eval(self, node->nd_body)) ? Qfalse : Qtrue;
break;
case NODE_DOT2:
case NODE_DOT3:
- {
- VALUE beg = rb_eval(self, node->nd_beg);
- VALUE end = rb_eval(self, node->nd_end);
- result = rb_range_new(beg, end, nd_type(node) == NODE_DOT3);
- }
- break;
+ result = eval_dot(self,node);
+ break;
case NODE_FLIP2: /* like AWK */
- {
- VALUE *flip = rb_svar(node->nd_cnt);
- if (!flip) rb_bug("unexpected local variable");
- if (!RTEST(*flip)) {
- if (RTEST(rb_eval(self, node->nd_beg))) {
- *flip = RTEST(rb_eval(self, node->nd_end))?Qfalse:Qtrue;
- result = Qtrue;
- }
- else {
- result = Qfalse;
- }
- }
- else {
- if (RTEST(rb_eval(self, node->nd_end))) {
- *flip = Qfalse;
- }
- result = Qtrue;
- }
- }
+ result = eval_flip2(self,node);
break;
case NODE_FLIP3: /* like SED */
- {
- VALUE *flip = rb_svar(node->nd_cnt);
- if (!flip) rb_bug("unexpected local variable");
- if (!RTEST(*flip)) {
- result = RTEST(rb_eval(self, node->nd_beg)) ? Qtrue : Qfalse;
- *flip = result;
- }
- else {
- if (RTEST(rb_eval(self, node->nd_end))) {
- *flip = Qfalse;
- }
- result = Qtrue;
- }
- }
+ result = eval_flip3(self,node);
break;
case NODE_RETURN:
@@ -3444,75 +4060,25 @@
break;
case NODE_ARGSCAT:
- {
- VALUE args = rb_eval(self, node->nd_head);
- result = rb_ary_concat(args, splat_value(rb_eval(self, node->nd_body)));
- }
+ result = rb_eval(self, node->nd_head);
+ result = rb_ary_concat(result, splat_value(rb_eval(self, node->nd_body)));
break;
case NODE_ARGSPUSH:
- {
- VALUE args = rb_ary_dup(rb_eval(self, node->nd_head));
- result = rb_ary_push(args, rb_eval(self, node->nd_body));
- }
+ result = rb_ary_dup(rb_eval(self, node->nd_head));
+ result = rb_ary_push(result, rb_eval(self, node->nd_body));
break;
case NODE_ATTRASGN:
- {
- VALUE recv;
- int argc; VALUE *argv; /* used in SETUP_ARGS */
- int scope;
- TMP_PROTECT;
-
- BEGIN_CALLARGS;
- if (node->nd_recv == (NODE *)1) {
- recv = self;
- scope = 1;
- }
- else {
- recv = rb_eval(self, node->nd_recv);
- scope = 0;
- }
- SETUP_ARGS(node->nd_args);
- END_CALLARGS;
-
- ruby_current_node = node;
- SET_CURRENT_SOURCE();
- rb_call(CLASS_OF(recv),recv,node->nd_mid,argc,argv,scope,self);
- result = argv[argc-1];
- }
- break;
+ result = eval_attrasgn(self,node);
+ break;
case NODE_CALL:
- {
- VALUE recv;
- int argc; VALUE *argv; /* used in SETUP_ARGS */
- TMP_PROTECT;
-
- BEGIN_CALLARGS;
- recv = rb_eval(self, node->nd_recv);
- SETUP_ARGS(node->nd_args);
- END_CALLARGS;
-
- ruby_current_node = node;
- SET_CURRENT_SOURCE();
- result = rb_call(CLASS_OF(recv),recv,node->nd_mid,argc,argv,0,self);
- }
+ result = eval_call(self,node);
break;
case NODE_FCALL:
- {
- int argc; VALUE *argv; /* used in SETUP_ARGS */
- TMP_PROTECT;
-
- BEGIN_CALLARGS;
- SETUP_ARGS(node->nd_args);
- END_CALLARGS;
-
- ruby_current_node = node;
- SET_CURRENT_SOURCE();
- result = rb_call(CLASS_OF(self),self,node->nd_mid,argc,argv,1,self);
- }
+ result = eval_fcall(self,node);
break;
case NODE_VCALL:
@@ -3522,142 +4088,19 @@
case NODE_SUPER:
case NODE_ZSUPER:
- {
- int argc; VALUE *argv; /* used in SETUP_ARGS */
- TMP_PROTECT;
-
- if (ruby_frame->last_class == 0) {
- if (ruby_frame->last_func) {
- rb_name_error(ruby_frame->last_func,
- "superclass method `%s' disabled",
- rb_id2name(ruby_frame->orig_func));
- }
- else {
- rb_raise(rb_eNoMethodError, "super called outside of method");
- }
- }
- if (nd_type(node) == NODE_ZSUPER) {
- argc = ruby_frame->argc;
- if (argc && DMETHOD_P()) {
- if (TYPE(RBASIC(ruby_scope)->klass) != T_ARRAY ||
- RARRAY(RBASIC(ruby_scope)->klass)->len != argc) {
- rb_raise(rb_eRuntimeError,
- "super: specify arguments explicitly");
- }
- argv = RARRAY(RBASIC(ruby_scope)->klass)->ptr;
- }
- else if (!ruby_scope->local_vars) {
- argc = 0;
- argv = 0;
- }
- else {
- argv = ruby_scope->local_vars + 2;
- }
- }
- else {
- BEGIN_CALLARGS;
- SETUP_ARGS(node->nd_args);
- END_CALLARGS;
- ruby_current_node = node;
- }
-
- SET_CURRENT_SOURCE();
- result = rb_call_super(argc, argv);
- }
+ result = eval_super(self,node);
break;
case NODE_SCOPE:
- {
- struct FRAME frame;
- NODE *saved_cref = 0;
-
- frame = *ruby_frame;
- frame.tmp = ruby_frame;
- ruby_frame = &frame;
-
- PUSH_SCOPE();
- PUSH_TAG(PROT_NONE);
- if (node->nd_rval) {
- saved_cref = ruby_cref;
- ruby_cref = (NODE*)node->nd_rval;
- }
- if (node->nd_tbl) {
- VALUE *vars = ALLOCA_N(VALUE, node->nd_tbl[0]+1);
- *vars++ = (VALUE)node;
- ruby_scope->local_vars = vars;
- rb_mem_clear(ruby_scope->local_vars, node->nd_tbl[0]);
- ruby_scope->local_tbl = node->nd_tbl;
- }
- else {
- ruby_scope->local_vars = 0;
- ruby_scope->local_tbl = 0;
- }
- if ((state = EXEC_TAG()) == 0) {
- result = rb_eval(self, node->nd_next);
- }
- POP_TAG();
- POP_SCOPE();
- ruby_frame = frame.tmp;
- if (saved_cref)
- ruby_cref = saved_cref;
- if (state) JUMP_TAG(state);
- }
- break;
+ result = eval_scope(self,node);
+ break;
case NODE_OP_ASGN1:
- {
- int argc; VALUE *argv; /* used in SETUP_ARGS */
- VALUE recv, val, tmp;
- NODE *rval;
- TMP_PROTECT;
-
- recv = rb_eval(self, node->nd_recv);
- rval = node->nd_args->nd_head;
- SETUP_ARGS0(node->nd_args->nd_body, 1);
- val = rb_funcall3(recv, aref, argc, argv);
- switch (node->nd_mid) {
- case 0: /* OR */
- if (RTEST(val)) RETURN(val);
- val = rb_eval(self, rval);
- break;
- case 1: /* AND */
- if (!RTEST(val)) RETURN(val);
- val = rb_eval(self, rval);
- break;
- default:
- tmp = rb_eval(self, rval);
- val = rb_funcall3(val, node->nd_mid, 1, &tmp);
- }
- argv[argc] = val;
- rb_funcall2(recv, aset, argc+1, argv);
- result = val;
- }
+ result = eval_op_asgn1(self,node);
break;
case NODE_OP_ASGN2:
- {
- ID id = node->nd_next->nd_vid;
- VALUE recv, val, tmp;
-
- recv = rb_eval(self, node->nd_recv);
- val = rb_funcall3(recv, id, 0, 0);
- switch (node->nd_next->nd_mid) {
- case 0: /* OR */
- if (RTEST(val)) RETURN(val);
- val = rb_eval(self, node->nd_value);
- break;
- case 1: /* AND */
- if (!RTEST(val)) RETURN(val);
- val = rb_eval(self, node->nd_value);
- break;
- default:
- tmp = rb_eval(self, node->nd_value);
- val = rb_funcall3(val, node->nd_next->nd_mid, 1, &tmp);
- }
-
- rb_funcall2(recv, node->nd_next->nd_aid, 1, &val);
- result = val;
- }
+ result = eval_op_asgn2(self,node);
break;
case NODE_OP_ASGN_AND:
@@ -3706,26 +4149,21 @@
break;
case NODE_CDECL:
- result = rb_eval(self, node->nd_value);
- if (node->nd_vid == 0) {
- rb_const_set(class_prefix(self, node->nd_else), node->nd_else->nd_mid, result);
- }
- else {
- rb_const_set(ruby_cbase, node->nd_vid, result);
- }
+ result = rb_eval(self, node->nd_value);
+ eval_cdecl(self, node, result);
break;
case NODE_CVDECL:
if (NIL_P(ruby_cbase)) {
rb_raise(rb_eTypeError, "no class/module to define class variable");
}
- result = rb_eval(self, node->nd_value);
- rb_cvar_set(cvar_cbase(), node->nd_vid, result, Qtrue);
+ result = rb_eval(self, node->nd_value);
+ eval_cvar_set(result, node, Qtrue);
break;
case NODE_CVASGN:
- result = rb_eval(self, node->nd_value);
- rb_cvar_set(cvar_cbase(), node->nd_vid, result, Qfalse);
+ result = rb_eval(self, node->nd_value);
+ eval_cvar_set(result, node, Qfalse);
break;
case NODE_LVAR:
@@ -3768,26 +4206,21 @@
break;
case NODE_COLON2:
- {
- VALUE klass;
-
- klass = rb_eval(self, node->nd_head);
- if (rb_is_const_id(node->nd_mid)) {
- switch (TYPE(klass)) {
- case T_CLASS:
- case T_MODULE:
- result = rb_const_get_from(klass, node->nd_mid);
- break;
- default:
- rb_raise(rb_eTypeError, "%s is not a class/module",
- RSTRING(rb_obj_as_string(klass))->ptr);
- break;
- }
- }
- else {
- result = rb_funcall(klass, node->nd_mid, 0, 0);
+ result = rb_eval(self, node->nd_head);
+ if (rb_is_const_id(node->nd_mid)) {
+ switch (TYPE(result)) {
+ case T_CLASS:
+ case T_MODULE:
+ result = rb_const_get_from(result, node->nd_mid);
+ break;
+ default:
+ rb_raise(rb_eTypeError, "%s is not a class/module",
+ RSTRING(rb_obj_as_string(result))->ptr);
+ break;
}
}
+ else
+ result = rb_funcall(result, node->nd_mid, 0, 0);
break;
case NODE_COLON3:
@@ -3818,23 +4251,7 @@
break;
case NODE_HASH:
- {
- NODE *list;
- VALUE hash = rb_hash_new();
- VALUE key, val;
-
- list = node->nd_head;
- while (list) {
- key = rb_eval(self, list->nd_head);
- list = list->nd_next;
- if (list == 0)
- rb_bug("odd number list for Hash");
- val = rb_eval(self, list->nd_head);
- list = list->nd_next;
- rb_hash_aset(hash, key, val);
- }
- result = hash;
- }
+ result = eval_hash(self,node);
break;
case NODE_ZARRAY: /* zero length list */
@@ -3842,19 +4259,7 @@
break;
case NODE_ARRAY:
- {
- VALUE ary;
- long i;
-
- i = node->nd_alen;
- ary = rb_ary_new2(i);
- for (i=0;node;node=node->nd_next) {
- RARRAY(ary)->ptr[i++] = rb_eval(self, node->nd_head);
- RARRAY(ary)->len = i;
- }
-
- result = ary;
- }
+ result = eval_array(self,node);
break;
case NODE_STR:
@@ -3870,51 +4275,8 @@
case NODE_DREGX:
case NODE_DREGX_ONCE:
case NODE_DSYM:
- {
- VALUE str, str2;
- NODE *list = node->nd_next;
-
- str = rb_str_new3(node->nd_lit);
- while (list) {
- if (list->nd_head) {
- switch (nd_type(list->nd_head)) {
- case NODE_STR:
- str2 = list->nd_head->nd_lit;
- break;
- default:
- str2 = rb_eval(self, list->nd_head);
- break;
- }
- rb_str_append(str, str2);
- OBJ_INFECT(str, str2);
- }
- list = list->nd_next;
- }
- switch (nd_type(node)) {
- case NODE_DREGX:
- result = rb_reg_new(RSTRING(str)->ptr, RSTRING(str)->len,
- node->nd_cflag);
- break;
- case NODE_DREGX_ONCE: /* regexp expand once */
- result = rb_reg_new(RSTRING(str)->ptr, RSTRING(str)->len,
- node->nd_cflag);
- nd_set_type(node, NODE_LIT);
- node->nd_lit = result;
- break;
- case NODE_LIT:
- /* other thread may replace NODE_DREGX_ONCE to NODE_LIT */
- goto again;
- case NODE_DXSTR:
- result = rb_funcall(self, '`', 1, str);
- break;
- case NODE_DSYM:
- result = rb_str_intern(str);
- break;
- default:
- result = str;
- break;
- }
- }
+ result = eval_slit(self, node);
+ if (result == Qundef) goto again;
break;
case NODE_XSTR:
@@ -3926,84 +4288,13 @@
break;
case NODE_DEFN:
- if (node->nd_defn) {
- NODE *body, *defn;
- VALUE origin = 0;
- int noex;
-
- if (NIL_P(ruby_class)) {
- rb_raise(rb_eTypeError, "no class/module to add method");
- }
- if (ruby_class == rb_cObject && node->nd_mid == init) {
- rb_warn("redefining Object#initialize may cause infinite loop");
- }
- if (node->nd_mid == __id__ || node->nd_mid == __send__) {
- rb_warn("redefining `%s' may cause serious problem",
- rb_id2name(node->nd_mid));
- }
- rb_frozen_class_p(ruby_class);
- body = search_method(ruby_class, node->nd_mid, &origin);
- if (body){
- if (RTEST(ruby_verbose) && ruby_class == origin && body->nd_cnt == 0 && body->nd_body) {
- rb_warning("method redefined; discarding old %s", rb_id2name(node->nd_mid));
- }
- }
-
- if (SCOPE_TEST(SCOPE_PRIVATE) || node->nd_mid == init) {
- noex = NOEX_PRIVATE;
- }
- else if (SCOPE_TEST(SCOPE_PROTECTED)) {
- noex = NOEX_PROTECTED;
- }
- else {
- noex = NOEX_PUBLIC;
- }
- if (body && origin == ruby_class && body->nd_body == 0) {
- noex |= NOEX_NOSUPER;
- }
-
- defn = rb_copy_node_scope(node->nd_defn, ruby_cref);
- rb_add_method(ruby_class, node->nd_mid, defn, noex);
- if (scope_vmode == SCOPE_MODFUNC) {
- rb_add_method(rb_singleton_class(ruby_class),
- node->nd_mid, defn, NOEX_PUBLIC);
- }
- result = Qnil;
- }
+ if (node->nd_defn)
+ eval_defn(self,node);
break;
case NODE_DEFS:
- if (node->nd_defn) {
- VALUE recv = rb_eval(self, node->nd_recv);
- VALUE klass;
- NODE *body = 0, *defn;
-
- if (ruby_safe_level >= 4 && !OBJ_TAINTED(recv)) {
- rb_raise(rb_eSecurityError, "Insecure: can't define singleton method");
- }
- if (FIXNUM_P(recv) || SYMBOL_P(recv)) {
- rb_raise(rb_eTypeError,
- "can't define singleton method \"%s\" for %s",
- rb_id2name(node->nd_mid),
- rb_obj_classname(recv));
- }
-
- if (OBJ_FROZEN(recv)) rb_error_frozen("object");
- klass = rb_singleton_class(recv);
- if (st_lookup(RCLASS(klass)->m_tbl, node->nd_mid, &data)) {
- body = (NODE *)data;
- if (ruby_safe_level >= 4) {
- rb_raise(rb_eSecurityError, "redefining method prohibited");
- }
- if (RTEST(ruby_verbose)) {
- rb_warning("redefine %s", rb_id2name(node->nd_mid));
- }
- }
- defn = rb_copy_node_scope(node->nd_defn, ruby_cref);
- rb_add_method(klass, node->nd_mid, defn,
- NOEX_PUBLIC|(body?body->nd_noex&NOEX_UNDEF:0));
- result = Qnil;
- }
+ if (node->nd_defn)
+ eval_defs(self,node);
break;
case NODE_UNDEF:
@@ -4011,7 +4302,6 @@
rb_raise(rb_eTypeError, "no class to undef method");
}
rb_undef(ruby_class, rb_to_id(rb_eval(self, node->u2.node)));
- result = Qnil;
break;
case NODE_ALIAS:
@@ -4020,134 +4310,26 @@
}
rb_alias(ruby_class, rb_to_id(rb_eval(self, node->u1.node)),
rb_to_id(rb_eval(self, node->u2.node)));
- result = Qnil;
break;
case NODE_VALIAS:
rb_alias_variable(node->u1.id, node->u2.id);
- result = Qnil;
break;
case NODE_CLASS:
- {
- VALUE super, klass, tmp, cbase;
- ID cname;
- int gen = Qfalse;
-
- cbase = class_prefix(self, node->nd_cpath);
- cname = node->nd_cpath->nd_mid;
-
- if (NIL_P(ruby_cbase)) {
- rb_raise(rb_eTypeError, "no outer class/module");
- }
- if (node->nd_super) {
- super = rb_eval(self, node->nd_super);
- rb_check_inheritable(super);
- }
- else {
- super = 0;
- }
-
- if (rb_const_defined_at(cbase, cname)) {
- klass = rb_const_get_at(cbase, cname);
- if (TYPE(klass) != T_CLASS) {
- rb_raise(rb_eTypeError, "%s is not a class",
- rb_id2name(cname));
- }
- if (super) {
- tmp = rb_class_real(RCLASS(klass)->super);
- if (tmp != super) {
- rb_raise(rb_eTypeError, "superclass mismatch for class %s",
- rb_id2name(cname));
- }
- super = 0;
- }
- if (ruby_safe_level >= 4) {
- rb_raise(rb_eSecurityError, "extending class prohibited");
- }
- }
- else {
- if (!super) super = rb_cObject;
- klass = rb_define_class_id(cname, super);
- rb_set_class_path(klass, cbase, rb_id2name(cname));
- rb_const_set(cbase, cname, klass);
- gen = Qtrue;
- }
- if (ruby_wrapper) {
- rb_extend_object(klass, ruby_wrapper);
- rb_include_module(klass, ruby_wrapper);
- }
- if (super && gen) {
- rb_class_inherited(super, klass);
- }
- result = module_setup(klass, node);
- }
+ result = eval_class(self,node);
break;
case NODE_MODULE:
- {
- VALUE module, cbase;
- ID cname;
-
- if (NIL_P(ruby_cbase)) {
- rb_raise(rb_eTypeError, "no outer class/module");
- }
- cbase = class_prefix(self, node->nd_cpath);
- cname = node->nd_cpath->nd_mid;
- if (rb_const_defined_at(cbase, cname)) {
- module = rb_const_get_at(cbase, cname);
- if (TYPE(module) != T_MODULE) {
- rb_raise(rb_eTypeError, "%s is not a module",
- rb_id2name(cname));
- }
- if (ruby_safe_level >= 4) {
- rb_raise(rb_eSecurityError, "extending module prohibited");
- }
- }
- else {
- module = rb_define_module_id(cname);
- rb_set_class_path(module, cbase, rb_id2name(cname));
- rb_const_set(cbase, cname, module);
- }
- if (ruby_wrapper) {
- rb_extend_object(module, ruby_wrapper);
- rb_include_module(module, ruby_wrapper);
- }
-
- result = module_setup(module, node);
- }
+ result = eval_module(self,node);
break;
case NODE_SCLASS:
- {
- VALUE klass;
-
- result = rb_eval(self, node->nd_recv);
- if (FIXNUM_P(result) || SYMBOL_P(result)) {
- rb_raise(rb_eTypeError, "no virtual class for %s",
- rb_obj_classname(result));
- }
- if (ruby_safe_level >= 4 && !OBJ_TAINTED(result))
- rb_raise(rb_eSecurityError, "Insecure: can't extend object");
- klass = rb_singleton_class(result);
-
- if (ruby_wrapper) {
- rb_extend_object(klass, ruby_wrapper);
- rb_include_module(klass, ruby_wrapper);
- }
-
- result = module_setup(klass, node);
- }
+ result = eval_sclass(self,node);
break;
case NODE_DEFINED:
- {
- char buf[20];
- const char *desc = is_defined(self, node->nd_head, buf);
-
- if (desc) result = rb_str_new2(desc);
- else result = Qnil;
- }
+ result = eval_defined(self,node);
break;
case NODE_NEWLINE:
@@ -4160,14 +4342,8 @@
default:
unknown_node(node);
}
- finish:
- CHECK_INTS;
- if (contnode) {
- node = contnode;
- contnode = 0;
- goto again;
- }
- return result;
+ }
+ return result;
}
static VALUE
@@ -13081,6 +13257,32 @@
VALUE rb_cCont;
+
+static rb_thread_t prep4callcc(void)
+{
+ rb_thread_t th;
+ struct tag *tag;
+ struct RVarmap *vars;
+
+ THREAD_ALLOC(th);
+ /* must finish th initialization before any possible gc */
+ th->thread = curr_thread->thread; /* brent@mbari.org */
+ th->thgroup = cont_protect;
+
+ scope_dup(ruby_scope);
+ for (tag=prot_tag; tag; tag=tag->prev) {
+ if (tag->tag == PROT_THREAD) break;
+ scope_dup(tag->scope);
+ }
+
+ for (vars = ruby_dyna_vars; vars; vars = vars->next) {
+ if (FL_TEST(vars, DVAR_DONT_RECYCLE)) break;
+ FL_SET(vars, DVAR_DONT_RECYCLE);
+ }
+ return th;
+}
+
+
/*
* call-seq:
* callcc {|cont| block } => obj
@@ -13099,37 +13301,14 @@
rb_callcc(self)
VALUE self;
{
- volatile VALUE cont;
- rb_thread_t th;
- volatile rb_thread_t th_save;
- struct tag *tag;
- struct RVarmap *vars;
-
- THREAD_ALLOC(th);
- /* must finish th initialization before any possible gc */
- th->thread = curr_thread->thread; /* brent@mbari.org */
- th->thgroup = cont_protect;
- cont = Data_Wrap_Struct(rb_cCont, cc_mark, thread_free, th);
-
- scope_dup(ruby_scope);
- for (tag=prot_tag; tag; tag=tag->prev) {
- if (tag->tag == PROT_THREAD) break;
- scope_dup(tag->scope);
- }
-
- for (vars = ruby_dyna_vars; vars; vars = vars->next) {
- if (FL_TEST(vars, DVAR_DONT_RECYCLE)) break;
- FL_SET(vars, DVAR_DONT_RECYCLE);
- }
- th_save = th;
- if (THREAD_SAVE_CONTEXT(th)) {
- return th_save->result;
- }
- else {
- return rb_yield(cont);
- }
+ rb_thread_t th = prep4callcc();
+ return THREAD_SAVE_CONTEXT(th) ?
+ th->result
+ :
+ rb_yield(Data_Wrap_Struct(rb_cCont, cc_mark, thread_free, th));
}
+
/*
* call-seq:
* cont.call(args, ...)
diff -rux '*.o' ruby-1.8.7-p72/version.h ruby-1.8.7-mbari/version.h
--- ruby-1.8.7-p72/version.h 2008-12-16 00:47:26.000000000 -0800
+++ ruby-1.8.7-mbari/version.h 2008-12-16 20:02:42.000000000 -0800
@@ -1,7 +1,7 @@
#define RUBY_VERSION "1.8.7"
-#define RUBY_RELEASE_DATE "2008-12-13"
+#define RUBY_RELEASE_DATE "2008-12-16"
#define RUBY_VERSION_CODE 187
-#define RUBY_RELEASE_CODE 20081213
+#define RUBY_RELEASE_CODE 20081216
#define RUBY_PATCHLEVEL 72
#define RUBY_VERSION_MAJOR 1
@@ -9,7 +9,7 @@
#define RUBY_VERSION_TEENY 7
#define RUBY_RELEASE_YEAR 2008
#define RUBY_RELEASE_MONTH 12
-#define RUBY_RELEASE_DAY 13
+#define RUBY_RELEASE_DAY 16
#ifdef RUBY_EXTERN
RUBY_EXTERN const char ruby_version[];
@@ -25,7 +25,7 @@
#define RUBY_BIRTH_MONTH 2
#define RUBY_BIRTH_DAY 24
-#define RUBY_RELEASE_STR "MBARI 3 on patchlevel"
+#define RUBY_RELEASE_STR "MBARI 4 on patchlevel"
#define RUBY_RELEASE_NUM RUBY_PATCHLEVEL