From 46603a78afde1386f92b38f9b16ca86daa93ad88 Mon Sep 17 00:00:00 2001 From: nobu Date: Thu, 5 Jul 2007 08:12:18 +0000 Subject: * include/ruby/{intern,ruby}.h, compile.[ch], error.c, eval.c, eval_load.c, gc.c, iseq.c, main.c, parse.y, re.c, ruby.c, yarvcore.[ch] (ruby_eval_tree, ruby_sourcefile, ruby_sourceline, ruby_nerrs): purge global variables. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12700 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 7 ++ compile.c | 265 +++++++++++++++++++++++++++----------------------- compile.h | 4 + error.c | 74 ++++++++------ eval.c | 61 +++++------- eval_load.c | 63 +++++------- gc.c | 26 +++-- include/ruby/intern.h | 8 +- include/ruby/ruby.h | 9 +- iseq.c | 24 +++-- main.c | 4 +- parse.y | 262 +++++++++++++++++++++++++------------------------ re.c | 70 ++++++++----- ruby.c | 80 +++++---------- yarvcore.c | 10 +- yarvcore.h | 2 +- 16 files changed, 497 insertions(+), 472 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4a8fc9ee7c..ea733b166a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +Thu Jul 5 17:12:16 2007 Nobuyoshi Nakada + + * include/ruby/{intern,ruby}.h, compile.[ch], error.c, eval.c, + eval_load.c, gc.c, iseq.c, main.c, parse.y, re.c, ruby.c, + yarvcore.[ch] (ruby_eval_tree, ruby_sourcefile, ruby_sourceline, + ruby_nerrs): purge global variables. + Thu Jul 5 16:37:34 2007 NAKAMURA Usaku * numeric.c (int_pow): fix previous nubu's commit. diff --git a/compile.c b/compile.c index 3b6a0edc5b..3e237e7f37 100644 --- a/compile.c +++ b/compile.c @@ -181,27 +181,29 @@ rb_iseq_compile(VALUE self, NODE *node) } } else { - if (iseq->type == ISEQ_TYPE_METHOD || - iseq->type == ISEQ_TYPE_CLASS || - iseq->type == ISEQ_TYPE_BLOCK || - iseq->type == ISEQ_TYPE_EVAL || - iseq->type == ISEQ_TYPE_TOP) { + switch (iseq->type) { + case ISEQ_TYPE_METHOD: + case ISEQ_TYPE_CLASS: + case ISEQ_TYPE_BLOCK: + case ISEQ_TYPE_EVAL: + case ISEQ_TYPE_TOP: dpn(node); - rb_bug("compile/should not be reached: %s:%d", __FILE__, __LINE__); - } - else if (iseq->type == ISEQ_TYPE_RESCUE) { + rb_compile_error(ERROR_ARGS "compile/should not be reached: %s:%d", + __FILE__, __LINE__); + break; + case ISEQ_TYPE_RESCUE: set_exception_tbl(iseq); COMPILE(ret, "rescue", node); - } - else if (iseq->type == ISEQ_TYPE_ENSURE) { + break; + case ISEQ_TYPE_ENSURE: set_exception_tbl(iseq); COMPILE_POPED(ret, "ensure", node); - } - else if (iseq->type == ISEQ_TYPE_DEFINED_GUARD) { + break; + case ISEQ_TYPE_DEFINED_GUARD: COMPILE(ret, "defined guard", node); - } - else { - rb_bug("unknown scope"); + break; + default: + rb_compile_error(ERROR_ARGS "unknown scope"); } } @@ -317,7 +319,8 @@ verify_list(char *info, LINK_ANCHOR *anchor) } if (flag != 0) { - rb_bug("list verify error: %08x (%s)", flag, info); + rb_compile_error(ERROR_ARGS "list verify error: %08x (%s)", + flag, info); } #endif } @@ -669,14 +672,14 @@ iseq_setup(rb_iseq_t *iseq, LINK_ANCHOR *anchor) debugs("[compile step 3.2 (iseq_insns_unification)]\n"); iseq_insns_unification(iseq, anchor); if (CPDEBUG > 5) - dump_disasm_list(FIRST_ELEMENT(anchor)); + dump_disasm_list(FIRST_ELEMENT(anchor)); } if (iseq->compile_data->option->stack_caching) { debugs("[compile step 3.3 (set_sequence_stackcaching)]\n"); set_sequence_stackcaching(iseq, anchor); if (CPDEBUG > 5) - dump_disasm_list(FIRST_ELEMENT(anchor)); + dump_disasm_list(FIRST_ELEMENT(anchor)); } debugs("[compile step 4.1 (set_sequence)]\n"); @@ -738,35 +741,31 @@ get_dyna_var_idx_at_raw(rb_iseq_t *iseq, ID id) } static int -get_local_var_idx(rb_iseq_t *iseq, ID id) +get_local_var_idx(rb_iseq_t *iseq, ID id, NODE *node) { int idx = get_dyna_var_idx_at_raw(iseq->local_iseq, id); if (idx == -1) { dpi(id); - rb_bug("get_local_var_idx: -1"); + rb_compile_error(ERROR_ARGS "get_local_var_idx: -1"); } return idx; } static int -get_dyna_var_idx(rb_iseq_t *iseq, ID id, int *level, int *ls) +get_dyna_var_idx(rb_iseq_t *iseq, ID id, int *level, int *ls, NODE *node) { int lv = 0, idx; - while (iseq) { - if ((idx = get_dyna_var_idx_at_raw(iseq, id)) >= 0) { - *level = lv; - *ls = iseq->local_size; - return idx; - } + while (iseq ? (idx = get_dyna_var_idx_at_raw(iseq, id)) < 0 : + (rb_compile_error(ERROR_ARGS "get_dyna_var_idx: -1"), 0)) { iseq = iseq->parent_iseq; lv++; } - - rb_bug("get_dyna_var_idx: -1"); - return -1; + *level = lv; + *ls = iseq->local_size; + return idx; } static int @@ -783,8 +782,9 @@ set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *optargs, NODE *node_args) NODE *node_init = 0; if (nd_type(node_args) != NODE_ARGS) { - rb_bug("set_arguments: NODE_ARGS is expected, but %s", - ruby_node_name(nd_type(node_args))); + NODE *node = node_args; + rb_compile_error(ERROR_ARGS "set_arguments: NODE_ARGS is expected, but %s", + ruby_node_name(nd_type(node_args))); } /* @@ -864,7 +864,8 @@ set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *optargs, NODE *node_args) iseq->arg_rest = get_dyna_var_idx_at_raw(iseq, rest_id); if (iseq->arg_rest == -1) { - rb_bug("arg_rest: -1"); + NODE *node = node_aux; + rb_compile_error(ERROR_ARGS "arg_rest: -1"); } if (iseq->arg_post_start == 0) { @@ -958,7 +959,7 @@ set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *anchor) LINK_ELEMENT *list; VALUE *generated_iseq; - int k, pos, sp, stack_max = 0; + int k, pos, sp, stack_max = 0, line = 0; /* set label position */ list = FIRST_ELEMENT(anchor); @@ -969,6 +970,7 @@ set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *anchor) { iobj = (INSN *)list; pos += insn_data_length(iobj); + line = iobj->line_no; k += 1; break; @@ -988,7 +990,8 @@ set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *anchor) default: dump_disasm_list(FIRST_ELEMENT(anchor)); dump_disasm_list(list); - rb_bug("error: set_sequence"); + rb_compile_error(RSTRING_PTR(iseq->filename), line, + "error: set_sequence"); break; } list = list->next; @@ -1032,8 +1035,9 @@ set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *anchor) /* operand check */ if (iobj->operand_size != len - 1) { dump_disasm_list(list); - rb_bug("operand size miss! (%d for %d)", - iobj->operand_size, len - 1); + rb_compile_error(RSTRING_PTR(iseq->filename), iobj->line_no, + "operand size miss! (%d for %d)", + iobj->operand_size, len - 1); return 0; } @@ -1046,7 +1050,9 @@ set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *anchor) /* label(destination position) */ lobj = (LABEL *)operands[j]; if (lobj->set != Qtrue) { - rb_bug("unknown label"); + rb_compile_error(RSTRING_PTR(iseq->filename), + iobj->line_no, + "unknown label"); } if (lobj->sp == -1) { lobj->sp = sp; @@ -1070,7 +1076,9 @@ set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *anchor) lobj = (LABEL *)(lv & ~1); if (lobj->set != Qtrue) { - rb_bug("unknown label"); + rb_compile_error(RSTRING_PTR(iseq->filename), + iobj->line_no, + "unknown label"); } rb_hash_aset(map, obj, INT2FIX(lobj->position - (pos+len))); @@ -1120,7 +1128,8 @@ set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *anchor) } break; default: - rb_bug("unknown operand type: %c", type); + rb_compile_error(RSTRING_PTR(iseq->filename), iobj->line_no, + "unknown operand type: %c", type); return 0; } } @@ -1602,7 +1611,7 @@ iseq_insns_unification(rb_iseq_t *iseq, LINK_ANCHOR *anchor) #include "opt_sc.inc" static int -insn_set_sc_state(INSN *iobj, int state) +insn_set_sc_state(rb_iseq_t *iseq, INSN *iobj, int state) { int nstate; int insn_id; @@ -1620,7 +1629,8 @@ insn_set_sc_state(INSN *iobj, int state) dump_disasm_list((LINK_ELEMENT *)iobj); dump_disasm_list((LINK_ELEMENT *)lobj); printf("\n-- %d, %d\n", lobj->sc_state, nstate); - rb_bug("insn_set_sc_state error\n"); + rb_compile_error(RSTRING_PTR(iseq->filename), iobj->lineno, + "insn_set_sc_state error\n"); return 0; } } @@ -1721,7 +1731,7 @@ set_sequence_stackcaching(rb_iseq_t *iseq, LINK_ANCHOR *anchor) case SCS_XX: goto normal_insn; default: - rb_bug("unreachable"); + rb_compile_error(ERROR_ARGS "unreachable"); } /* remove useless pop */ REMOVE_ELEM(list); @@ -1732,7 +1742,7 @@ set_sequence_stackcaching(rb_iseq_t *iseq, LINK_ANCHOR *anchor) /* none */ } /* end of switch */ normal_insn: - state = insn_set_sc_state(iobj, state); + state = insn_set_sc_state(iseq, iobj, state); break; } case ISEQ_ELEMENT_LABEL: @@ -1834,8 +1844,8 @@ compile_array_(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE* node_root, if (nd_type(node) != NODE_ZARRAY) { while (node) { if (nd_type(node) != NODE_ARRAY) { - rb_bug("compile_array: This node is not NODE_ARRAY, but %s", - ruby_node_name(nd_type(node))); + rb_compile_error(ERROR_ARGS "compile_array: This node is not NODE_ARRAY, but %s", + ruby_node_name(nd_type(node))); } i++; @@ -1848,8 +1858,10 @@ compile_array_(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE* node_root, } if (len != i) { - if (0) rb_bug("node error: compile_array (%d: %d-%d)", - (int)nd_line(node_root), len, i); + if (0) { + rb_compile_error(ERROR_ARGS "node error: compile_array (%d: %d-%d)", + (int)nd_line(node_root), len, i); + } len = i; } @@ -1884,13 +1896,15 @@ compile_array(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE* node_root, VALUE opt_p) static VALUE case_when_optimizable_literal(NODE * node) { - if (nd_type(node) == NODE_LIT) { + switch (nd_type(node)) { + case NODE_LIT: { VALUE v = node->nd_lit; if (SYMBOL_P(v) || rb_obj_is_kind_of(v, rb_cNumeric)) { return v; } - } - else if (nd_type(node) == NODE_STR) { + break; + } + case NODE_STR: return node->nd_lit; } return Qfalse; @@ -1984,11 +1998,13 @@ compile_massign(rb_iseq_t *iseq, LINK_ANCHOR *ret, int rlen = rhsn->nd_alen; int max = rlen > llen ? rlen : llen; int i, si = 0; + int rline = nd_line(rhsn); for (i = 0; i < max; i++) { if (i < rlen && i < llen) { /* a, b = c, d */ COMPILE(ret, "masgn val1", rhsn->nd_head); + rline = nd_line(rhsn); rhsn = rhsn->nd_next; } else if (i < rlen) { @@ -1998,6 +2014,7 @@ compile_massign(rb_iseq_t *iseq, LINK_ANCHOR *ret, si++; COMPILE(ret, "masgn rhs for lhs splat", rhsn->nd_head); + rline = nd_line(rhsn); rhsn = rhsn->nd_next; } break; @@ -2011,12 +2028,12 @@ compile_massign(rb_iseq_t *iseq, LINK_ANCHOR *ret, } else if (i < llen) { /* a, b, c = c, d */ - ADD_INSN(ret, 0, putnil); + ADD_INSN(ret, rline, putnil); } } if (lhs_splat) { - ADD_INSN1(ret, 0, newarray, INT2FIX(si)); + ADD_INSN1(ret, rline, newarray, INT2FIX(si)); } break; } @@ -2041,7 +2058,7 @@ compile_massign(rb_iseq_t *iseq, LINK_ANCHOR *ret, COMPILE(ret, "rhs to ary (splat/default)", rhsn); ADD_INSN2(ret, nd_line(rhsn), expandarray, INT2FIX(llen), INT2FIX(lhs_splat)); - /* rb_bug("unknown rhs: %s", ruby_node_name(nd_type(rhsn))); */ + /* rb_compile_error(ERROR_ARGS "unknown rhs: %s", ruby_node_name(nd_type(rhsn))); */ } } else { @@ -2051,8 +2068,8 @@ compile_massign(rb_iseq_t *iseq, LINK_ANCHOR *ret, if (lhs_splat) { if (nd_type(splatn) == NODE_POSTARG) { - int num = splatn->nd_2nd->nd_alen; NODE *n = splatn->nd_2nd; + int num = n->nd_alen; ADD_INSN (ret, nd_line(n), dup); ADD_INSN2(ret, nd_line(n), expandarray, INT2FIX(num), INT2FIX(2)); @@ -2116,7 +2133,7 @@ compile_colon2(rb_iseq_t *iseq, NODE * node, static int compile_cpath(LINK_ANCHOR *ret, rb_iseq_t *iseq, NODE *cpath) { - if(cpath->nd_head) { + if (cpath->nd_head) { COMPILE(ret, "nd_else->nd_head", cpath->nd_head); } else if (nd_type(cpath) == NODE_COLON2) { @@ -2170,7 +2187,7 @@ defined_expr(rb_iseq_t *iseq, LINK_ANCHOR *ret, ADD_INSNL(ret, nd_line(node), jump, lfinish); ADD_LABEL(ret, lcont); } - } while ((vals = vals->nd_next)); + } while ((vals = vals->nd_next) != NULL); } case NODE_STR: case NODE_LIT: @@ -2354,7 +2371,7 @@ defined_expr(rb_iseq_t *iseq, LINK_ANCHOR *ret, ADD_CATCH_ENTRY(CATCH_TYPE_ENSURE, lstart, lend, ensure, lfinish); return 1; - /* rb_bug("unimplemented defined: %s", ruby_node_name(nd_type(node))); */ + /* rb_compile_error(ERROR_ARGS "unimplemented defined: %s", ruby_node_name(nd_type(node))); */ } /* end of default */ } @@ -2377,26 +2394,18 @@ defined_expr(rb_iseq_t *iseq, LINK_ANCHOR *ret, static VALUE make_name_for_block(rb_iseq_t *iseq) { - char buf[BUFSIZE]; if (iseq->parent_iseq == 0) { - snprintf(buf, BUFSIZE, "block in %s", RSTRING_PTR(iseq->name)); + return rb_sprintf("block in %s", RSTRING_PTR(iseq->name)); } else { int level = 1; rb_iseq_t *ip = iseq; - while (1) { - if (ip->local_iseq != ip) { - ip = ip->parent_iseq; - } - else { - break; - } + while (ip->local_iseq != ip) { + ip = ip->parent_iseq; level++; } - snprintf(buf, BUFSIZE, "block (%d levels) in %s", level, - RSTRING_PTR(ip->name)); + return rb_sprintf("block (%d levels) in %s", level, RSTRING_PTR(ip->name)); } - return rb_str_new2(buf); } static void @@ -2504,7 +2513,9 @@ setup_args(rb_iseq_t *iseq, LINK_ANCHOR *args, NODE *argn, unsigned long *flag) break; } default: { - rb_bug("setup_arg: unknown node: %s\n", ruby_node_name(nd_type(argn))); + NODE *node = argn; + rb_compile_error(ERROR_ARGS "setup_arg: unknown node: %s\n", + ruby_node_name(nd_type(argn))); } } } @@ -2537,14 +2548,12 @@ setup_args(rb_iseq_t *iseq, LINK_ANCHOR *args, NODE *argn, unsigned long *flag) static int iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) { - int type; + enum node_type type; if (node == 0) { if (!poped) { - debug_node_start("NODE_NIL(implicit)"); - debug_node_end(); - ADD_INSN(ret, 0, putnil); - return COMPILE_OK; + debugs("node: NODE_NIL(implicit)\n"); + ADD_INSN(ret, iseq->compile_data->last_line, putnil); } return COMPILE_OK; } @@ -2617,7 +2626,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) type = nd_type(node); if (type != NODE_WHEN) { - COMPILE_ERROR(("NODE_CASE: unexpected node. must be NODE_WHEN, but %s", ruby_node_name(type))); + COMPILE_ERROR((ERROR_ARGS "NODE_CASE: unexpected node. must be NODE_WHEN, but %s", ruby_node_name(type))); } endlabel = NEW_LABEL(nd_line(node)); @@ -2653,11 +2662,12 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) ADD_INSNL(cond_seq, nd_line(val), branchif, l1); } else { - rb_bug("NODE_CASAE: unknown node (%s)", ruby_node_name(nd_type(vals))); + rb_compile_error(ERROR_ARGS "NODE_CASAE: unknown node (%s)", + ruby_node_name(nd_type(vals))); } } else { - rb_bug("NODE_CASAE: must be NODE_ARRAY, but 0\n"); + rb_compile_error(ERROR_ARGS "NODE_CASAE: must be NODE_ARRAY, but 0"); } node = node->nd_next; @@ -2741,7 +2751,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) ADD_INSNL(ret, nd_line(val), branchif, l1); } else { - rb_bug("err"); + rb_compile_error(ERROR_ARGS "err"); } node = node->nd_next; } @@ -2801,7 +2811,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) if (node->nd_state == Qundef) { /* ADD_INSN(ret, nd_line(node), putundef); */ - rb_bug("unsupported: putundef"); + rb_compile_error(ERROR_ARGS "unsupported: putundef"); } else { ADD_INSN(ret, nd_line(node), putnil); @@ -2881,7 +2891,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) INT2FIX(level | 0x02) /* TAG_BREAK */ ); } else if (iseq->type == ISEQ_TYPE_EVAL) { - COMPILE_ERROR(("Can't escape from eval with break")); + COMPILE_ERROR((ERROR_ARGS "Can't escape from eval with break")); } else { rb_iseq_t *ip = iseq->parent_iseq; @@ -2901,7 +2911,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) } ip = ip->parent_iseq; } - COMPILE_ERROR(("Illegal break")); + COMPILE_ERROR((ERROR_ARGS "Illegal break")); } break; } @@ -2920,7 +2930,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) iseq->compile_data->end_label); } else if (iseq->type == ISEQ_TYPE_EVAL) { - COMPILE_ERROR(("Can't escape from eval with next")); + COMPILE_ERROR((ERROR_ARGS "Can't escape from eval with next")); } else { rb_iseq_t *ip = iseq->parent_iseq; @@ -2942,7 +2952,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) INT2FIX(level | 0x03) /* TAG_NEXT */ ); } else { - COMPILE_ERROR(("Illegal next")); + COMPILE_ERROR((ERROR_ARGS "Illegal next")); } } break; @@ -2957,7 +2967,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) } } else if (iseq->type == ISEQ_TYPE_EVAL) { - COMPILE_ERROR(("Can't escape from eval with redo")); + COMPILE_ERROR((ERROR_ARGS "Can't escape from eval with redo")); } else if (iseq->compile_data->start_label) { ADD_INSNL(ret, nd_line(node), jump, @@ -2974,7 +2984,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) break; } else if (ip->type == ISEQ_TYPE_EVAL) { - COMPILE_ERROR(("Can't escape from eval with redo")); + COMPILE_ERROR((ERROR_ARGS "Can't escape from eval with redo")); } else if (ip->compile_data->redo_label != 0) { break; @@ -2987,7 +2997,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) INT2FIX(level | 0x05) /* TAG_REDO */ ); } else { - COMPILE_ERROR(("Illegal redo")); + COMPILE_ERROR((ERROR_ARGS "Illegal redo")); } } break; @@ -3000,7 +3010,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) INT2FIX(0x04) /* TAG_RETRY */ ); } else { - COMPILE_ERROR(("Illegal retry")); + COMPILE_ERROR((ERROR_ARGS "Illegal retry")); } break; } @@ -3158,7 +3168,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) case NODE_LASGN:{ ID id = node->nd_vid; - int idx = iseq->local_iseq->local_size - get_local_var_idx(iseq, id); + int idx = iseq->local_iseq->local_size - get_local_var_idx(iseq, id, node); debugs("lvar: %s idx: %d\n", rb_id2name(id), idx); COMPILE(ret, "rvalue", node->nd_value); @@ -3180,10 +3190,11 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) ADD_INSN(ret, nd_line(node), dup); } - idx = get_dyna_var_idx(iseq, node->nd_vid, &lv, &ls); + idx = get_dyna_var_idx(iseq, node->nd_vid, &lv, &ls, node); if (idx < 0) { - rb_bug("NODE_DASGN(_CURR): unknown id (%s)", rb_id2name(node->nd_vid)); + rb_compile_error(ERROR_ARGS "NODE_DASGN(_CURR): unknown id (%s)", + rb_id2name(node->nd_vid)); } ADD_INSN2(ret, nd_line(node), setdynamic, @@ -3492,7 +3503,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) } } else { - rb_bug("illegal goto/label format"); + rb_compile_error(ERROR_ARGS "illegal goto/label format"); } @@ -3666,7 +3677,8 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) break; default: - rb_bug("can't make hash with this node: %s", ruby_node_name(type)); + rb_compile_error(ERROR_ARGS "can't make hash with this node: %s", + ruby_node_name(type)); } ADD_INSN1(ret, nd_line(node), newhash, size); @@ -3681,7 +3693,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) while (is) { if (is->type == ISEQ_TYPE_TOP || is->type == ISEQ_TYPE_CLASS) { - COMPILE_ERROR(("Illegal return")); + COMPILE_ERROR((ERROR_ARGS "Illegal return")); break; } else { @@ -3712,7 +3724,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) unsigned long flag = 0; if (iseq->type == ISEQ_TYPE_TOP || iseq->type == ISEQ_TYPE_CLASS) { - COMPILE_ERROR(("Illegal yield")); + COMPILE_ERROR((ERROR_ARGS "Illegal yield")); } if (node->nd_head) { @@ -3733,7 +3745,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) case NODE_LVAR:{ if (!poped) { ID id = node->nd_vid; - int idx = iseq->local_iseq->local_size - get_local_var_idx(iseq, id); + int idx = iseq->local_iseq->local_size - get_local_var_idx(iseq, id, node); debugs("id: %s idx: %d\n", rb_id2name(id), idx); ADD_INSN1(ret, nd_line(node), getlocal, INT2FIX(idx)); @@ -3744,9 +3756,9 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) int lv, idx, ls; debugi("nd_vid", node->nd_vid); if (!poped) { - idx = get_dyna_var_idx(iseq, node->nd_vid, &lv, &ls); + idx = get_dyna_var_idx(iseq, node->nd_vid, &lv, &ls, node); if (idx < 0) { - rb_bug("unknown dvar (%s)", rb_id2name(node->nd_vid)); + rb_compile_error(ERROR_ARGS "unknown dvar (%s)", rb_id2name(node->nd_vid)); } ADD_INSN2(ret, nd_line(node), getdynamic, INT2FIX(ls - idx), INT2FIX(lv)); @@ -4001,7 +4013,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) if (nd_type(node->u1.node) != NODE_LIT || nd_type(node->u2.node) != NODE_LIT) { - rb_bug("alias args must be NODE_LIT"); + rb_compile_error(ERROR_ARGS "alias args must be NODE_LIT"); } s1 = node->u1.node->nd_lit; s2 = node->u2.node->nd_lit; @@ -4023,7 +4035,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) } case NODE_UNDEF:{ if (nd_type(node->u2.node) != NODE_LIT) { - rb_bug("undef args must be NODE_LIT"); + rb_compile_error(ERROR_ARGS "undef args must be NODE_LIT"); } ADD_INSN1(ret, nd_line(node), undef, ID2SYM(rb_to_id(node->u2.node->nd_lit))); @@ -4052,7 +4064,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) VALUE iseqval = NEW_CHILD_ISEQVAL( node->nd_body, rb_sprintf("", rb_id2name(node->nd_cpath->nd_mid)), - ISEQ_TYPE_CLASS); + ISEQ_TYPE_CLASS); COMPILE(ret, "mbase", node->nd_cpath->nd_head); ADD_INSN (ret, nd_line(node), putnil); /* dummy */ @@ -4347,7 +4359,8 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) break; } default: - rb_bug("iseq_compile_each: unknown node: %s", ruby_node_name(type)); + rb_compile_error(ERROR_ARGS "iseq_compile_each: unknown node: %s", + ruby_node_name(type)); return Qnil; } @@ -4381,10 +4394,8 @@ static VALUE insn_data_to_s_detail(INSN *iobj) { VALUE str = rb_str_new(0, 0); - char buff[0x100]; - snprintf(buff, sizeof(buff), "%-16s", insn_name(iobj->insn_id)); - rb_str_cat2(str, buff); + str = rb_sprintf("%-16s", insn_name(iobj->insn_id)); if (iobj->operands) { char *types = insn_op_types(iobj->insn_id); int j; @@ -4434,7 +4445,7 @@ insn_data_to_s_detail(INSN *iobj) rb_str_cat2(str, ""); break; default:{ - rb_bug("unknown operand type: %c", type); + rb_raise(rb_eSyntaxError, "unknown operand type: %c", type); } } if (types[j + 1]) { @@ -4479,8 +4490,7 @@ dump_disasm_list(struct iseq_link_element *link) } default: /* ignore */ - printf("%ld\n", FIX2LONG(link->type)); - rb_bug("dump_disasm_list error"); + rb_raise(rb_eSyntaxError, "dump_disasm_list error: %ld\n", FIX2LONG(link->type)); } link = link->next; } @@ -4536,7 +4546,8 @@ get_exception_sym2type(VALUE sym) if (sym == symBreak) return CATCH_TYPE_BREAK; if (sym == symRedo) return CATCH_TYPE_REDO; if (sym == symNext) return CATCH_TYPE_NEXT; - rb_bug("get_exception_sym2type"); + rb_raise(rb_eSyntaxError, "invalid exception symbol: %s", + RSTRING_PTR(rb_inspect(sym))); return 0; } @@ -4547,13 +4558,17 @@ iseq_build_exception(rb_iseq_t *iseq, struct st_table *labels_table, int i; for (i=0; ifilename), line_no, + "unknown instruction: %s", RSTRING_PTR(insn)); } if (argc != insn_len(insn_id)-1) { - rb_raise(rb_eRuntimeError, "operand size mismatch"); + rb_compile_error(RSTRING_PTR(iseq->filename), line_no, + "operand size mismatch"); } if (argc > 0) { @@ -4623,9 +4641,9 @@ iseq_build_body(rb_iseq_t *iseq, LINK_ANCHOR *anchor, VALUE op = rb_ary_entry(obj, j+1); switch (insn_op_type(insn_id, j)) { case TS_OFFSET: { - LABEL *label = register_label(iseq, labels_table, op); - argv[j] = (VALUE)label; - break; + LABEL *label = register_label(iseq, labels_table, op); + argv[j] = (VALUE)label; + break; } case TS_LINDEX: case TS_DINDEX: @@ -4646,7 +4664,7 @@ iseq_build_body(rb_iseq_t *iseq, LINK_ANCHOR *anchor, argv[j] = op; } else { - rb_raise(rb_eRuntimeError, "ISEQ is required"); + rb_raise(rb_eSyntaxError, "ISEQ is required"); } iseq_add_mark_object(iseq, argv[j]); } @@ -4681,7 +4699,7 @@ iseq_build_body(rb_iseq_t *iseq, LINK_ANCHOR *anchor, } break; default: - rb_bug("unknown operand: %c", insn_op_type(insn_id, j)); + rb_raise(rb_eSyntaxError, "unknown operand: %c", insn_op_type(insn_id, j)); } } } @@ -4725,7 +4743,8 @@ iseq_build_from_ary(rb_iseq_t *iseq, VALUE locals, VALUE args, iseq->local_size = opt + iseq->local_table_size; for (i=0; i 0 #define debugp(header, value) \ @@ -205,6 +207,8 @@ r_value(VALUE value) break; \ } +#define ERROR_ARGS (node)->nd_file, nd_line(node), + #define COMPILE_OK 1 #define COMPILE_NG 0 diff --git a/error.c b/error.c index d2b5a0ef71..4bdc028bd4 100644 --- a/error.c +++ b/error.c @@ -24,10 +24,9 @@ #endif extern const char ruby_version[], ruby_release_date[], ruby_platform[]; -int ruby_nerrs; static int -err_position_0(char *buf, long len, const char *file, long line) +err_position_0(char *buf, long len, const char *file, int line) { if (!file) { return 0; @@ -46,12 +45,6 @@ err_position(char *buf, long len) return err_position_0(buf, len, rb_sourcefile(), rb_sourceline()); } -static int -compile_position(char *buf, long len) -{ - return err_position_0(buf, len, rb_sourcefile(), rb_sourceline()); -} - static void err_snprintf(char *buf, long len, const char *fmt, va_list args) { @@ -64,11 +57,11 @@ err_snprintf(char *buf, long len, const char *fmt, va_list args) } static void -compile_snprintf(char *buf, long len, const char *fmt, va_list args) +compile_snprintf(char *buf, long len, const char *file, int line, const char *fmt, va_list args) { long n; - n = compile_position(buf, len); + n = err_position_0(buf, len, file, line); if (len > n) { vsnprintf((char*)buf+n, len-n, fmt, args); } @@ -77,16 +70,15 @@ compile_snprintf(char *buf, long len, const char *fmt, va_list args) static void err_append(const char*); void -rb_compile_error(const char *fmt, ...) +rb_compile_error(const char *file, int line, const char *fmt, ...) { va_list args; char buf[BUFSIZ]; va_start(args, fmt); - compile_snprintf(buf, BUFSIZ, fmt, args); + compile_snprintf(buf, BUFSIZ, file, line, fmt, args); va_end(args); err_append(buf); - ruby_nerrs++; } void @@ -102,19 +94,19 @@ rb_compile_error_append(const char *fmt, ...) } static void -compile_warn_print(const char *fmt, va_list args) +compile_warn_print(const char *file, int line, const char *fmt, va_list args) { char buf[BUFSIZ]; int len; - compile_snprintf(buf, BUFSIZ, fmt, args); + compile_snprintf(buf, BUFSIZ, file, line, fmt, args); len = strlen(buf); buf[len++] = '\n'; rb_write_error2(buf, len); } void -rb_compile_warn(const char *fmt, ...) +rb_compile_warn(const char *file, int line, const char *fmt, ...) { char buf[BUFSIZ]; va_list args; @@ -124,13 +116,13 @@ rb_compile_warn(const char *fmt, ...) snprintf(buf, BUFSIZ, "warning: %s", fmt); va_start(args, fmt); - compile_warn_print(buf, args); + compile_warn_print(file, line, buf, args); va_end(args); } /* rb_compile_warning() reports only in verbose mode */ void -rb_compile_warning(const char *fmt, ...) +rb_compile_warning(const char *file, int line, const char *fmt, ...) { char buf[BUFSIZ]; va_list args; @@ -140,7 +132,7 @@ rb_compile_warning(const char *fmt, ...) snprintf(buf, BUFSIZ, "warning: %s", fmt); va_start(args, fmt); - compile_warn_print(buf, args); + compile_warn_print(file, line, buf, args); va_end(args); } @@ -207,24 +199,43 @@ rb_warn_m(VALUE self, VALUE mesg) void yarv_bug(void); -void -rb_bug(const char *fmt, ...) +static void +report_bug(const char *file, int line, const char *fmt, va_list args) { char buf[BUFSIZ]; - va_list args; FILE *out = stderr; - int len = err_position(buf, BUFSIZ); + int len = err_position_0(buf, BUFSIZ, file, line); if (fwrite(buf, 1, len, out) == len || fwrite(buf, 1, len, (out = stdout)) == len) { yarv_bug(); fputs("[BUG] ", out); - va_start(args, fmt); vfprintf(out, fmt, args); - va_end(args); fprintf(out, "\nruby %s (%s) [%s]\n\n", ruby_version, ruby_release_date, ruby_platform); } +} + +void +rb_bug(const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + report_bug(rb_sourcefile(), rb_sourceline(), fmt, args); + va_end(args); + + abort(); +} + +void +rb_compile_bug(const char *file, int line, const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + report_bug(file, line, fmt, args); + va_end(args); abort(); } @@ -1531,12 +1542,15 @@ static void err_append(const char *s) { rb_thread_t *th = GET_THREAD(); + VALUE err = th->errinfo; + if (th->parse_in_eval) { - if (NIL_P(th->errinfo)) { - th->errinfo = rb_exc_new2(rb_eSyntaxError, s); + if (!RTEST(err)) { + err = rb_exc_new2(rb_eSyntaxError, s); + th->errinfo = err; } else { - VALUE str = rb_obj_as_string(GET_THREAD()->errinfo); + VALUE str = rb_obj_as_string(err); rb_str_cat2(str, "\n"); rb_str_cat2(str, s); @@ -1544,6 +1558,10 @@ err_append(const char *s) } } else { + if (!RTEST(err)) { + err = rb_exc_new2(rb_eSyntaxError, "compile error"); + th->errinfo = err; + } rb_write_error(s); rb_write_error("\n"); } diff --git a/eval.c b/eval.c index 48d6449404..ffe297e5a2 100644 --- a/eval.c +++ b/eval.c @@ -32,7 +32,6 @@ VALUE rb_eSysStackError; VALUE exception_error; VALUE sysstack_error; -extern int ruby_nerrs; extern VALUE ruby_top_self; static VALUE eval(VALUE, VALUE, VALUE, const char *, int); @@ -108,21 +107,23 @@ ruby_init(void) ruby_running = 1; } -void +void * ruby_options(int argc, char **argv) { int state; + void *tree = 0; Init_stack((void *)&state); PUSH_TAG(); if ((state = EXEC_TAG()) == 0) { - SAVE_ROOT_JMPBUF(GET_THREAD(), ruby_process_options(argc, argv)); + SAVE_ROOT_JMPBUF(GET_THREAD(), tree = ruby_process_options(argc, argv)); } else { rb_clear_trace_func(); exit(error_handle(state)); } POP_TAG(); + return tree; } static void @@ -212,65 +213,47 @@ ruby_cleanup(int ex) return ex; } -extern NODE *ruby_eval_tree; - -static int -ruby_exec_internal(void) +int +ruby_exec_node(void *n) { int state; VALUE val; + NODE *node = n; rb_thread_t *th = GET_THREAD(); - if (!ruby_eval_tree) return 0; + if (!node) return 0; PUSH_TAG(); if ((state = EXEC_TAG()) == 0) { SAVE_ROOT_JMPBUF(th, { th->base_block = 0; - val = yarvcore_eval_parsed(ruby_eval_tree, rb_str_new2(ruby_sourcefile)); + val = yarvcore_eval_parsed(node, rb_str_new2(node->nd_file)); }); } POP_TAG(); return state; } -int -ruby_exec(void) -{ - volatile NODE *tmp; - - Init_stack((void *)&tmp); - return ruby_exec_internal(); -} - void ruby_stop(int ex) { exit(ruby_cleanup(ex)); } -void -ruby_run(void) +int +ruby_run_node(void *n) { - int state; - static int ex; - - if (ruby_nerrs > 0) { - exit(EXIT_FAILURE); + if (!n) { + return EXIT_FAILURE; } - - state = ruby_exec(); - - if (state && !ex) { - ex = state; - } - ruby_stop(ex); + Init_stack((void *)&n); + return ruby_cleanup(ruby_exec_node(n)); } VALUE rb_eval_string(const char *str) { - return eval(ruby_top_self, rb_str_new2(str), Qnil, "(eval)", 0); + return eval(ruby_top_self, rb_str_new2(str), Qnil, "(eval)", 1); } VALUE @@ -662,6 +645,8 @@ rb_longjmp(int tag, VALUE mesg) { VALUE at; rb_thread_t *th = GET_THREAD(); + const char *file; + int line = 0; if (thread_set_raised(th)) { th->errinfo = exception_error; @@ -674,7 +659,9 @@ rb_longjmp(int tag, VALUE mesg) mesg = rb_exc_new(rb_eRuntimeError, 0, 0); } - if (ruby_sourcefile && !NIL_P(mesg)) { + file = rb_sourcefile(); + if (file) line = rb_sourceline(); + if (file && !NIL_P(mesg)) { at = get_backtrace(mesg); if (NIL_P(at)) { at = make_backtrace(); @@ -695,7 +682,7 @@ rb_longjmp(int tag, VALUE mesg) e = rb_obj_as_string(e); warn_printf("Exception `%s' at %s:%d - %s\n", rb_obj_classname(GET_THREAD()->errinfo), - rb_sourcefile(), rb_sourceline(), RSTRING_PTR(e)); + file, line, RSTRING_PTR(e)); } POP_TAG(); if (status == TAG_FATAL && GET_THREAD()->errinfo == exception_error) { @@ -1105,7 +1092,7 @@ rb_rescue2(VALUE (*b_proc) (ANYARGS), VALUE data1, VALUE (*r_proc) (ANYARGS), VALUE eclass; va_init_list(args, data2); - while (eclass = va_arg(args, VALUE)) { + while ((eclass = va_arg(args, VALUE)) != 0) { if (rb_obj_is_kind_of(th->errinfo, eclass)) { handle = Qtrue; break; @@ -2662,8 +2649,6 @@ Init_eval(void) __send = rb_intern("__send"); __send_bang = rb_intern("__send!"); - rb_global_variable((VALUE *)&ruby_eval_tree); - rb_define_virtual_variable("$@", errat_getter, errat_setter); rb_define_virtual_variable("$!", errinfo_getter, errinfo_setter); diff --git a/eval_load.c b/eval_load.c index 49a4afaa8c..3974513b16 100644 --- a/eval_load.c +++ b/eval_load.c @@ -130,33 +130,6 @@ VALUE rb_load_path; NORETURN(static void load_failed _((VALUE))); -RUBY_EXTERN NODE *ruby_eval_tree; - -static VALUE -rb_load_internal(char *file) -{ - NODE *node; - VALUE iseq; - rb_thread_t *th = GET_THREAD(); - - { - th->parse_in_eval++; - node = (NODE *)rb_load_file(file); - th->parse_in_eval--; - node = ruby_eval_tree; - } - - if (ruby_nerrs > 0) { - return 0; - } - - iseq = rb_iseq_new(node, rb_str_new2(""), - rb_str_new2(file), Qfalse, ISEQ_TYPE_TOP); - - rb_thread_eval(GET_THREAD(), iseq); - return 0; -} - void rb_load(VALUE fname, int wrap) { @@ -165,6 +138,8 @@ rb_load(VALUE fname, int wrap) rb_thread_t *th = GET_THREAD(); VALUE wrapper = th->top_wrapper; VALUE self = th->top_self; + volatile int parse_in_eval; + volatile int loaded = Qfalse; FilePathValue(fname); fname = rb_str_new4(fname); @@ -172,7 +147,7 @@ rb_load(VALUE fname, int wrap) if (!tmp) { load_failed(fname); } - fname = tmp; + RB_GC_GUARD(fname) = rb_str_new4(tmp); th->errinfo = Qnil; /* ensure */ @@ -187,18 +162,28 @@ rb_load(VALUE fname, int wrap) rb_extend_object(th->top_self, th->top_wrapper); } + parse_in_eval = th->parse_in_eval; PUSH_TAG(); state = EXEC_TAG(); if (state == 0) { - rb_load_internal(RSTRING_PTR(fname)); + NODE *node; + VALUE iseq; + + th->parse_in_eval++; + node = (NODE *)rb_load_file(RSTRING_PTR(fname)); + th->parse_in_eval--; + loaded = Qtrue; + iseq = rb_iseq_new(node, rb_str_new2(""), + fname, Qfalse, ISEQ_TYPE_TOP); + rb_thread_eval(th, iseq); } POP_TAG(); + th->parse_in_eval = parse_in_eval; th->top_self = self; th->top_wrapper = wrapper; - if (ruby_nerrs > 0) { - ruby_nerrs = 0; + if (!loaded) { rb_exc_raise(GET_THREAD()->errinfo); } if (state) { @@ -318,7 +303,7 @@ rb_f_require(VALUE obj, VALUE fname) } static int -search_required(VALUE fname, VALUE *path) +search_required(VALUE fname, volatile VALUE *path) { VALUE tmp; char *ext, *ftptr; @@ -330,7 +315,7 @@ search_required(VALUE fname, VALUE *path) if (strcmp(".rb", ext) == 0) { if (rb_feature_p(ftptr, ext, Qtrue)) return 'r'; - if (tmp = rb_find_file(fname)) { + if ((tmp = rb_find_file(fname)) != 0) { tmp = rb_file_expand_path(tmp, Qnil); ext = strrchr(ftptr = RSTRING_PTR(tmp), '.'); if (!rb_feature_p(ftptr, ext, Qtrue)) @@ -355,7 +340,7 @@ search_required(VALUE fname, VALUE *path) #else rb_str_cat2(tmp, DLEXT); OBJ_FREEZE(tmp); - if (tmp = rb_find_file(tmp)) { + if ((tmp = rb_find_file(tmp)) != 0) { tmp = rb_file_expand_path(tmp, Qnil); ext = strrchr(ftptr = RSTRING_PTR(tmp), '.'); if (!rb_feature_p(ftptr, ext, Qfalse)) @@ -367,7 +352,7 @@ search_required(VALUE fname, VALUE *path) else if (IS_DLEXT(ext)) { if (rb_feature_p(ftptr, ext, Qfalse)) return 's'; - if (tmp = rb_find_file(fname)) { + if ((tmp = rb_find_file(fname)) != 0) { tmp = rb_file_expand_path(tmp, Qnil); ext = strrchr(ftptr = RSTRING_PTR(tmp), '.'); if (!rb_feature_p(ftptr, ext, Qfalse)) @@ -450,8 +435,6 @@ rb_require_safe(VALUE fname, int safe) break; case 's': - ruby_sourcefile = rb_source_filename(RSTRING_PTR(path)); - ruby_sourceline = 0; handle = (long)rb_vm_call_cfunc(ruby_top_self, load_ext, path, 0, path); rb_ary_push(ruby_dln_librefs, LONG2NUM(handle)); @@ -498,11 +481,9 @@ init_ext_call(VALUE arg) void ruby_init_ext(const char *name, void (*init)(void)) { - ruby_sourcefile = rb_source_filename(name); - ruby_sourceline = 0; - if (load_lock(name)) { - rb_vm_call_cfunc(ruby_top_self, init_ext_call, (VALUE)init, 0, rb_str_new2(name)); + rb_vm_call_cfunc(ruby_top_self, init_ext_call, (VALUE)init, + 0, rb_str_new2(name)); rb_provide(name); load_unlock(name); } diff --git a/gc.c b/gc.c index a21ced7bd9..d596d10735 100644 --- a/gc.c +++ b/gc.c @@ -529,6 +529,21 @@ rb_newobj(void) #endif } +NODE* +rb_node_newnode(enum node_type type, VALUE a0, VALUE a1, VALUE a2) +{ + NODE *n = (NODE*)rb_newobj(); + + n->flags |= T_NODE; + nd_set_type(n, type); + + n->u1.value = a0; + n->u2.value = a1; + n->u3.value = a2; + + return n; +} + VALUE rb_data_object_alloc(VALUE klass, void *datap, RUBY_DATA_FUNC dmark, RUBY_DATA_FUNC dfree) { @@ -634,8 +649,8 @@ rb_source_filename(const char *f) return (char *)name + 1; } -static void -mark_source_filename(char *f) +void +rb_mark_source_filename(char *f) { if (f) { f[-1] = 1; @@ -843,7 +858,7 @@ gc_mark_children(VALUE ptr, int lev) break; case T_NODE: - mark_source_filename(obj->as.node.nd_file); + rb_mark_source_filename(obj->as.node.nd_file); switch (nd_type(obj)) { case NODE_IF: /* 1,2,3 */ case NODE_FOR: @@ -1119,7 +1134,6 @@ gc_sweep(void) if (free_min < FREE_MIN) free_min = FREE_MIN; - mark_source_filename(ruby_sourcefile); if (source_filenames) { st_foreach(source_filenames, sweep_source_filename, 0); } @@ -1426,8 +1440,8 @@ garbage_collect(void) rb_gc_mark_parser(); /* gc_mark objects whose marking are not completed*/ - while (!MARK_STACK_EMPTY){ - if (mark_stack_overflow){ + while (!MARK_STACK_EMPTY) { + if (mark_stack_overflow) { gc_mark_all(); } else { diff --git a/include/ruby/intern.h b/include/ruby/intern.h index 9c597f0f64..77663fd5f0 100644 --- a/include/ruby/intern.h +++ b/include/ruby/intern.h @@ -160,14 +160,13 @@ VALUE rb_enumeratorize(VALUE, VALUE, int, VALUE *); argc, argv); \ } while (0) /* error.c */ -RUBY_EXTERN int ruby_nerrs; VALUE rb_exc_new(VALUE, const char*, long); VALUE rb_exc_new2(VALUE, const char*); VALUE rb_exc_new3(VALUE, VALUE); PRINTF_ARGS(NORETURN(void rb_loaderror(const char*, ...)), 1, 2); PRINTF_ARGS(NORETURN(void rb_name_error(ID, const char*, ...)), 2, 3); NORETURN(void rb_invalid_str(const char*, const char*)); -PRINTF_ARGS(void rb_compile_error(const char*, ...), 1, 2); +PRINTF_ARGS(void rb_compile_error(const char*, int, const char*, ...), 3, 4); PRINTF_ARGS(void rb_compile_error_append(const char*, ...), 1, 2); NORETURN(void rb_load_fail(const char*)); NORETURN(void rb_error_frozen(const char*)); @@ -454,7 +453,7 @@ VALUE rb_reg_match_pre(VALUE); VALUE rb_reg_match_post(VALUE); VALUE rb_reg_match_last(VALUE); VALUE rb_reg_new(const char*, long, int); -VALUE rb_reg_compile(const char*, long, int); +VALUE rb_reg_compile(const char*, long, int, const char*, int); VALUE rb_reg_match(VALUE, VALUE); VALUE rb_reg_match2(VALUE); int rb_reg_options(VALUE); @@ -467,8 +466,7 @@ void *rb_load_file(const char*); void ruby_script(const char*); void ruby_prog_init(void); void ruby_set_argv(int, char**); -void ruby_process_options(int, char**); -void ruby_load_script(void); +void *ruby_process_options(int, char**); void ruby_init_loadpath(void); void ruby_incpush(const char*); /* signal.c */ diff --git a/include/ruby/ruby.h b/include/ruby/ruby.h index e6c16e82bb..059c145265 100644 --- a/include/ruby/ruby.h +++ b/include/ruby/ruby.h @@ -299,6 +299,8 @@ enum ruby_value_type { #define TYPE(x) rb_type((VALUE)(x)) +#define RB_GC_GUARD(v) (*(volatile VALUE *)&(v)) + void rb_check_type(VALUE,int); #define Check_Type(v,t) rb_check_type((VALUE)(v),t) @@ -701,11 +703,11 @@ NORETURN(void rb_notimplement(void)); /* reports if `-w' specified */ PRINTF_ARGS(void rb_warning(const char*, ...), 1, 2); -PRINTF_ARGS(void rb_compile_warning(const char*, ...), 1, 2); +PRINTF_ARGS(void rb_compile_warning(const char *, int, const char*, ...), 3, 4); PRINTF_ARGS(void rb_sys_warning(const char*, ...), 1, 2); /* reports always */ PRINTF_ARGS(void rb_warn(const char*, ...), 1, 2); -PRINTF_ARGS(void rb_compile_warn(const char*, ...), 1, 2); +PRINTF_ARGS(void rb_compile_warn(const char *, int, const char*, ...), 3, 4); VALUE rb_each(VALUE); VALUE rb_yield(VALUE); @@ -735,7 +737,8 @@ void ruby_init_stack(VALUE*); ruby_init_stack(&variable_in_this_stack_frame); #endif void ruby_init(void); -void ruby_options(int, char**); +void *ruby_options(int, char**); +int ruby_run_node(void *); NORETURN(void ruby_run(void)); RUBY_EXTERN VALUE rb_mKernel; diff --git a/iseq.c b/iseq.c index 7e1b40c5fb..55ff9952b3 100644 --- a/iseq.c +++ b/iseq.c @@ -192,13 +192,13 @@ static VALUE cleanup_iseq_build(rb_iseq_t *iseq) { struct iseq_compile_data *data = iseq->compile_data; + VALUE err = data->err_info; iseq->compile_data = 0; compile_data_free(data); - if (ruby_nerrs > 0) { - VALUE str = rb_str_buf_new2("compile error"); - ruby_nerrs = 0; - rb_exc_raise(rb_exc_new3(rb_eSyntaxError, str)); + if (RTEST(err)) { + rb_funcall2(err, rb_intern("set_backtrace"), 1, &iseq->filename); + rb_exc_raise(err); } return Qtrue; } @@ -375,7 +375,11 @@ iseq_load(VALUE self, VALUE data, VALUE parent, VALUE opt) } if (st_lookup(type_map, type, &iseq_type) == 0) { - rb_raise(rb_eTypeError, "unsupport type: %p", type); + const char *typename = rb_id2name(type); + if (typename) + rb_raise(rb_eTypeError, "unsupport type: :%s", typename); + else + rb_raise(rb_eTypeError, "unsupport type: %p", (void *)type); } if (parent == Qnil) { @@ -404,11 +408,11 @@ iseq_s_load(int argc, VALUE *argv, VALUE self) static NODE * compile_string(VALUE str, VALUE file, VALUE line) { - NODE *node; - node = rb_compile_string(StringValueCStr(file), str, NUM2INT(line)); + VALUE parser = rb_parser_new(); + NODE *node = rb_parser_compile_string(parser, StringValueCStr(file), + str, NUM2INT(line)); - if (ruby_nerrs > 0) { - ruby_nerrs = 0; + if (!node) { rb_exc_raise(GET_THREAD()->errinfo); /* TODO: check err */ } return node; @@ -822,7 +826,7 @@ ruby_iseq_disasm(VALUE self) return str; } -char * +const char * ruby_node_name(int node) { switch (node) { diff --git a/main.c b/main.c index 24fbc2e9f3..09c0bdb8bf 100644 --- a/main.c +++ b/main.c @@ -43,8 +43,6 @@ main(int argc, char **argv, char **envp) { RUBY_INIT_STACK; ruby_init(); - ruby_options(argc, argv); - ruby_run(); + return ruby_run_node(ruby_options(argc, argv)); } - return 0; } diff --git a/parse.y b/parse.y index c1b74fa074..deb86f5d07 100644 --- a/parse.y +++ b/parse.y @@ -58,11 +58,6 @@ ((id)&ID_SCOPE_MASK) == ID_INSTANCE || \ ((id)&ID_SCOPE_MASK) == ID_CLASS)) -#ifndef RIPPER -char *ruby_sourcefile; /* current source file */ -int ruby_sourceline; /* current line no. */ -#endif - enum lex_state_e { EXPR_BEG, /* ignore newline, +/- is a sign. */ EXPR_END, /* newline significant, +/- is a operator. */ @@ -238,15 +233,17 @@ struct parser_params { int parser_ruby__end__seen; int line_count; int has_shebang; + int parser_ruby_sourceline; /* current line no. */ #ifndef RIPPER /* Ruby core only */ + char *parser_ruby_sourcefile; /* current source file */ NODE *parser_eval_tree_begin; NODE *parser_eval_tree; VALUE debug_lines; + int nerr; #else /* Ripper only */ - int parser_ruby_sourceline; VALUE parser_ruby_sourcefile; const char *tokp; VALUE delayed; @@ -302,9 +299,9 @@ static int parser_yyerror(struct parser_params*, const char*); #define lex_gets (parser->parser_lex_gets) #define lvtbl (parser->parser_lvtbl) #define ruby__end__seen (parser->parser_ruby__end__seen) -#ifdef RIPPER #define ruby_sourceline (parser->parser_ruby_sourceline) #define ruby_sourcefile (parser->parser_ruby_sourcefile) +#ifdef RIPPER #else #define ruby_debug_lines (parser->debug_lines) #endif @@ -315,6 +312,9 @@ static int yylex(void*, void*); #define yyparse ruby_yyparse #define yydebug ruby_yydebug +static NODE* node_newnode(struct parser_params *, enum node_type, VALUE, VALUE, VALUE); +#define rb_node_newnode(type, a1, a2, a3) node_newnode(parser, type, a1, a2, a3) + static NODE *cond_gen(struct parser_params*,NODE*); #define cond(node) cond_gen(parser, node) static NODE *logop_gen(struct parser_params*,enum node_type,NODE*,NODE*); @@ -332,17 +332,27 @@ static NODE *remove_begin(NODE*); #define void_expr(node) void_expr_gen(parser, (node) = remove_begin(node)) static void void_stmts_gen(struct parser_params*,NODE*); #define void_stmts(node) void_stmts_gen(parser, node) -static void reduce_nodes(NODE**); -static void block_dup_check(NODE*,NODE*); - -static NODE *block_append(NODE*,NODE*); -static NODE *list_append(NODE*,NODE*); -static NODE *list_concat(NODE*,NODE*); -static NODE *arg_append(NODE*,NODE*); -static NODE *arg_concat(NODE*,NODE*); -static NODE *literal_concat(NODE*,NODE*); -static NODE *new_evstr(NODE*); -static NODE *evstr2dstr(NODE*); +static void reduce_nodes_gen(struct parser_params*,NODE**); +#define reduce_nodes(n) reduce_nodes_gen(parser,n) +static void block_dup_check_gen(struct parser_params*,NODE*,NODE*); +#define block_dup_check(n1,n2) block_dup_check_gen(parser,n1,n2) + +static NODE *block_append_gen(struct parser_params*,NODE*,NODE*); +#define block_append(h,t) block_append_gen(parser,h,t) +static NODE *list_append_gen(struct parser_params*,NODE*,NODE*); +#define list_append(l,i) list_append_gen(parser,l,i) +static NODE *list_concat_gen(struct parser_params*,NODE*,NODE*); +#define list_concat(h,t) list_concat_gen(parser,h,t) +static NODE *arg_append_gen(struct parser_params*,NODE*,NODE*); +#define arg_append(h,t) arg_append_gen(parser,h,t) +static NODE *arg_concat_gen(struct parser_params*,NODE*,NODE*); +#define arg_concat(h,t) arg_concat_gen(parser,h,t) +static NODE *literal_concat_gen(struct parser_params*,NODE*,NODE*); +#define literal_concat(h,t) literal_concat_gen(parser,h,t) +static NODE *new_evstr_gen(struct parser_params*,NODE*); +#define new_evstr(n) new_evstr_gen(parser,n) +static NODE *evstr2dstr_gen(struct parser_params*,NODE*); +#define evstr2dstr(n) evstr2dstr_gen(parser,n) static NODE *call_op_gen(struct parser_params*,NODE*,ID,int,NODE*); #define call_op(recv,id,narg,arg1) call_op_gen(parser, recv,id,narg,arg1) @@ -353,9 +363,11 @@ static void shadowing_lvar_gen(struct parser_params*,ID); #define shadowing_lvar(name) shadowing_lvar_gen(parser, name) static NODE *negate_lit(NODE*); -static NODE *ret_args(NODE*); +static NODE *ret_args_gen(struct parser_params*,NODE*); +#define ret_args(node) ret_args_gen(parser, node) static NODE *arg_blk_pass(NODE*,NODE*); -static NODE *new_yield(NODE*); +static NODE *new_yield_gen(struct parser_params*,NODE*); +#define new_yield(node) new_yield_gen(parser, node) static NODE *gettable_gen(struct parser_params*,ID); #define gettable(id) gettable_gen(parser,id) @@ -368,7 +380,8 @@ static NODE *aryset_gen(struct parser_params*,NODE*,NODE*); static NODE *attrset_gen(struct parser_params*,NODE*,ID); #define attrset(node,id) attrset_gen(parser, node, id) -static void rb_backref_error(NODE*); +static void rb_backref_error_gen(struct parser_params*,NODE*); +#define rb_backref_error(n) rb_backref_error_gen(parser,n) static NODE *node_assign_gen(struct parser_params*,NODE*,NODE*); #define node_assign(node1, node2) node_assign_gen(parser, node1, node2) @@ -492,11 +505,11 @@ static VALUE ripper_id2sym(ID); #endif #ifndef RIPPER -# define rb_warn0(fmt) rb_compile_warn(fmt) -# define rb_warnI(fmt,a) rb_compile_warn(fmt,a) -# define rb_warnS(fmt,a) rb_compile_warn(fmt,a) -# define rb_warning0(fmt) rb_compile_warning(fmt) -# define rb_warningS(fmt,a) rb_compile_warning(fmt,a) +# define rb_warn0(fmt) rb_compile_warn(ruby_sourcefile, ruby_sourceline, fmt) +# define rb_warnI(fmt,a) rb_compile_warn(ruby_sourcefile, ruby_sourceline, fmt, a) +# define rb_warnS(fmt,a) rb_compile_warn(ruby_sourcefile, ruby_sourceline, fmt, a) +# define rb_warning0(fmt) rb_compile_warning(ruby_sourcefile, ruby_sourceline, fmt) +# define rb_warningS(fmt,a) rb_compile_warning(ruby_sourcefile, ruby_sourceline, fmt, a) #else # define rb_warn0(fmt) ripper_warn0(parser, fmt) # define rb_warnI(fmt,a) ripper_warnI(parser, fmt, a) @@ -516,8 +529,8 @@ static void ripper_compile_error(struct parser_params*, const char *fmt, ...); # define compile_error ripper_compile_error # define PARSER_ARG parser, #else -# define compile_error rb_compile_error -# define PARSER_ARG +# define compile_error parser->nerr++,rb_compile_error +# define PARSER_ARG ruby_sourcefile, ruby_sourceline, #endif #ifdef RIPPER @@ -772,7 +785,7 @@ compstmt : stmts opt_terms stmts : none { /*%%%*/ - $$ = NEW_NIL(); + $$ = NEW_BEGIN(0); /*% $$ = dispatch2(stmts_add, dispatch0(stmts_new), dispatch0(void_stmt)); @@ -3603,7 +3616,8 @@ regexp : tREGEXP_BEG xstring_contents tREGEXP_END int options = $3; NODE *node = $2; if (!node) { - node = NEW_LIT(rb_reg_compile("", 0, options & ~RE_OPTION_ONCE)); + node = NEW_LIT(rb_reg_compile("", 0, options & ~RE_OPTION_ONCE, + ruby_sourcefile, ruby_sourceline)); } else switch (nd_type(node)) { case NODE_STR: @@ -3612,7 +3626,8 @@ regexp : tREGEXP_BEG xstring_contents tREGEXP_END nd_set_type(node, NODE_LIT); node->nd_lit = rb_reg_compile(RSTRING_PTR(src), RSTRING_LEN(src), - options & ~RE_OPTION_ONCE); + options & ~RE_OPTION_ONCE, + ruby_sourcefile, ruby_sourceline); } break; default: @@ -4295,7 +4310,7 @@ singleton : var_ref { /*%%%*/ $$ = $1; - value_expr($$); + value_expr($1); /*% $$ = $1; %*/ @@ -4542,7 +4557,7 @@ parser_yyerror(struct parser_params *parser, const char *msg) char *buf; int len, i; - rb_compile_error("%s", msg); + compile_error(PARSER_ARG "%s", msg); p = lex_p; while (lex_pbeg <= p) { if (*p == '\n') break; @@ -4609,6 +4624,7 @@ yycompile(struct parser_params *parser, const char *f, int line) { int n; const char *kcode_save; + NODE *tree; if (!compile_for_eval && rb_safe_level() == 0) { ruby_debug_lines = ruby_suppress_tracing(debug_lines, (VALUE)f); @@ -4631,14 +4647,17 @@ yycompile(struct parser_params *parser, const char *f, int line) rb_set_kcode(kcode_save); lex_strterm = 0; - if (ruby_eval_tree_begin) { - NODE *scope = ruby_eval_tree; - scope->nd_body = NEW_PRELUDE(ruby_eval_tree_begin, scope->nd_body); - return scope; + if (parser->nerr) { + return 0; } - else { - return ruby_eval_tree; + tree = ruby_eval_tree; + if (!tree) { + tree = NEW_NIL(); + } + if (ruby_eval_tree_begin) { + tree->nd_body = NEW_PRELUDE(ruby_eval_tree_begin, tree->nd_body); } + return tree; } #endif /* !RIPPER */ @@ -5058,7 +5077,7 @@ parser_regx_options(struct parser_params *parser) if (toklen()) { tokfix(); compile_error(PARSER_ARG "unknown regexp option%s - %s", - toklen() > 1 ? "s" : "", tok()); + toklen() > 1 ? "s" : "", tok()); } return options | kcode; } @@ -5163,7 +5182,7 @@ parser_tokadd_string(struct parser_params *parser, } if (!c && (func & STR_FUNC_SYMBOL)) { func &= ~STR_FUNC_SYMBOL; - rb_compile_error(PARSER_ARG "symbol cannot contain '\\0'"); + compile_error(PARSER_ARG "symbol cannot contain '\\0'"); continue; } tokadd(c); @@ -5171,20 +5190,8 @@ parser_tokadd_string(struct parser_params *parser, return c; } -#define NEW_STRTERM0(func, term, paren) \ +#define NEW_STRTERM(func, term, paren) \ rb_node_newnode(NODE_STRTERM, (func), (term) | ((paren) << (CHAR_BIT * 2)), 0) -#ifndef RIPPER -# define NEW_STRTERM(func, term, paren) NEW_STRTERM0(func, term, paren) -#else -# define NEW_STRTERM(func, term, paren) ripper_new_strterm(parser, func, term, paren) -static NODE * -ripper_new_strterm(struct parser_params *parser, VALUE func, VALUE term, VALUE paren) -{ - NODE *node = NEW_STRTERM0(func, term, paren); - nd_set_line(node, ruby_sourceline); - return node; -} -#endif static int parser_parse_string(struct parser_params *parser, NODE *quote) @@ -5229,12 +5236,12 @@ parser_parse_string(struct parser_params *parser, NODE *quote) if (tokadd_string(func, term, paren, "e->nd_nest) == -1) { if (func & STR_FUNC_REGEXP) { ruby_sourceline = nd_line(quote); - rb_compile_error(PARSER_ARG "unterminated regexp meets end of file"); + compile_error(PARSER_ARG "unterminated regexp meets end of file"); return tREGEXP_END; } else { ruby_sourceline = nd_line(quote); - rb_compile_error(PARSER_ARG "unterminated string meets end of file"); + compile_error(PARSER_ARG "unterminated string meets end of file"); return tSTRING_END; } } @@ -5271,7 +5278,7 @@ parser_heredoc_identifier(struct parser_params *parser) do {tokadd(c);} while (--len > 0 && (c = nextc()) != -1); } if (c == -1) { - rb_compile_error(PARSER_ARG "unterminated here document identifier"); + compile_error(PARSER_ARG "unterminated here document identifier"); return 0; } break; @@ -5370,7 +5377,7 @@ parser_here_document(struct parser_params *parser, NODE *here) if ((c = nextc()) == -1) { error: - rb_compile_error(PARSER_ARG "can't find string \"%s\" anywhere before EOF", eos); + compile_error(PARSER_ARG "can't find string \"%s\" anywhere before EOF", eos); heredoc_restore(lex_strterm); lex_strterm = 0; return 0; @@ -5442,18 +5449,18 @@ parser_here_document(struct parser_params *parser, NODE *here) #ifndef RIPPER static void -arg_ambiguous(void) +arg_ambiguous_gen(struct parser_params *parser) { rb_warning0("ambiguous first argument; put parentheses or even spaces"); } #else static void -ripper_arg_ambiguous(struct parser_params *parser) +arg_ambiguous_gen(struct parser_params *parser) { dispatch0(arg_ambiguous); } -#define arg_ambiguous() ripper_arg_ambiguous(parser) #endif +#define arg_ambiguous() arg_ambiguous_gen(parser) static int lvar_defined_gen(struct parser_params *parser, ID id) @@ -5791,7 +5798,7 @@ parser_yylex(struct parser_params *parser) #endif c = nextc(); if (c == -1) { - rb_compile_error(PARSER_ARG "embedded document meets end of file"); + compile_error(PARSER_ARG "embedded document meets end of file"); return 0; } if (c != '=') continue; @@ -5919,7 +5926,7 @@ parser_yylex(struct parser_params *parser) } c = nextc(); if (c == -1) { - rb_compile_error(PARSER_ARG "incomplete character syntax"); + compile_error(PARSER_ARG "incomplete character syntax"); return 0; } uc = (unsigned char)c; @@ -6539,7 +6546,7 @@ parser_yylex(struct parser_params *parser) } } if (c == -1 || term == -1) { - rb_compile_error(PARSER_ARG "unterminated quoted string meets end of file"); + compile_error(PARSER_ARG "unterminated quoted string meets end of file"); return 0; } paren = term; @@ -6659,7 +6666,7 @@ parser_yylex(struct parser_params *parser) tokfix(); set_yylval_id(rb_intern(tok())); if (!is_global_id(yylval_id())) { - rb_compile_error(PARSER_ARG "invalid global variable `%s'", rb_id2name(yylval.id)); + compile_error(PARSER_ARG "invalid global variable `%s'", rb_id2name(yylval.id)); return 0; } return tGVAR; @@ -6711,10 +6718,10 @@ parser_yylex(struct parser_params *parser) } if (ISDIGIT(c)) { if (tokidx == 1) { - rb_compile_error(PARSER_ARG "`@%c' is not allowed as an instance variable name", c); + compile_error(PARSER_ARG "`@%c' is not allowed as an instance variable name", c); } else { - rb_compile_error(PARSER_ARG "`@@%c' is not allowed as a class variable name", c); + compile_error(PARSER_ARG "`@@%c' is not allowed as a class variable name", c); } return 0; } @@ -6743,7 +6750,7 @@ parser_yylex(struct parser_params *parser) default: uc = (unsigned char)c; if (!is_identchar(uc)) { - rb_compile_error(PARSER_ARG "Invalid char `\\%03o' in expression", c); + compile_error(PARSER_ARG "Invalid char `\\%03o' in expression", c); goto retry; } @@ -6914,20 +6921,12 @@ yylex(void *p) } #ifndef RIPPER -NODE* -rb_node_newnode(enum node_type type, VALUE a0, VALUE a1, VALUE a2) +static NODE* +node_newnode(struct parser_params *parser, enum node_type type, VALUE a0, VALUE a1, VALUE a2) { - NODE *n = (NODE*)rb_newobj(); - - n->flags |= T_NODE; - nd_set_type(n, type); + NODE *n = (rb_node_newnode)(type, a0, a1, a2); nd_set_line(n, ruby_sourceline); n->nd_file = ruby_sourcefile; - - n->u1.value = a0; - n->u2.value = a1; - n->u3.value = a2; - return n; } @@ -6965,23 +6964,17 @@ fixpos(NODE *node, NODE *orig) static void parser_warning(NODE *node, const char *mesg) { - int line = ruby_sourceline; - ruby_sourceline = nd_line(node); - rb_warningS("%s", mesg); - ruby_sourceline = line; + rb_compile_warning(node->nd_file, nd_line(node), "%s", mesg); } static void parser_warn(NODE *node, const char *mesg) { - int line = ruby_sourceline; - ruby_sourceline = nd_line(node); - rb_warnS("%s", mesg); - ruby_sourceline = line; + rb_compile_warn(node->nd_file, nd_line(node), "%s", mesg); } static NODE* -block_append(NODE *head, NODE *tail) +block_append_gen(struct parser_params *parser, NODE *head, NODE *tail) { NODE *end, *h = head, *nd; @@ -7035,7 +7028,7 @@ block_append(NODE *head, NODE *tail) /* append item to the list */ static NODE* -list_append(NODE *list, NODE *item) +list_append_gen(struct parser_params *parser, NODE *list, NODE *item) { NODE *last; @@ -7055,7 +7048,7 @@ list_append(NODE *list, NODE *item) /* concat two lists */ static NODE* -list_concat(NODE *head, NODE *tail) +list_concat_gen(struct parser_params *parser, NODE *head, NODE *tail) { NODE *last; @@ -7080,7 +7073,7 @@ list_concat(NODE *head, NODE *tail) /* concat two string literals */ static NODE * -literal_concat(NODE *head, NODE *tail) +literal_concat_gen(struct parser_params *parser, NODE *head, NODE *tail) { enum node_type htype; @@ -7129,7 +7122,7 @@ literal_concat(NODE *head, NODE *tail) } static NODE * -evstr2dstr(NODE *node) +evstr2dstr_gen(struct parser_params *parser, NODE *node) { if (nd_type(node) == NODE_EVSTR) { node = list_append(NEW_DSTR(rb_str_new(0, 0)), node); @@ -7138,7 +7131,7 @@ evstr2dstr(NODE *node) } static NODE * -new_evstr(NODE *node) +new_evstr_gen(struct parser_params *parser, NODE *node) { NODE *head = node; @@ -7238,7 +7231,7 @@ gettable_gen(struct parser_params *parser, ID id) else if (is_class_id(id)) { return NEW_CVAR(id); } - rb_compile_error("identifier %s is not valid", rb_id2name(id)); + compile_error(PARSER_ARG "identifier %s is not valid to get", rb_id2name(id)); return 0; } @@ -7301,9 +7294,7 @@ assignable_gen(struct parser_params *parser, ID id, NODE *val) else if (is_class_id(id)) { return NEW_CVASGN(id, val); } - else { - rb_compile_error("identifier %s is not valid", rb_id2name(id)); - } + compile_error(PARSER_ARG "identifier %s is not valid to set", rb_id2name(id)); return 0; } @@ -7349,10 +7340,10 @@ aryset_gen(struct parser_params *parser, NODE *recv, NODE *idx) } static void -block_dup_check(NODE *node1, NODE *node2) +block_dup_check_gen(struct parser_params *parser, NODE *node1, NODE *node2) { if (node2 && node1 && nd_type(node1) == NODE_BLOCK_PASS) { - compile_error("both block arg and actual block given"); + compile_error(PARSER_ARG "both block arg and actual block given"); } } @@ -7375,20 +7366,20 @@ attrset_gen(struct parser_params *parser, NODE *recv, ID id) } static void -rb_backref_error(NODE *node) +rb_backref_error_gen(struct parser_params *parser, NODE *node) { switch (nd_type(node)) { case NODE_NTH_REF: - rb_compile_error("Can't set variable $%ld", node->nd_nth); + compile_error(PARSER_ARG "Can't set variable $%ld", node->nd_nth); break; case NODE_BACK_REF: - rb_compile_error("Can't set variable $%c", (int)node->nd_nth); + compile_error(PARSER_ARG "Can't set variable $%c", (int)node->nd_nth); break; } } static NODE * -arg_concat(NODE *node1, NODE *node2) +arg_concat_gen(struct parser_params *parser, NODE *node1, NODE *node2) { if (!node2) return node1; if (nd_type(node1) == NODE_BLOCK_PASS) { @@ -7399,7 +7390,7 @@ arg_concat(NODE *node1, NODE *node2) } static NODE * -arg_append(NODE *node1, NODE *node2) +arg_append_gen(struct parser_params *parser, NODE *node1, NODE *node2) { if (!node1) return NEW_LIST(node2); switch (nd_type(node1)) { @@ -7413,8 +7404,9 @@ arg_append(NODE *node1, NODE *node2) } } +#define arg_add(n1, n2) arg_add_gen(parser,n1,n2) static NODE * -arg_add(NODE *node1, NODE *node2) +arg_add_gen(struct parser_params *parser, NODE *node1, NODE *node2) { if (!node1) return NEW_LIST(node2); switch (nd_type(node1)) { @@ -7628,7 +7620,7 @@ remove_begin(NODE *node) } static void -reduce_nodes(NODE **body) +reduce_nodes_gen(struct parser_params *parser, NODE **body) { NODE *node = *body; @@ -7720,9 +7712,9 @@ assign_in_cond(struct parser_params *parser, NODE *node) } static int -e_option_supplied(void) +e_option_supplied(NODE *node) { - if (strcmp(ruby_sourcefile, "-e") == 0) + if (strcmp(node->nd_file, "-e") == 0) return Qtrue; return Qfalse; } @@ -7730,13 +7722,13 @@ e_option_supplied(void) static void warn_unless_e_option(NODE *node, const char *str) { - if (!e_option_supplied()) parser_warn(node, str); + if (!e_option_supplied(node)) parser_warn(node, str); } static void warning_unless_e_option(NODE *node, const char *str) { - if (!e_option_supplied()) parser_warning(node, str); + if (!e_option_supplied(node)) parser_warning(node, str); } static NODE *cond0(struct parser_params*,NODE*); @@ -7746,7 +7738,7 @@ range_op(struct parser_params *parser, NODE *node) { enum node_type type; - if (!e_option_supplied()) return node; + if (!e_option_supplied(node)) return node; if (node == 0) return 0; value_expr(node); @@ -7810,7 +7802,7 @@ cond0(struct parser_params *parser, NODE *node) node->nd_end = range_op(parser, node->nd_end); if (nd_type(node) == NODE_DOT2) nd_set_type(node,NODE_FLIP2); else if (nd_type(node) == NODE_DOT3) nd_set_type(node, NODE_FLIP3); - if (!e_option_supplied()) { + if (!e_option_supplied(node)) { int b = literal_node(node->nd_beg); int e = literal_node(node->nd_end); if ((b == 1 && e == 1) || (b + e >= 2 && RTEST(ruby_verbose))) { @@ -7875,18 +7867,18 @@ cond_negative(NODE **nodep) } static void -no_blockarg(NODE *node) +no_blockarg(struct parser_params *parser, NODE *node) { if (node && nd_type(node) == NODE_BLOCK_PASS) { - rb_compile_error("block argument should not be given"); + compile_error(PARSER_ARG "block argument should not be given"); } } static NODE * -ret_args(NODE *node) +ret_args_gen(struct parser_params *parser, NODE *node) { if (node) { - no_blockarg(node); + no_blockarg(parser, node); if (nd_type(node) == NODE_ARRAY) { if (node->nd_next == 0) { node = node->nd_head; @@ -7900,12 +7892,12 @@ ret_args(NODE *node) } static NODE * -new_yield(NODE *node) +new_yield_gen(struct parser_params *parser, NODE *node) { long state = Qtrue; if (node) { - no_blockarg(node); + no_blockarg(parser, node); if (node && nd_type(node) == NODE_SPLAT) { state = Qtrue; } @@ -8081,7 +8073,7 @@ dyna_pop_gen(struct parser_params *parser) static int dyna_in_block_gen(struct parser_params *parser) { - return lvtbl->vars->prev != DVARS_TOPSCOPE; + return POINTER_P(lvtbl->vars) && lvtbl->vars->prev != DVARS_TOPSCOPE; } static int @@ -8123,10 +8115,14 @@ rb_gc_mark_parser(void) } NODE* -rb_parser_append_print(NODE *node) +rb_parser_append_print(VALUE vparser, NODE *node) { NODE *prelude = 0; NODE *scope = node; + struct parser_params *parser; + + Data_Get_Struct(vparser, struct parser_params, parser); + node = node->nd_body; if (node && (nd_type(node) == NODE_PRELUDE)) { @@ -8149,10 +8145,13 @@ rb_parser_append_print(NODE *node) } NODE * -rb_parser_while_loop(NODE *node, int chop, int split) +rb_parser_while_loop(VALUE vparser, NODE *node, int chop, int split) { NODE *prelude = 0; NODE *scope = node; + struct parser_params *parser; + + Data_Get_Struct(vparser, struct parser_params, parser); node = node->nd_body; @@ -8276,6 +8275,7 @@ Init_sym(void) global_symbols.id_str = st_init_numtable_with_size(1000); global_symbols.ivar2_id = st_init_table_with_size(&ivar2_hash_type, 1000); global_symbols.id_ivar2 = st_init_numtable_with_size(1000); + rb_intern2("", 0); } void @@ -8626,6 +8626,7 @@ parser_initialize(struct parser_params *parser) parser->parser_lvtbl = 0; parser->parser_ruby__end__seen = 0; #ifndef RIPPER + parser->parser_ruby_sourcefile = 0; parser->parser_eval_tree_begin = 0; parser->parser_eval_tree = 0; #else @@ -8641,6 +8642,8 @@ parser_initialize(struct parser_params *parser) #endif } +extern void rb_mark_source_filename(char *); + static void parser_mark(void *ptr) { @@ -8653,6 +8656,7 @@ parser_mark(void *ptr) rb_gc_mark((VALUE)p->parser_eval_tree_begin) ; rb_gc_mark((VALUE)p->parser_eval_tree) ; rb_gc_mark(p->debug_lines); + rb_mark_source_filename(p->parser_ruby_sourcefile); #else rb_gc_mark(p->parser_ruby_sourcefile); rb_gc_mark(p->delayed); @@ -8720,12 +8724,12 @@ rb_parser_end_seen_p(VALUE vparser) #ifdef YYMALLOC #define HEAPCNT(n, size) ((n) * (size) / sizeof(YYSTYPE)) -#define NEWHEAP() rb_node_newnode(NODE_ALLOCA, 0, (VALUE)parserp->heap, 0) -#define ADD2HEAP(n, c, p) ((parserp->heap = (n))->u1.node = (p), \ +#define NEWHEAP() rb_node_newnode(NODE_ALLOCA, 0, (VALUE)parser->heap, 0) +#define ADD2HEAP(n, c, p) ((parser->heap = (n))->u1.node = (p), \ (n)->u3.cnt = (c), (p)) void * -rb_parser_malloc(struct parser_params *parserp, size_t size) +rb_parser_malloc(struct parser_params *parser, size_t size) { size_t cnt = HEAPCNT(1, size); NODE *n = NEWHEAP(); @@ -8735,7 +8739,7 @@ rb_parser_malloc(struct parser_params *parserp, size_t size) } void * -rb_parser_calloc(struct parser_params *parserp, size_t nelem, size_t size) +rb_parser_calloc(struct parser_params *parser, size_t nelem, size_t size) { size_t cnt = HEAPCNT(nelem, size); NODE *n = NEWHEAP(); @@ -8745,12 +8749,12 @@ rb_parser_calloc(struct parser_params *parserp, size_t nelem, size_t size) } void * -rb_parser_realloc(struct parser_params *parserp, void *ptr, size_t size) +rb_parser_realloc(struct parser_params *parser, void *ptr, size_t size) { NODE *n; size_t cnt = HEAPCNT(1, size); - if (ptr && (n = parserp->heap) != NULL) { + if (ptr && (n = parser->heap) != NULL) { do { if (n->u1.node == ptr) { n->u1.node = ptr = xrealloc(ptr, size); @@ -8765,9 +8769,9 @@ rb_parser_realloc(struct parser_params *parserp, void *ptr, size_t size) } void -rb_parser_free(struct parser_params *parserp, void *ptr) +rb_parser_free(struct parser_params *parser, void *ptr) { - NODE **prev = &parserp->heap, *n; + NODE **prev = &parser->heap, *n; while ((n = *prev) != NULL) { if (n->u1.node == ptr) { diff --git a/re.c b/re.c index ec82593395..f8af10a7f3 100644 --- a/re.c +++ b/re.c @@ -21,6 +21,8 @@ VALUE rb_eRegexpError; +typedef char onig_errmsg_buffer[ONIG_MAX_ERROR_MESSAGE_LEN]; + #define BEG(no) regs->beg[no] #define END(no) regs->end[no] @@ -595,14 +597,11 @@ rb_reg_to_s(VALUE re) } static void -rb_reg_raise(const char *s, long len, const char *err, VALUE re, int ce) +rb_reg_raise(const char *s, long len, const char *err, VALUE re) { VALUE desc = rb_reg_desc(s, len, re); - if (ce) - rb_compile_error("%s: %s", err, RSTRING_PTR(desc)); - else - rb_raise(rb_eRegexpError, "%s: %s", err, RSTRING_PTR(desc)); + rb_raise(rb_eRegexpError, "%s: %s", err, RSTRING_PTR(desc)); } @@ -685,10 +684,9 @@ rb_reg_kcode_m(VALUE re) } static Regexp* -make_regexp(const char *s, long len, int flags, int ce) +make_regexp(const char *s, long len, int flags, onig_errmsg_buffer err) { Regexp *rp; - char err[ONIG_MAX_ERROR_MESSAGE_LEN]; int r; OnigErrorInfo einfo; @@ -705,7 +703,7 @@ make_regexp(const char *s, long len, int flags, int ce) OnigDefaultSyntax); if (r) { onig_error_code_to_str((UChar*)err, r); - rb_reg_raise(s, len, err, 0, ce); + return 0; } r = onig_compile(rp, (UChar*)s, (UChar*)(s + len), &einfo); @@ -713,7 +711,6 @@ make_regexp(const char *s, long len, int flags, int ce) if (r != 0) { onig_free(rp); (void )onig_error_code_to_str((UChar*)err, r, &einfo); - rb_reg_raise(s, len, err, 0, ce); return 0; } return rp; @@ -907,7 +904,7 @@ rb_reg_prepare_re(VALUE re) } if (need_recompile) { - char err[ONIG_MAX_ERROR_MESSAGE_LEN]; + onig_errmsg_buffer err; int r; OnigErrorInfo einfo; regex_t *reg, *reg2; @@ -924,8 +921,8 @@ rb_reg_prepare_re(VALUE re) reg->options, onigenc_get_default_encoding(), OnigDefaultSyntax, &einfo); if (r) { - onig_error_code_to_str((UChar*)err, r, &einfo); - rb_reg_raise((char* )pattern, RREGEXP(re)->len, err, re, Qfalse); + onig_error_code_to_str((UChar*)err, r, &einfo); + rb_reg_raise((char* )pattern, RREGEXP(re)->len, err, re); } RREGEXP(re)->ptr = reg2; @@ -1016,9 +1013,9 @@ rb_reg_search(VALUE re, VALUE str, long pos, long reverse) return result; } else { - char err[ONIG_MAX_ERROR_MESSAGE_LEN]; + onig_errmsg_buffer err; onig_error_code_to_str((UChar*)err, result); - rb_reg_raise(RREGEXP(re)->str, RREGEXP(re)->len, err, 0, Qfalse); + rb_reg_raise(RREGEXP(re)->str, RREGEXP(re)->len, err, 0); } } @@ -1460,10 +1457,9 @@ match_inspect(VALUE match) VALUE rb_cRegexp; -static void +static int rb_reg_initialize(VALUE obj, const char *s, long len, - int options, - int ce) /* call rb_compile_error() */ + int options, onig_errmsg_buffer err) { struct RRegexp *re = RREGEXP(obj); @@ -1486,7 +1482,8 @@ rb_reg_initialize(VALUE obj, const char *s, long len, options |= ONIG_OPTION_IGNORECASE; FL_SET(re, REG_CASESTATE); } - re->ptr = make_regexp(s, len, options & ARG_REG_OPTION_MASK, ce); + re->ptr = make_regexp(s, len, options & ARG_REG_OPTION_MASK, err); + if (!re->ptr) return -1; re->str = ALLOC_N(char, len+1); memcpy(re->str, s, len); re->str[len] = '\0'; @@ -1494,7 +1491,7 @@ rb_reg_initialize(VALUE obj, const char *s, long len, if (options & ARG_KCODE_MASK) { kcode_reset_option(); } - if (ce) FL_SET(obj, REG_LITERAL); + return 0; } static VALUE @@ -1514,18 +1511,27 @@ VALUE rb_reg_new(const char *s, long len, int options) { VALUE re = rb_reg_s_alloc(rb_cRegexp); + char err[ONIG_MAX_ERROR_MESSAGE_LEN]; - rb_reg_initialize(re, s, len, options, Qfalse); - return (VALUE)re; + if (rb_reg_initialize(re, s, len, options, err) != 0) { + rb_reg_raise(s, len, err, re); + } + + return re; } VALUE -rb_reg_compile(const char *s, long len, int options) +rb_reg_compile(const char *s, long len, int options, const char *file, int line) { VALUE re = rb_reg_s_alloc(rb_cRegexp); + char err[ONIG_MAX_ERROR_MESSAGE_LEN]; - rb_reg_initialize(re, s, len, options, Qtrue); - return (VALUE)re; + if (rb_reg_initialize(re, s, len, options, err) != 0) { + VALUE desc = rb_reg_desc(s, len, re); + rb_compile_error(file, line, "%s: %s", err, RSTRING_PTR(desc)); + } + FL_SET(re, REG_LITERAL); + return re; } static int case_cache; @@ -1805,6 +1811,7 @@ rb_reg_match_m(int argc, VALUE *argv, VALUE re) static VALUE rb_reg_initialize_m(int argc, VALUE *argv, VALUE self) { + onig_errmsg_buffer err; const char *s; long len; int flags = 0; @@ -1838,7 +1845,9 @@ rb_reg_initialize_m(int argc, VALUE *argv, VALUE self) s = StringValuePtr(argv[0]); len = RSTRING_LEN(argv[0]); } - rb_reg_initialize(self, s, len, flags, Qfalse); + if (rb_reg_initialize(self, s, len, flags, err) != 0) { + rb_reg_raise(s, len, err, self); + } return self; } @@ -2081,6 +2090,10 @@ rb_reg_s_union(int argc, VALUE *argv) static VALUE rb_reg_init_copy(VALUE copy, VALUE re) { + onig_errmsg_buffer err; + const char *s; + long len; + if (copy == re) return copy; rb_check_frozen(copy); /* need better argument type check */ @@ -2088,8 +2101,11 @@ rb_reg_init_copy(VALUE copy, VALUE re) rb_raise(rb_eTypeError, "wrong argument type"); } rb_reg_check(re); - rb_reg_initialize(copy, RREGEXP(re)->str, RREGEXP(re)->len, - rb_reg_options(re), Qfalse); + s = RREGEXP(re)->str; + len = RREGEXP(re)->len; + if (rb_reg_initialize(copy, s, len, rb_reg_options(re), err) != 0) { + rb_reg_raise(s, len, err, copy); + } return copy; } diff --git a/ruby.c b/ruby.c index c126274c4a..e58d069382 100644 --- a/ruby.c +++ b/ruby.c @@ -63,8 +63,7 @@ extern int ruby_yydebug; char *ruby_inplace_mode = Qfalse; -static void load_stdin(void); -static NODE *load_file(const char *, int); +static NODE *load_file(VALUE, const char *, int); static void forbid_setid(const char *); static VALUE do_loop = Qfalse, do_print = Qfalse; @@ -374,14 +373,9 @@ extern void Init_ext(void); static void require_libraries(void) { - extern NODE *ruby_eval_tree; - NODE *save[3]; struct req_list *list = req_list_head.next; struct req_list *tmp; - save[0] = ruby_eval_tree; - save[1] = NEW_BEGIN(0); - ruby_eval_tree = 0; Init_ext(); /* should be called here for some reason :-( */ req_list_last = 0; while (list) { @@ -396,8 +390,6 @@ require_libraries(void) list = tmp; } req_list_head.next = 0; - ruby_eval_tree = save[0]; - rb_gc_force_recycle((VALUE)save[1]); } static void @@ -464,7 +456,7 @@ process_sflag(void) sflag = 0; } -static void proc_options(int argc, char **argv); +static NODE *proc_options(int argc, char **argv); static char * moreswitches(const char *s) @@ -487,16 +479,15 @@ moreswitches(const char *s) return (char *)s; } -NODE *ruby_eval_tree; - -static void +static NODE * proc_options(int argc, char **argv) { char *argv0 = argv[0]; int do_search; const char *s; char *script = 0; - NODE *volatile script_node = 0; + NODE *tree; + VALUE parser; int version = 0; int copyright = 0; @@ -504,7 +495,7 @@ proc_options(int argc, char **argv) VALUE e_script = Qfalse; if (argc == 0) - return; + return 0; do_search = Qfalse; @@ -780,7 +771,7 @@ proc_options(int argc, char **argv) switch_end: if (argv0 == 0) - return; + return 0; if (rb_safe_level() == 0 && (s = getenv("RUBYOPT"))) { while (ISSPACE(*s)) @@ -855,8 +846,6 @@ proc_options(int argc, char **argv) } if (!script) script = argv[0]; - script = ruby_sourcefile = rb_source_filename(script); - script_node = NEW_BEGIN(0); } #if defined DOSISH || defined __CYGWIN__ /* assume that we can change argv[n] if never change its length. */ @@ -872,16 +861,16 @@ proc_options(int argc, char **argv) process_sflag(); ruby_init_loadpath(); - ruby_sourcefile = rb_source_filename(argv0); + parser = rb_parser_new(); if (e_script) { require_libraries(); - ruby_eval_tree = rb_compile_string(script, e_script, 1); - } - else if (strlen(script) == 1 && script[0] == '-') { - load_stdin(); + tree = rb_parser_compile_string(parser, script, e_script, 1); } else { - load_file(script, 1); + if (script[0] == '-' && !script[1]) { + forbid_setid("program input from stdin"); + } + tree = load_file(parser, script, 1); } process_sflag(); @@ -891,13 +880,14 @@ proc_options(int argc, char **argv) FL_UNSET(rb_argv, FL_TAINT); FL_UNSET(rb_load_path, FL_TAINT); } + + return tree; } static NODE * -load_file(const char *fname, int script) +load_file(VALUE parser, const char *fname, int script) { extern VALUE rb_stdin; - volatile VALUE parser; VALUE f; int line_start = 1; NODE *tree = 0; @@ -949,11 +939,7 @@ load_file(const char *fname, int script) c = rb_io_getc(f); if (c == INT2FIX('#')) { c = rb_io_getc(f); - if (c == INT2FIX('!')) { - line = rb_io_gets(f); - if (NIL_P(line)) - return 0; - + if (c == INT2FIX('!') && !NIL_P(line = rb_io_gets(f))) { if ((p = strstr(RSTRING_PTR(line), "ruby")) == 0) { /* not ruby script, kick the program */ char **argv; @@ -983,8 +969,6 @@ load_file(const char *fname, int script) argv[0] = path; execv(path, argv); - ruby_sourcefile = rb_source_filename(fname); - ruby_sourceline = 1; rb_fatal("Can't exec %s", path); } @@ -1013,11 +997,8 @@ load_file(const char *fname, int script) rb_io_ungetc(f, c); } require_libraries(); /* Why here? unnatural */ - if (NIL_P(c)) - return 0; } - parser = rb_parser_new(); - ruby_eval_tree = tree = (NODE *)rb_parser_compile_file(parser, fname, f, line_start); + tree = (NODE *)rb_parser_compile_file(parser, fname, f, line_start); if (script && rb_parser_end_seen_p(parser)) { rb_define_global_const("DATA", f); } @@ -1030,14 +1011,7 @@ load_file(const char *fname, int script) void * rb_load_file(const char *fname) { - return load_file(fname, 0); -} - -static void -load_stdin(void) -{ - forbid_setid("program input from stdin"); - load_file("-", 1); + return load_file(rb_parser_new(), fname, 0); } VALUE rb_progname; @@ -1155,7 +1129,6 @@ ruby_script(const char *name) { if (name) { rb_progname = rb_tainted_str_new2(name); - ruby_sourcefile = rb_source_filename(name); } } @@ -1211,7 +1184,6 @@ ruby_prog_init(void) { init_ids(); - ruby_sourcefile = rb_source_filename("ruby"); rb_define_hooked_variable("$VERBOSE", &ruby_verbose, 0, verbose_setter); rb_define_hooked_variable("$-v", &ruby_verbose, 0, verbose_setter); rb_define_hooked_variable("$-w", &ruby_verbose, 0, verbose_setter); @@ -1263,9 +1235,11 @@ ruby_set_argv(int argc, char **argv) NODE *rb_parser_append_print(NODE *); NODE *rb_parser_while_loop(NODE *, int, int); -void +void * ruby_process_options(int argc, char **argv) { + NODE *tree; + origargc = argc; origargv = argv; @@ -1275,17 +1249,17 @@ ruby_process_options(int argc, char **argv) dln_argv0 = argv[0]; #endif set_arg0space(); - proc_options(argc, argv); + tree = proc_options(argc, argv); - if (do_check && ruby_nerrs == 0) { + if (do_check && tree) { printf("Syntax OK\n"); exit(0); } if (do_print) { - ruby_eval_tree = rb_parser_append_print(ruby_eval_tree); + tree = rb_parser_append_print(tree); } if (do_loop) { - ruby_eval_tree = - rb_parser_while_loop(ruby_eval_tree, do_line, do_split); + tree = rb_parser_while_loop(tree, do_line, do_split); } + return tree; } diff --git a/yarvcore.c b/yarvcore.c index 2273ef81cb..b25de4afc4 100644 --- a/yarvcore.c +++ b/yarvcore.c @@ -76,16 +76,16 @@ ID id__send_bang; rb_thread_t *ruby_current_thread = 0; rb_vm_t *ruby_current_vm = 0; -RUBY_EXTERN int ruby_nerrs; - static NODE * compile_string(VALUE str, VALUE file, VALUE line) { + VALUE parser = rb_parser_new(); NODE *node; - node = rb_compile_string(StringValueCStr(file), str, NUM2INT(line)); - if (ruby_nerrs > 0) { - ruby_nerrs = 0; + node = rb_parser_compile_string(parser, StringValueCStr(file), + str, NUM2INT(line)); + + if (!node) { rb_exc_raise(GET_THREAD()->errinfo); /* TODO: check err */ } return node; diff --git a/yarvcore.h b/yarvcore.h index d72ed96951..149a57fd10 100644 --- a/yarvcore.h +++ b/yarvcore.h @@ -537,7 +537,7 @@ VALUE rb_iseq_new_with_opt(NODE*, VALUE, VALUE, VALUE, VALUE, const rb_compile_o VALUE ruby_iseq_disasm(VALUE self); VALUE ruby_iseq_disasm_insn(VALUE str, VALUE *iseqval, int pos, rb_iseq_t *iseq, VALUE child); -char *ruby_node_name(int node); +const char *ruby_node_name(int node); /* each thread has this size stack : 2MB */ -- cgit v1.2.3