From 6bd0345627f383f1d1b041edba2a255ea4cdfb9b Mon Sep 17 00:00:00 2001 From: ko1 Date: Sun, 24 Jun 2007 19:23:24 +0000 Subject: * eval_*.h: rename to eval_*.ci. * common.mk: ditto. * eval_error.ci: remove ruby_set_current_source(). * error.c, eval.c, ruby.c: ditto. * eval_safe.c, proc.c: remove unused macros. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12607 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 12 ++ common.mk | 4 +- error.c | 1 - eval.c | 10 +- eval_error.ci | 243 ++++++++++++++++++++++ eval_error.h | 256 ------------------------ eval_jump.ci | 410 +++++++++++++++++++++++++++++++++++++ eval_jump.h | 410 ------------------------------------- eval_method.ci | 621 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ eval_method.h | 621 --------------------------------------------------------- eval_safe.ci | 109 ++++++++++ eval_safe.h | 117 ----------- proc.c | 7 - ruby.c | 2 - 14 files changed, 1401 insertions(+), 1422 deletions(-) create mode 100644 eval_error.ci delete mode 100644 eval_error.h create mode 100644 eval_jump.ci delete mode 100644 eval_jump.h create mode 100644 eval_method.ci delete mode 100644 eval_method.h create mode 100644 eval_safe.ci delete mode 100644 eval_safe.h diff --git a/ChangeLog b/ChangeLog index 0033f7f203..e37a928220 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +Mon Jun 25 04:20:14 2007 Koichi Sasada + + * eval_*.h: rename to eval_*.ci. + + * common.mk: ditto. + + * eval_error.ci: remove ruby_set_current_source(). + + * error.c, eval.c, ruby.c: ditto. + + * eval_safe.c, proc.c: remove unused macros. + Mon Jun 25 03:37:20 2007 Koichi Sasada * insnhelper.ci (caller_setup_args): add need_block_check option. diff --git a/common.mk b/common.mk index 47041139e1..3e335561d9 100644 --- a/common.mk +++ b/common.mk @@ -407,8 +407,8 @@ error.$(OBJEXT): {$(VPATH)}error.c {$(VPATH)}ruby.h {$(VPATH)}config.h \ {$(VPATH)}thread_$(THREAD_MODEL).h euc_jp.$(OBJEXT): {$(VPATH)}euc_jp.c {$(VPATH)}regenc.h \ {$(VPATH)}oniguruma.h {$(VPATH)}config.h -eval.$(OBJEXT): {$(VPATH)}eval.c {$(VPATH)}eval_error.h {$(VPATH)}eval_intern.h \ - {$(VPATH)}eval_method.h {$(VPATH)}eval_safe.h {$(VPATH)}eval_jump.h \ +eval.$(OBJEXT): {$(VPATH)}eval.c {$(VPATH)}eval_error.ci {$(VPATH)}eval_intern.h \ + {$(VPATH)}eval_method.ci {$(VPATH)}eval_safe.ci {$(VPATH)}eval_jump.ci \ {$(VPATH)}ruby.h {$(VPATH)}config.h {$(VPATH)}yarvcore.h \ {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \ {$(VPATH)}node.h {$(VPATH)}util.h {$(VPATH)}signal.h \ diff --git a/error.c b/error.c index 283e9c856f..6b5aac0126 100644 --- a/error.c +++ b/error.c @@ -52,7 +52,6 @@ err_position(char *buf, long len) static int compile_position(char *buf, long len) { - ruby_set_current_source(); return err_position_0(buf, len, ruby_sourcefile, ruby_sourceline); } diff --git a/eval.c b/eval.c index 65f972918f..e156c9c263 100644 --- a/eval.c +++ b/eval.c @@ -40,10 +40,10 @@ static VALUE eval(VALUE, VALUE, VALUE, char *, int); static inline VALUE rb_yield_0(int argc, VALUE *argv); static VALUE rb_call(VALUE, VALUE, ID, int, const VALUE *, int); -#include "eval_error.h" -#include "eval_method.h" -#include "eval_safe.h" -#include "eval_jump.h" +#include "eval_error.ci" +#include "eval_method.ci" +#include "eval_safe.ci" +#include "eval_jump.ci" /* initialize ruby */ @@ -691,7 +691,6 @@ rb_longjmp(int tag, VALUE mesg) mesg = rb_exc_new(rb_eRuntimeError, 0, 0); } - ruby_set_current_source(); if (ruby_sourcefile && !NIL_P(mesg)) { at = get_backtrace(mesg); if (NIL_P(at)) { @@ -1708,7 +1707,6 @@ eval(VALUE self, VALUE src, VALUE scope, char *file, int line) NODE *stored_cref_stack = 0; if (file == 0) { - ruby_set_current_source(); file = ruby_sourcefile; line = ruby_sourceline; } diff --git a/eval_error.ci b/eval_error.ci new file mode 100644 index 0000000000..63428991f3 --- /dev/null +++ b/eval_error.ci @@ -0,0 +1,243 @@ +/* + * included by eval.c + */ + +static void +warn_printf(const char *fmt, ...) +{ + char buf[BUFSIZ]; + va_list args; + + va_init_list(args, fmt); + vsnprintf(buf, BUFSIZ, fmt, args); + va_end(args); + rb_write_error(buf); +} + +#define warn_print(x) rb_write_error(x) +#define warn_print2(x,l) rb_write_error2(x,l) + +static void +error_pos(void) +{ + if (ruby_sourcefile) { + if (ruby_sourceline == 0) { + warn_printf("%s", ruby_sourcefile); + } + else if (rb_frame_callee()) { + warn_printf("%s:%d:in `%s'", ruby_sourcefile, ruby_sourceline, + rb_id2name(rb_frame_callee())); + } + else { + warn_printf("%s:%d", ruby_sourcefile, ruby_sourceline); + } + } +} + +static VALUE +get_backtrace(VALUE info) +{ + if (NIL_P(info)) + return Qnil; + info = rb_funcall(info, rb_intern("backtrace"), 0); + if (NIL_P(info)) + return Qnil; + return rb_check_array_type(info); +} + +static void +set_backtrace(VALUE info, VALUE bt) +{ + rb_funcall(info, rb_intern("set_backtrace"), 1, bt); +} + +static void +error_print(void) +{ + VALUE errat = Qnil; /* OK */ + volatile VALUE eclass, e; + char *einfo; + long elen; + + if (NIL_P(GET_THREAD()->errinfo)) + return; + + PUSH_TAG(); + if (EXEC_TAG() == 0) { + errat = get_backtrace(GET_THREAD()->errinfo); + } + else { + errat = Qnil; + } + if (EXEC_TAG()) + goto error; + if (NIL_P(errat)) { + if (ruby_sourcefile) + warn_printf("%s:%d", ruby_sourcefile, ruby_sourceline); + else + warn_printf("%d", ruby_sourceline); + } + else if (RARRAY_LEN(errat) == 0) { + error_pos(); + } + else { + VALUE mesg = RARRAY_PTR(errat)[0]; + + if (NIL_P(mesg)) + error_pos(); + else { + warn_print2(RSTRING_PTR(mesg), RSTRING_LEN(mesg)); + } + } + + eclass = CLASS_OF(GET_THREAD()->errinfo); + if (EXEC_TAG() == 0) { + e = rb_funcall(GET_THREAD()->errinfo, rb_intern("message"), 0, 0); + StringValue(e); + einfo = RSTRING_PTR(e); + elen = RSTRING_LEN(e); + } + else { + einfo = ""; + elen = 0; + } + if (EXEC_TAG()) + goto error; + if (eclass == rb_eRuntimeError && elen == 0) { + warn_print(": unhandled exception\n"); + } + else { + VALUE epath; + + epath = rb_class_name(eclass); + if (elen == 0) { + warn_print(": "); + warn_print2(RSTRING_PTR(epath), RSTRING_LEN(epath)); + warn_print("\n"); + } + else { + char *tail = 0; + long len = elen; + + if (RSTRING_PTR(epath)[0] == '#') + epath = 0; + if (tail = memchr(einfo, '\n', elen)) { + len = tail - einfo; + tail++; /* skip newline */ + } + warn_print(": "); + warn_print2(einfo, len); + if (epath) { + warn_print(" ("); + warn_print2(RSTRING_PTR(epath), RSTRING_LEN(epath)); + warn_print(")\n"); + } + if (tail) { + warn_print2(tail, elen - len - 1); + } + } + } + + if (!NIL_P(errat)) { + long i; + long len = RARRAY_LEN(errat); + VALUE *ptr = RARRAY_PTR(errat); + int skip = eclass == rb_eSysStackError; + +#define TRACE_MAX (TRACE_HEAD+TRACE_TAIL+5) +#define TRACE_HEAD 8 +#define TRACE_TAIL 5 + + for (i = 1; i < len; i++) { + if (TYPE(ptr[i]) == T_STRING) { + warn_printf("\tfrom %s\n", RSTRING_PTR(ptr[i])); + } + if (skip && i == TRACE_HEAD && len > TRACE_MAX) { + warn_printf("\t ... %ld levels...\n", + len - TRACE_HEAD - TRACE_TAIL); + i = len - TRACE_TAIL; + } + } + } + error: + POP_TAG(); +} + +void +print_undef(VALUE klass, ID id) +{ + rb_name_error(id, "undefined method `%s' for %s `%s'", + rb_id2name(id), + (TYPE(klass) == T_MODULE) ? "module" : "class", + rb_class2name(klass)); +} + +VALUE exception_error; +VALUE sysstack_error; + +static int +sysexit_status(VALUE err) +{ + VALUE st = rb_iv_get(err, "status"); + return NUM2INT(st); +} + +static int +error_handle(int ex) +{ + int status = EXIT_FAILURE; + rb_thread_t *th = GET_THREAD(); + + if (thread_set_raised(th)) + return EXIT_FAILURE; + switch (ex & TAG_MASK) { + case 0: + status = EXIT_SUCCESS; + break; + + case TAG_RETURN: + error_pos(); + warn_print(": unexpected return\n"); + break; + case TAG_NEXT: + error_pos(); + warn_print(": unexpected next\n"); + break; + case TAG_BREAK: + error_pos(); + warn_print(": unexpected break\n"); + break; + case TAG_REDO: + error_pos(); + warn_print(": unexpected redo\n"); + break; + case TAG_RETRY: + error_pos(); + warn_print(": retry outside of rescue clause\n"); + break; + case TAG_THROW: + /* TODO: fix me */ + error_pos(); + warn_printf(": unexpected throw\n"); + break; + case TAG_RAISE: + case TAG_FATAL: { + VALUE errinfo = GET_THREAD()->errinfo; + if (rb_obj_is_kind_of(errinfo, rb_eSystemExit)) { + status = sysexit_status(errinfo); + } + else if (rb_obj_is_instance_of(errinfo, rb_eSignal)) { + /* no message when exiting by signal */ + } + else { + error_print(); + } + break; + } + default: + rb_bug("Unknown longjmp status %d", ex); + break; + } + thread_reset_raised(th); + return status; +} diff --git a/eval_error.h b/eval_error.h deleted file mode 100644 index 8792462dfe..0000000000 --- a/eval_error.h +++ /dev/null @@ -1,256 +0,0 @@ -/* - * included by eval.c - */ - -#define SET_CURRENT_SOURCE() ((void)0) - -void -ruby_set_current_source(void) -{ - if (ruby_current_node) { - ruby_sourcefile = ruby_current_node->nd_file; - ruby_sourceline = nd_line(ruby_current_node); - } -} - -static void -warn_printf(const char *fmt, ...) -{ - char buf[BUFSIZ]; - va_list args; - - va_init_list(args, fmt); - vsnprintf(buf, BUFSIZ, fmt, args); - va_end(args); - rb_write_error(buf); -} - -#define warn_print(x) rb_write_error(x) -#define warn_print2(x,l) rb_write_error2(x,l) - -static void -error_pos(void) -{ - ruby_set_current_source(); - if (ruby_sourcefile) { - if (ruby_sourceline == 0) { - warn_printf("%s", ruby_sourcefile); - } - else if (rb_frame_callee()) { - warn_printf("%s:%d:in `%s'", ruby_sourcefile, ruby_sourceline, - rb_id2name(rb_frame_callee())); - } - else { - warn_printf("%s:%d", ruby_sourcefile, ruby_sourceline); - } - } -} - -static VALUE -get_backtrace(VALUE info) -{ - if (NIL_P(info)) - return Qnil; - info = rb_funcall(info, rb_intern("backtrace"), 0); - if (NIL_P(info)) - return Qnil; - return rb_check_array_type(info); -} - -static void -set_backtrace(VALUE info, VALUE bt) -{ - rb_funcall(info, rb_intern("set_backtrace"), 1, bt); -} - -static void -error_print(void) -{ - VALUE errat = Qnil; /* OK */ - volatile VALUE eclass, e; - char *einfo; - long elen; - - if (NIL_P(GET_THREAD()->errinfo)) - return; - - PUSH_TAG(); - if (EXEC_TAG() == 0) { - errat = get_backtrace(GET_THREAD()->errinfo); - } - else { - errat = Qnil; - } - if (EXEC_TAG()) - goto error; - if (NIL_P(errat)) { - ruby_set_current_source(); - if (ruby_sourcefile) - warn_printf("%s:%d", ruby_sourcefile, ruby_sourceline); - else - warn_printf("%d", ruby_sourceline); - } - else if (RARRAY_LEN(errat) == 0) { - error_pos(); - } - else { - VALUE mesg = RARRAY_PTR(errat)[0]; - - if (NIL_P(mesg)) - error_pos(); - else { - warn_print2(RSTRING_PTR(mesg), RSTRING_LEN(mesg)); - } - } - - eclass = CLASS_OF(GET_THREAD()->errinfo); - if (EXEC_TAG() == 0) { - e = rb_funcall(GET_THREAD()->errinfo, rb_intern("message"), 0, 0); - StringValue(e); - einfo = RSTRING_PTR(e); - elen = RSTRING_LEN(e); - } - else { - einfo = ""; - elen = 0; - } - if (EXEC_TAG()) - goto error; - if (eclass == rb_eRuntimeError && elen == 0) { - warn_print(": unhandled exception\n"); - } - else { - VALUE epath; - - epath = rb_class_name(eclass); - if (elen == 0) { - warn_print(": "); - warn_print2(RSTRING_PTR(epath), RSTRING_LEN(epath)); - warn_print("\n"); - } - else { - char *tail = 0; - long len = elen; - - if (RSTRING_PTR(epath)[0] == '#') - epath = 0; - if (tail = memchr(einfo, '\n', elen)) { - len = tail - einfo; - tail++; /* skip newline */ - } - warn_print(": "); - warn_print2(einfo, len); - if (epath) { - warn_print(" ("); - warn_print2(RSTRING_PTR(epath), RSTRING_LEN(epath)); - warn_print(")\n"); - } - if (tail) { - warn_print2(tail, elen - len - 1); - } - } - } - - if (!NIL_P(errat)) { - long i; - long len = RARRAY_LEN(errat); - VALUE *ptr = RARRAY_PTR(errat); - int skip = eclass == rb_eSysStackError; - -#define TRACE_MAX (TRACE_HEAD+TRACE_TAIL+5) -#define TRACE_HEAD 8 -#define TRACE_TAIL 5 - - for (i = 1; i < len; i++) { - if (TYPE(ptr[i]) == T_STRING) { - warn_printf("\tfrom %s\n", RSTRING_PTR(ptr[i])); - } - if (skip && i == TRACE_HEAD && len > TRACE_MAX) { - warn_printf("\t ... %ld levels...\n", - len - TRACE_HEAD - TRACE_TAIL); - i = len - TRACE_TAIL; - } - } - } - error: - POP_TAG(); -} - -void -print_undef(VALUE klass, ID id) -{ - rb_name_error(id, "undefined method `%s' for %s `%s'", - rb_id2name(id), - (TYPE(klass) == T_MODULE) ? "module" : "class", - rb_class2name(klass)); -} - -VALUE exception_error; -VALUE sysstack_error; - -static int -sysexit_status(VALUE err) -{ - VALUE st = rb_iv_get(err, "status"); - return NUM2INT(st); -} - -static int -error_handle(int ex) -{ - int status = EXIT_FAILURE; - rb_thread_t *th = GET_THREAD(); - - if (thread_set_raised(th)) - return EXIT_FAILURE; - switch (ex & TAG_MASK) { - case 0: - status = EXIT_SUCCESS; - break; - - case TAG_RETURN: - error_pos(); - warn_print(": unexpected return\n"); - break; - case TAG_NEXT: - error_pos(); - warn_print(": unexpected next\n"); - break; - case TAG_BREAK: - error_pos(); - warn_print(": unexpected break\n"); - break; - case TAG_REDO: - error_pos(); - warn_print(": unexpected redo\n"); - break; - case TAG_RETRY: - error_pos(); - warn_print(": retry outside of rescue clause\n"); - break; - case TAG_THROW: - /* TODO: fix me */ - error_pos(); - warn_printf(": unexpected throw\n"); - break; - case TAG_RAISE: - case TAG_FATAL: { - VALUE errinfo = GET_THREAD()->errinfo; - if (rb_obj_is_kind_of(errinfo, rb_eSystemExit)) { - status = sysexit_status(errinfo); - } - else if (rb_obj_is_instance_of(errinfo, rb_eSignal)) { - /* no message when exiting by signal */ - } - else { - error_print(); - } - break; - } - default: - rb_bug("Unknown longjmp status %d", ex); - break; - } - thread_reset_raised(th); - return status; -} diff --git a/eval_jump.ci b/eval_jump.ci new file mode 100644 index 0000000000..b929136afd --- /dev/null +++ b/eval_jump.ci @@ -0,0 +1,410 @@ +/* + * from eval.c + */ + +#include "eval_intern.h" + +NORETURN(static VALUE rb_f_throw _((int, VALUE *))); + +/* + * call-seq: + * throw(symbol [, obj]) + * + * Transfers control to the end of the active +catch+ block + * waiting for _symbol_. Raises +NameError+ if there + * is no +catch+ block for the symbol. The optional second + * parameter supplies a return value for the +catch+ block, + * which otherwise defaults to +nil+. For examples, see + * Kernel::catch. + */ + +static VALUE +rb_f_throw(int argc, VALUE *argv) +{ + VALUE tag, value; + rb_thread_t *th = GET_THREAD(); + struct rb_vm_tag *tt = th->tag; + + rb_scan_args(argc, argv, "11", &tag, &value); + tag = ID2SYM(rb_to_id(tag)); + + while (tt) { + if (tt->tag == tag) { + tt->retval = value; + break; + } + tt = tt->prev; + } + if (!tt) { + rb_name_error(SYM2ID(tag), "uncaught throw `%s'", + rb_id2name(SYM2ID(tag))); + } + rb_trap_restore_mask(); + th->errinfo = tag; + + JUMP_TAG(TAG_THROW); +#ifndef __GNUC__ + return Qnil; /* not reached */ +#endif +} + +void +rb_throw(const char *tag, VALUE val) +{ + VALUE argv[2]; + + argv[0] = ID2SYM(rb_intern(tag)); + argv[1] = val; + rb_f_throw(2, argv); +} + +/* + * call-seq: + * catch(symbol) {| | block } > obj + * + * +catch+ executes its block. If a +throw+ is + * executed, Ruby searches up its stack for a +catch+ block + * with a tag corresponding to the +throw+'s + * _symbol_. If found, that block is terminated, and + * +catch+ returns the value given to +throw+. If + * +throw+ is not called, the block terminates normally, and + * the value of +catch+ is the value of the last expression + * evaluated. +catch+ expressions may be nested, and the + * +throw+ call need not be in lexical scope. + * + * def routine(n) + * puts n + * throw :done if n <= 0 + * routine(n-1) + * end + * + * + * catch(:done) { routine(3) } + * + * produces: + * + * 3 + * 2 + * 1 + * 0 + */ + +static VALUE +rb_f_catch(VALUE dmy, VALUE tag) +{ + int state; + VALUE val = Qnil; /* OK */ + rb_thread_t *th = GET_THREAD(); + + tag = ID2SYM(rb_to_id(tag)); + PUSH_TAG(); + + th->tag->tag = tag; + + if ((state = EXEC_TAG()) == 0) { + val = rb_yield_0(1, &tag); + } + else if (state == TAG_THROW && th->errinfo == tag) { + val = th->tag->retval; + th->errinfo = Qnil; + state = 0; + } + POP_TAG(); + if (state) + JUMP_TAG(state); + + return val; +} + +static VALUE +catch_i(VALUE tag) +{ + return rb_funcall(Qnil, rb_intern("catch"), 1, tag); +} + +VALUE +rb_catch(const char *tag, VALUE (*func)(), VALUE data) +{ + return rb_iterate((VALUE (*)_((VALUE)))catch_i, ID2SYM(rb_intern(tag)), + func, data); +} + + +/* exit */ + +NORETURN(static VALUE terminate_process _((int, const char *, long))); + +static VALUE +terminate_process(int status, const char *mesg, long mlen) +{ + VALUE args[2]; + + args[0] = INT2NUM(status); + args[1] = rb_str_new(mesg, mlen); + + rb_exc_raise(rb_class_new_instance(2, args, rb_eSystemExit)); +} + + +void +rb_exit(int status) +{ + if (GET_THREAD()->tag) { + terminate_process(status, "exit", 4); + } + ruby_finalize(); + exit(status); +} + +/* + * call-seq: + * exit(integer=0) + * Kernel::exit(integer=0) + * Process::exit(integer=0) + * + * Initiates the termination of the Ruby script by raising the + * SystemExit exception. This exception may be caught. The + * optional parameter is used to return a status code to the invoking + * environment. + * + * begin + * exit + * puts "never get here" + * rescue SystemExit + * puts "rescued a SystemExit exception" + * end + * puts "after begin block" + * + * produces: + * + * rescued a SystemExit exception + * after begin block + * + * Just prior to termination, Ruby executes any at_exit functions + * (see Kernel::at_exit) and runs any object finalizers (see + * ObjectSpace::define_finalizer). + * + * at_exit { puts "at_exit function" } + * ObjectSpace.define_finalizer("string", proc { puts "in finalizer" }) + * exit + * + * produces: + * + * at_exit function + * in finalizer + */ + +VALUE +rb_f_exit(int argc, VALUE *argv) +{ + VALUE status; + int istatus; + + rb_secure(4); + if (rb_scan_args(argc, argv, "01", &status) == 1) { + switch (status) { + case Qtrue: + istatus = EXIT_SUCCESS; + break; + case Qfalse: + istatus = EXIT_FAILURE; + break; + default: + istatus = NUM2INT(status); +#if EXIT_SUCCESS != 0 + if (istatus == 0) + istatus = EXIT_SUCCESS; +#endif + break; + } + } + else { + istatus = EXIT_SUCCESS; + } + rb_exit(istatus); + return Qnil; /* not reached */ +} + + +/* + * call-seq: + * abort + * Kernel::abort + * Process::abort + * + * Terminate execution immediately, effectively by calling + * Kernel.exit(1). If _msg_ is given, it is written + * to STDERR prior to terminating. + */ + +VALUE +rb_f_abort(int argc, VALUE *argv) +{ + rb_secure(4); + if (argc == 0) { + if (!NIL_P(GET_THREAD()->errinfo)) { + error_print(); + } + rb_exit(EXIT_FAILURE); + } + else { + VALUE mesg; + + rb_scan_args(argc, argv, "1", &mesg); + StringValue(argv[0]); + rb_io_puts(argc, argv, rb_stderr); + terminate_process(EXIT_FAILURE, RSTRING_PTR(argv[0]), + RSTRING_LEN(argv[0])); + } + return Qnil; /* not reached */ +} + +static void call_end_proc _((VALUE data)); + +static void +call_end_proc(VALUE data) +{ + /* TODO: fix me */ + proc_invoke(data, rb_ary_new2(0), Qundef, 0); +} + +/* + * call-seq: + * at_exit { block } -> proc + * + * Converts _block_ to a +Proc+ object (and therefore + * binds it at the point of call) and registers it for execution when + * the program exits. If multiple handlers are registered, they are + * executed in reverse order of registration. + * + * def do_at_exit(str1) + * at_exit { print str1 } + * end + * at_exit { puts "cruel world" } + * do_at_exit("goodbye ") + * exit + * + * produces: + * + * goodbye cruel world + */ + +static VALUE +rb_f_at_exit(void) +{ + VALUE proc; + + if (!rb_block_given_p()) { + rb_raise(rb_eArgError, "called without a block"); + } + proc = rb_block_proc(); + rb_set_end_proc(call_end_proc, proc); + return proc; +} + +struct end_proc_data { + void (*func) (); + VALUE data; + int safe; + struct end_proc_data *next; +}; + +static struct end_proc_data *end_procs, *ephemeral_end_procs, *tmp_end_procs; + +void +rb_set_end_proc(void (*func)(VALUE), VALUE data) +{ + struct end_proc_data *link = ALLOC(struct end_proc_data); + struct end_proc_data **list; + rb_thread_t *th = GET_THREAD(); + + if (th->top_wrapper) { + list = &ephemeral_end_procs; + } + else { + list = &end_procs; + } + link->next = *list; + link->func = func; + link->data = data; + link->safe = rb_safe_level(); + *list = link; +} + +void +rb_mark_end_proc(void) +{ + struct end_proc_data *link; + + link = end_procs; + while (link) { + rb_gc_mark(link->data); + link = link->next; + } + link = ephemeral_end_procs; + while (link) { + rb_gc_mark(link->data); + link = link->next; + } + link = tmp_end_procs; + while (link) { + rb_gc_mark(link->data); + link = link->next; + } +} + +void +rb_exec_end_proc(void) +{ + struct end_proc_data *link, *tmp; + int status; + volatile int safe = rb_safe_level(); + + while (ephemeral_end_procs) { + tmp_end_procs = link = ephemeral_end_procs; + ephemeral_end_procs = 0; + while (link) { + PUSH_TAG(); + if ((status = EXEC_TAG()) == 0) { + rb_set_safe_level_force(link->safe); + (*link->func) (link->data); + } + POP_TAG(); + if (status) { + error_handle(status); + } + tmp = link; + tmp_end_procs = link = link->next; + free(tmp); + } + } + while (end_procs) { + tmp_end_procs = link = end_procs; + end_procs = 0; + while (link) { + PUSH_TAG(); + if ((status = EXEC_TAG()) == 0) { + rb_set_safe_level_force(link->safe); + (*link->func) (link->data); + } + POP_TAG(); + if (status) { + error_handle(status); + } + tmp = link; + tmp_end_procs = link = link->next; + free(tmp); + } + } + rb_set_safe_level_force(safe); +} + +void +Init_jump(void) +{ + rb_define_global_function("catch", rb_f_catch, 1); + rb_define_global_function("throw", rb_f_throw, -1); + rb_define_global_function("exit", rb_f_exit, -1); + rb_define_global_function("abort", rb_f_abort, -1); + rb_define_global_function("at_exit", rb_f_at_exit, 0); +} diff --git a/eval_jump.h b/eval_jump.h deleted file mode 100644 index b929136afd..0000000000 --- a/eval_jump.h +++ /dev/null @@ -1,410 +0,0 @@ -/* - * from eval.c - */ - -#include "eval_intern.h" - -NORETURN(static VALUE rb_f_throw _((int, VALUE *))); - -/* - * call-seq: - * throw(symbol [, obj]) - * - * Transfers control to the end of the active +catch+ block - * waiting for _symbol_. Raises +NameError+ if there - * is no +catch+ block for the symbol. The optional second - * parameter supplies a return value for the +catch+ block, - * which otherwise defaults to +nil+. For examples, see - * Kernel::catch. - */ - -static VALUE -rb_f_throw(int argc, VALUE *argv) -{ - VALUE tag, value; - rb_thread_t *th = GET_THREAD(); - struct rb_vm_tag *tt = th->tag; - - rb_scan_args(argc, argv, "11", &tag, &value); - tag = ID2SYM(rb_to_id(tag)); - - while (tt) { - if (tt->tag == tag) { - tt->retval = value; - break; - } - tt = tt->prev; - } - if (!tt) { - rb_name_error(SYM2ID(tag), "uncaught throw `%s'", - rb_id2name(SYM2ID(tag))); - } - rb_trap_restore_mask(); - th->errinfo = tag; - - JUMP_TAG(TAG_THROW); -#ifndef __GNUC__ - return Qnil; /* not reached */ -#endif -} - -void -rb_throw(const char *tag, VALUE val) -{ - VALUE argv[2]; - - argv[0] = ID2SYM(rb_intern(tag)); - argv[1] = val; - rb_f_throw(2, argv); -} - -/* - * call-seq: - * catch(symbol) {| | block } > obj - * - * +catch+ executes its block. If a +throw+ is - * executed, Ruby searches up its stack for a +catch+ block - * with a tag corresponding to the +throw+'s - * _symbol_. If found, that block is terminated, and - * +catch+ returns the value given to +throw+. If - * +throw+ is not called, the block terminates normally, and - * the value of +catch+ is the value of the last expression - * evaluated. +catch+ expressions may be nested, and the - * +throw+ call need not be in lexical scope. - * - * def routine(n) - * puts n - * throw :done if n <= 0 - * routine(n-1) - * end - * - * - * catch(:done) { routine(3) } - * - * produces: - * - * 3 - * 2 - * 1 - * 0 - */ - -static VALUE -rb_f_catch(VALUE dmy, VALUE tag) -{ - int state; - VALUE val = Qnil; /* OK */ - rb_thread_t *th = GET_THREAD(); - - tag = ID2SYM(rb_to_id(tag)); - PUSH_TAG(); - - th->tag->tag = tag; - - if ((state = EXEC_TAG()) == 0) { - val = rb_yield_0(1, &tag); - } - else if (state == TAG_THROW && th->errinfo == tag) { - val = th->tag->retval; - th->errinfo = Qnil; - state = 0; - } - POP_TAG(); - if (state) - JUMP_TAG(state); - - return val; -} - -static VALUE -catch_i(VALUE tag) -{ - return rb_funcall(Qnil, rb_intern("catch"), 1, tag); -} - -VALUE -rb_catch(const char *tag, VALUE (*func)(), VALUE data) -{ - return rb_iterate((VALUE (*)_((VALUE)))catch_i, ID2SYM(rb_intern(tag)), - func, data); -} - - -/* exit */ - -NORETURN(static VALUE terminate_process _((int, const char *, long))); - -static VALUE -terminate_process(int status, const char *mesg, long mlen) -{ - VALUE args[2]; - - args[0] = INT2NUM(status); - args[1] = rb_str_new(mesg, mlen); - - rb_exc_raise(rb_class_new_instance(2, args, rb_eSystemExit)); -} - - -void -rb_exit(int status) -{ - if (GET_THREAD()->tag) { - terminate_process(status, "exit", 4); - } - ruby_finalize(); - exit(status); -} - -/* - * call-seq: - * exit(integer=0) - * Kernel::exit(integer=0) - * Process::exit(integer=0) - * - * Initiates the termination of the Ruby script by raising the - * SystemExit exception. This exception may be caught. The - * optional parameter is used to return a status code to the invoking - * environment. - * - * begin - * exit - * puts "never get here" - * rescue SystemExit - * puts "rescued a SystemExit exception" - * end - * puts "after begin block" - * - * produces: - * - * rescued a SystemExit exception - * after begin block - * - * Just prior to termination, Ruby executes any at_exit functions - * (see Kernel::at_exit) and runs any object finalizers (see - * ObjectSpace::define_finalizer). - * - * at_exit { puts "at_exit function" } - * ObjectSpace.define_finalizer("string", proc { puts "in finalizer" }) - * exit - * - * produces: - * - * at_exit function - * in finalizer - */ - -VALUE -rb_f_exit(int argc, VALUE *argv) -{ - VALUE status; - int istatus; - - rb_secure(4); - if (rb_scan_args(argc, argv, "01", &status) == 1) { - switch (status) { - case Qtrue: - istatus = EXIT_SUCCESS; - break; - case Qfalse: - istatus = EXIT_FAILURE; - break; - default: - istatus = NUM2INT(status); -#if EXIT_SUCCESS != 0 - if (istatus == 0) - istatus = EXIT_SUCCESS; -#endif - break; - } - } - else { - istatus = EXIT_SUCCESS; - } - rb_exit(istatus); - return Qnil; /* not reached */ -} - - -/* - * call-seq: - * abort - * Kernel::abort - * Process::abort - * - * Terminate execution immediately, effectively by calling - * Kernel.exit(1). If _msg_ is given, it is written - * to STDERR prior to terminating. - */ - -VALUE -rb_f_abort(int argc, VALUE *argv) -{ - rb_secure(4); - if (argc == 0) { - if (!NIL_P(GET_THREAD()->errinfo)) { - error_print(); - } - rb_exit(EXIT_FAILURE); - } - else { - VALUE mesg; - - rb_scan_args(argc, argv, "1", &mesg); - StringValue(argv[0]); - rb_io_puts(argc, argv, rb_stderr); - terminate_process(EXIT_FAILURE, RSTRING_PTR(argv[0]), - RSTRING_LEN(argv[0])); - } - return Qnil; /* not reached */ -} - -static void call_end_proc _((VALUE data)); - -static void -call_end_proc(VALUE data) -{ - /* TODO: fix me */ - proc_invoke(data, rb_ary_new2(0), Qundef, 0); -} - -/* - * call-seq: - * at_exit { block } -> proc - * - * Converts _block_ to a +Proc+ object (and therefore - * binds it at the point of call) and registers it for execution when - * the program exits. If multiple handlers are registered, they are - * executed in reverse order of registration. - * - * def do_at_exit(str1) - * at_exit { print str1 } - * end - * at_exit { puts "cruel world" } - * do_at_exit("goodbye ") - * exit - * - * produces: - * - * goodbye cruel world - */ - -static VALUE -rb_f_at_exit(void) -{ - VALUE proc; - - if (!rb_block_given_p()) { - rb_raise(rb_eArgError, "called without a block"); - } - proc = rb_block_proc(); - rb_set_end_proc(call_end_proc, proc); - return proc; -} - -struct end_proc_data { - void (*func) (); - VALUE data; - int safe; - struct end_proc_data *next; -}; - -static struct end_proc_data *end_procs, *ephemeral_end_procs, *tmp_end_procs; - -void -rb_set_end_proc(void (*func)(VALUE), VALUE data) -{ - struct end_proc_data *link = ALLOC(struct end_proc_data); - struct end_proc_data **list; - rb_thread_t *th = GET_THREAD(); - - if (th->top_wrapper) { - list = &ephemeral_end_procs; - } - else { - list = &end_procs; - } - link->next = *list; - link->func = func; - link->data = data; - link->safe = rb_safe_level(); - *list = link; -} - -void -rb_mark_end_proc(void) -{ - struct end_proc_data *link; - - link = end_procs; - while (link) { - rb_gc_mark(link->data); - link = link->next; - } - link = ephemeral_end_procs; - while (link) { - rb_gc_mark(link->data); - link = link->next; - } - link = tmp_end_procs; - while (link) { - rb_gc_mark(link->data); - link = link->next; - } -} - -void -rb_exec_end_proc(void) -{ - struct end_proc_data *link, *tmp; - int status; - volatile int safe = rb_safe_level(); - - while (ephemeral_end_procs) { - tmp_end_procs = link = ephemeral_end_procs; - ephemeral_end_procs = 0; - while (link) { - PUSH_TAG(); - if ((status = EXEC_TAG()) == 0) { - rb_set_safe_level_force(link->safe); - (*link->func) (link->data); - } - POP_TAG(); - if (status) { - error_handle(status); - } - tmp = link; - tmp_end_procs = link = link->next; - free(tmp); - } - } - while (end_procs) { - tmp_end_procs = link = end_procs; - end_procs = 0; - while (link) { - PUSH_TAG(); - if ((status = EXEC_TAG()) == 0) { - rb_set_safe_level_force(link->safe); - (*link->func) (link->data); - } - POP_TAG(); - if (status) { - error_handle(status); - } - tmp = link; - tmp_end_procs = link = link->next; - free(tmp); - } - } - rb_set_safe_level_force(safe); -} - -void -Init_jump(void) -{ - rb_define_global_function("catch", rb_f_catch, 1); - rb_define_global_function("throw", rb_f_throw, -1); - rb_define_global_function("exit", rb_f_exit, -1); - rb_define_global_function("abort", rb_f_abort, -1); - rb_define_global_function("at_exit", rb_f_at_exit, 0); -} diff --git a/eval_method.ci b/eval_method.ci new file mode 100644 index 0000000000..1f4ba33d2f --- /dev/null +++ b/eval_method.ci @@ -0,0 +1,621 @@ +/* + * This file is included by eval.c + */ + +#define CACHE_SIZE 0x800 +#define CACHE_MASK 0x7ff +#define EXPR1(c,m) ((((c)>>3)^(m))&CACHE_MASK) + +struct cache_entry { /* method hash table. */ + ID mid; /* method's id */ + ID mid0; /* method's original id */ + VALUE klass; /* receiver's class */ + NODE *method; +}; + +static struct cache_entry cache[CACHE_SIZE]; +static int ruby_running = 0; + +void +rb_clear_cache(void) +{ + struct cache_entry *ent, *end; + + rb_vm_change_state(); + + if (!ruby_running) + return; + ent = cache; + end = ent + CACHE_SIZE; + while (ent < end) { + ent->mid = 0; + ent++; + } +} + +static void +rb_clear_cache_for_undef(VALUE klass, ID id) +{ + struct cache_entry *ent, *end; + + rb_vm_change_state(); + + if (!ruby_running) + return; + ent = cache; + end = ent + CACHE_SIZE; + while (ent < end) { + if (ent->method && ent->method->nd_clss == klass && ent->mid == id) { + ent->mid = 0; + } + ent++; + } +} + +static void +rb_clear_cache_by_id(ID id) +{ + struct cache_entry *ent, *end; + + rb_vm_change_state(); + + if (!ruby_running) + return; + ent = cache; + end = ent + CACHE_SIZE; + while (ent < end) { + if (ent->mid == id) { + ent->mid = 0; + } + ent++; + } +} + +void +rb_clear_cache_by_class(VALUE klass) +{ + struct cache_entry *ent, *end; + + rb_vm_change_state(); + + if (!ruby_running) + return; + ent = cache; + end = ent + CACHE_SIZE; + while (ent < end) { + if ((ent->klass == klass) || + (ent->method && ent->method->nd_clss == klass)) { + ent->mid = 0; + } + ent++; + } +} + +void +rb_add_method(VALUE klass, ID mid, NODE * node, int noex) +{ + NODE *body; + + if (NIL_P(klass)) { + klass = rb_cObject; + } + if (rb_safe_level() >= 4 && (klass == rb_cObject || !OBJ_TAINTED(klass))) { + rb_raise(rb_eSecurityError, "Insecure: can't define method"); + } + if (!FL_TEST(klass, FL_SINGLETON) && + node && nd_type(node) != NODE_ZSUPER && + (mid == rb_intern("initialize") || mid == rb_intern("initialize_copy"))) { + noex = NOEX_PRIVATE | noex; + } + else if (FL_TEST(klass, FL_SINGLETON) && node + && nd_type(node) == NODE_CFUNC && mid == rb_intern("allocate")) { + rb_warn + ("defining %s.allocate is deprecated; use rb_define_alloc_func()", + rb_class2name(rb_iv_get(klass, "__attached__"))); + mid = ID_ALLOCATOR; + } + if (OBJ_FROZEN(klass)) { + rb_error_frozen("class/module"); + } + rb_clear_cache_by_id(mid); + + /* + * NODE_METHOD (NEW_METHOD(body, klass, vis)): + * nd_body : method body // (2) // mark + * nd_clss : klass // (1) // mark + * nd_noex : visibility // (3) + * + * NODE_FBODY (NEW_FBODY(method, alias)): + * nd_body : method (NODE_METHOD) // (2) // mark + * nd_oid : original id // (1) + * nd_cnt : alias count // (3) + */ + if (node) { + body = NEW_FBODY(NEW_METHOD(node, klass, noex), 0); + } + else { + body = 0; + } + + { + /* check re-definition */ + NODE *old_node; + + if (st_lookup(RCLASS(klass)->m_tbl, mid, (st_data_t *)&old_node)) { + if (old_node) { + if (nd_type(old_node->nd_body->nd_body) == NODE_CFUNC) { + rb_vm_check_redefinition_opt_method(old_node); + } + if (RTEST(ruby_verbose) && old_node->nd_cnt == 0 && old_node->nd_body) { + rb_warning("method redefined; discarding old %s", rb_id2name(mid)); + } + } + if (klass == rb_cObject && node && node->nd_mid == init) { + rb_warn("redefining Object#initialize may cause infinite loop"); + } + } + + if (mid == object_id || mid == __send || mid == __send_bang) { + if (node && nd_type(node) == RUBY_VM_METHOD_NODE) { + rb_warn("redefining `%s' may cause serious problem", + rb_id2name(mid)); + } + } + } + + st_insert(RCLASS(klass)->m_tbl, mid, (st_data_t) body); + + if (node && mid != ID_ALLOCATOR && ruby_running) { + if (FL_TEST(klass, FL_SINGLETON)) { + rb_funcall(rb_iv_get(klass, "__attached__"), singleton_added, 1, + ID2SYM(mid)); + } + else { + rb_funcall(klass, added, 1, ID2SYM(mid)); + } + } +} + +void +rb_define_alloc_func(VALUE klass, VALUE (*func) _((VALUE))) +{ + Check_Type(klass, T_CLASS); + rb_add_method(CLASS_OF(klass), ID_ALLOCATOR, NEW_CFUNC(func, 0), + NOEX_PRIVATE); +} + +void +rb_undef_alloc_func(VALUE klass) +{ + Check_Type(klass, T_CLASS); + rb_add_method(CLASS_OF(klass), ID_ALLOCATOR, 0, NOEX_UNDEF); +} + +static NODE * +search_method(VALUE klass, ID id, VALUE *klassp) +{ + NODE *body; + + if (!klass) { + return 0; + } + + while (!st_lookup(RCLASS(klass)->m_tbl, id, (st_data_t *) & body)) { + klass = RCLASS(klass)->super; + if (!klass) + return 0; + } + + if (klassp) { + *klassp = klass; + } + + return body; +} + +/* + * search method body (NODE_METHOD) + * with : klass and id + * without : method cache + * + * if you need method node with method cache, use + * rb_method_node() + */ +NODE * +rb_get_method_body(VALUE klass, ID id, ID *idp) +{ + NODE *volatile fbody, *body; + NODE *method; + + if ((fbody = search_method(klass, id, 0)) == 0 || !fbody->nd_body) { + /* store empty info in cache */ + struct cache_entry *ent; + ent = cache + EXPR1(klass, id); + ent->klass = klass; + ent->mid = ent->mid0 = id; + ent->method = 0; + return 0; + } + + method = fbody->nd_body; + + if (ruby_running) { + /* store in cache */ + struct cache_entry *ent; + ent = cache + EXPR1(klass, id); + ent->klass = klass; + ent->mid = id; + ent->mid0 = fbody->nd_oid; + ent->method = body = method; + } + else { + body = method; + } + + if (idp) { + *idp = fbody->nd_oid; + } + + return body; +} + +NODE * +rb_method_node(VALUE klass, ID id) +{ + struct cache_entry *ent; + + ent = cache + EXPR1(klass, id); + if (ent->mid == id && ent->klass == klass && ent->method) { + return ent->method; + } + + return rb_get_method_body(klass, id, 0); +} + +static void +remove_method(VALUE klass, ID mid) +{ + NODE *body; + + if (klass == rb_cObject) { + rb_secure(4); + } + if (rb_safe_level() >= 4 && !OBJ_TAINTED(klass)) { + rb_raise(rb_eSecurityError, "Insecure: can't remove method"); + } + if (OBJ_FROZEN(klass)) + rb_error_frozen("class/module"); + if (mid == object_id || mid == __send || mid == __send_bang || mid == init) { + rb_warn("removing `%s' may cause serious problem", rb_id2name(mid)); + } + if (!st_delete(RCLASS(klass)->m_tbl, &mid, (st_data_t *) & body) || + !body->nd_body) { + rb_name_error(mid, "method `%s' not defined in %s", + rb_id2name(mid), rb_class2name(klass)); + } + + if (nd_type(body->nd_body->nd_body) == NODE_CFUNC) { + rb_vm_check_redefinition_opt_method(body); + } + + rb_clear_cache_for_undef(klass, mid); + if (FL_TEST(klass, FL_SINGLETON)) { + rb_funcall(rb_iv_get(klass, "__attached__"), singleton_removed, 1, + ID2SYM(mid)); + } + else { + rb_funcall(klass, removed, 1, ID2SYM(mid)); + } +} + +void +rb_remove_method(VALUE klass, const char *name) +{ + remove_method(klass, rb_intern(name)); +} + +/* + * call-seq: + * remove_method(symbol) => self + * + * Removes the method identified by _symbol_ from the current + * class. For an example, see Module.undef_method. + */ + +static VALUE +rb_mod_remove_method(int argc, VALUE *argv, VALUE mod) +{ + int i; + + for (i = 0; i < argc; i++) { + remove_method(mod, rb_to_id(argv[i])); + } + return mod; +} + +#undef rb_disable_super +#undef rb_enable_super + +void +rb_disable_super(VALUE klass, const char *name) +{ + /* obsolete - no use */ +} + +void +rb_enable_super(VALUE klass, const char *name) +{ + rb_warning("rb_enable_super() is obsolete"); +} + +static void +rb_export_method(VALUE klass, ID name, ID noex) +{ + NODE *fbody; + VALUE origin; + + if (klass == rb_cObject) { + rb_secure(4); + } + fbody = search_method(klass, name, &origin); + if (!fbody && TYPE(klass) == T_MODULE) { + fbody = search_method(rb_cObject, name, &origin); + } + if (!fbody || !fbody->nd_body) { + print_undef(klass, name); + } + if (fbody->nd_body->nd_noex != noex) { + if (klass == origin) { + fbody->nd_body->nd_noex = noex; + } + else { + rb_add_method(klass, name, NEW_ZSUPER(), noex); + } + } +} + +int +rb_method_boundp(VALUE klass, ID id, int ex) +{ + NODE *method; + + if ((method = rb_method_node(klass, id)) != 0) { + if (ex && (method->nd_noex & NOEX_PRIVATE)) { + return Qfalse; + } + return Qtrue; + } + return Qfalse; +} + +void +rb_attr(VALUE klass, ID id, int read, int write, int ex) +{ + const char *name; + char *buf; + ID attriv; + int noex; + size_t len; + + if (!ex) { + noex = NOEX_PUBLIC; + } + else { + if (SCOPE_TEST(NOEX_PRIVATE)) { + noex = NOEX_PRIVATE; + rb_warning((SCOPE_CHECK(NOEX_MODFUNC)) ? + "attribute accessor as module_function" : + "private attribute?"); + } + else if (SCOPE_TEST(NOEX_PROTECTED)) { + noex = NOEX_PROTECTED; + } + else { + noex = NOEX_PUBLIC; + } + } + + if (!rb_is_local_id(id) && !rb_is_const_id(id)) { + rb_name_error(id, "invalid attribute name `%s'", rb_id2name(id)); + } + name = rb_id2name(id); + if (!name) { + rb_raise(rb_eArgError, "argument needs to be symbol or string"); + } + len = strlen(name) + 2; + buf = ALLOCA_N(char, len); + snprintf(buf, len, "@%s", name); + attriv = rb_intern(buf); + if (read) { + rb_add_method(klass, id, NEW_IVAR(attriv), noex); + } + if (write) { + rb_add_method(klass, rb_id_attrset(id), NEW_ATTRSET(attriv), noex); + } +} + +void +rb_undef(VALUE klass, ID id) +{ + VALUE origin; + NODE *body; + + if (ruby_cbase() == rb_cObject && klass == rb_cObject) { + rb_secure(4); + } + if (rb_safe_level() >= 4 && !OBJ_TAINTED(klass)) { + rb_raise(rb_eSecurityError, "Insecure: can't undef `%s'", + rb_id2name(id)); + } + rb_frozen_class_p(klass); + if (id == object_id || id == __send || id == __send_bang || id == init) { + rb_warn("undefining `%s' may cause serious problem", rb_id2name(id)); + } + body = search_method(klass, id, &origin); + if (!body || !body->nd_body) { + char *s0 = " class"; + VALUE c = klass; + + if (FL_TEST(c, FL_SINGLETON)) { + VALUE obj = rb_iv_get(klass, "__attached__"); + + switch (TYPE(obj)) { + case T_MODULE: + case T_CLASS: + c = obj; + s0 = ""; + } + } + else if (TYPE(c) == T_MODULE) { + s0 = " module"; + } + rb_name_error(id, "undefined method `%s' for%s `%s'", + rb_id2name(id), s0, rb_class2name(c)); + } + + rb_add_method(klass, id, 0, NOEX_PUBLIC); + + if (FL_TEST(klass, FL_SINGLETON)) { + rb_funcall(rb_iv_get(klass, "__attached__"), + singleton_undefined, 1, ID2SYM(id)); + } + else { + rb_funcall(klass, undefined, 1, ID2SYM(id)); + } +} + +/* + * call-seq: + * undef_method(symbol) => self + * + * Prevents the current class from responding to calls to the named + * method. Contrast this with remove_method, which deletes + * the method from the particular class; Ruby will still search + * superclasses and mixed-in modules for a possible receiver. + * + * class Parent + * def hello + * puts "In parent" + * end + * end + * class Child < Parent + * def hello + * puts "In child" + * end + * end + * + * + * c = Child.new + * c.hello + * + * + * class Child + * remove_method :hello # remove from child, still in parent + * end + * c.hello + * + * + * class Child + * undef_method :hello # prevent any calls to 'hello' + * end + * c.hello + * + * produces: + * + * In child + * In parent + * prog.rb:23: undefined method `hello' for # (NoMethodError) + */ + +static VALUE +rb_mod_undef_method(int argc, VALUE *argv, VALUE mod) +{ + int i; + for (i = 0; i < argc; i++) { + rb_undef(mod, rb_to_id(argv[i])); + } + return mod; +} + +void +rb_alias(VALUE klass, ID name, ID def) +{ + NODE *orig_fbody, *node; + VALUE singleton = 0; + + rb_frozen_class_p(klass); + if (name == def) + return; + if (klass == rb_cObject) { + rb_secure(4); + } + orig_fbody = search_method(klass, def, 0); + if (!orig_fbody || !orig_fbody->nd_body) { + if (TYPE(klass) == T_MODULE) { + orig_fbody = search_method(rb_cObject, def, 0); + } + } + if (!orig_fbody || !orig_fbody->nd_body) { + print_undef(klass, def); + } + if (FL_TEST(klass, FL_SINGLETON)) { + singleton = rb_iv_get(klass, "__attached__"); + } + + orig_fbody->nd_cnt++; + + if (st_lookup(RCLASS(klass)->m_tbl, name, (st_data_t *) & node)) { + if (node) { + if (RTEST(ruby_verbose) && node->nd_cnt == 0 && node->nd_body) { + rb_warning("discarding old %s", rb_id2name(name)); + } + if (nd_type(node->nd_body->nd_body) == NODE_CFUNC) { + rb_vm_check_redefinition_opt_method(node); + } + } + } + + st_insert(RCLASS(klass)->m_tbl, name, + (st_data_t) NEW_FBODY( + NEW_METHOD(orig_fbody->nd_body->nd_body, + orig_fbody->nd_body->nd_clss, + orig_fbody->nd_body->nd_noex), def)); + + rb_clear_cache_by_id(name); + + if (singleton) { + rb_funcall(singleton, singleton_added, 1, ID2SYM(name)); + } + else { + rb_funcall(klass, added, 1, ID2SYM(name)); + } +} + +/* + * call-seq: + * alias_method(new_name, old_name) => self + * + * Makes new_name a new copy of the method old_name. This can + * be used to retain access to methods that are overridden. + * + * module Mod + * alias_method :orig_exit, :exit + * def exit(code=0) + * puts "Exiting with code #{code}" + * orig_exit(code) + * end + * end + * include Mod + * exit(99) + * + * produces: + * + * Exiting with code 99 + */ + +static VALUE +rb_mod_alias_method(VALUE mod, VALUE newname, VALUE oldname) +{ + rb_alias(mod, rb_to_id(newname), rb_to_id(oldname)); + return mod; +} diff --git a/eval_method.h b/eval_method.h deleted file mode 100644 index 1f4ba33d2f..0000000000 --- a/eval_method.h +++ /dev/null @@ -1,621 +0,0 @@ -/* - * This file is included by eval.c - */ - -#define CACHE_SIZE 0x800 -#define CACHE_MASK 0x7ff -#define EXPR1(c,m) ((((c)>>3)^(m))&CACHE_MASK) - -struct cache_entry { /* method hash table. */ - ID mid; /* method's id */ - ID mid0; /* method's original id */ - VALUE klass; /* receiver's class */ - NODE *method; -}; - -static struct cache_entry cache[CACHE_SIZE]; -static int ruby_running = 0; - -void -rb_clear_cache(void) -{ - struct cache_entry *ent, *end; - - rb_vm_change_state(); - - if (!ruby_running) - return; - ent = cache; - end = ent + CACHE_SIZE; - while (ent < end) { - ent->mid = 0; - ent++; - } -} - -static void -rb_clear_cache_for_undef(VALUE klass, ID id) -{ - struct cache_entry *ent, *end; - - rb_vm_change_state(); - - if (!ruby_running) - return; - ent = cache; - end = ent + CACHE_SIZE; - while (ent < end) { - if (ent->method && ent->method->nd_clss == klass && ent->mid == id) { - ent->mid = 0; - } - ent++; - } -} - -static void -rb_clear_cache_by_id(ID id) -{ - struct cache_entry *ent, *end; - - rb_vm_change_state(); - - if (!ruby_running) - return; - ent = cache; - end = ent + CACHE_SIZE; - while (ent < end) { - if (ent->mid == id) { - ent->mid = 0; - } - ent++; - } -} - -void -rb_clear_cache_by_class(VALUE klass) -{ - struct cache_entry *ent, *end; - - rb_vm_change_state(); - - if (!ruby_running) - return; - ent = cache; - end = ent + CACHE_SIZE; - while (ent < end) { - if ((ent->klass == klass) || - (ent->method && ent->method->nd_clss == klass)) { - ent->mid = 0; - } - ent++; - } -} - -void -rb_add_method(VALUE klass, ID mid, NODE * node, int noex) -{ - NODE *body; - - if (NIL_P(klass)) { - klass = rb_cObject; - } - if (rb_safe_level() >= 4 && (klass == rb_cObject || !OBJ_TAINTED(klass))) { - rb_raise(rb_eSecurityError, "Insecure: can't define method"); - } - if (!FL_TEST(klass, FL_SINGLETON) && - node && nd_type(node) != NODE_ZSUPER && - (mid == rb_intern("initialize") || mid == rb_intern("initialize_copy"))) { - noex = NOEX_PRIVATE | noex; - } - else if (FL_TEST(klass, FL_SINGLETON) && node - && nd_type(node) == NODE_CFUNC && mid == rb_intern("allocate")) { - rb_warn - ("defining %s.allocate is deprecated; use rb_define_alloc_func()", - rb_class2name(rb_iv_get(klass, "__attached__"))); - mid = ID_ALLOCATOR; - } - if (OBJ_FROZEN(klass)) { - rb_error_frozen("class/module"); - } - rb_clear_cache_by_id(mid); - - /* - * NODE_METHOD (NEW_METHOD(body, klass, vis)): - * nd_body : method body // (2) // mark - * nd_clss : klass // (1) // mark - * nd_noex : visibility // (3) - * - * NODE_FBODY (NEW_FBODY(method, alias)): - * nd_body : method (NODE_METHOD) // (2) // mark - * nd_oid : original id // (1) - * nd_cnt : alias count // (3) - */ - if (node) { - body = NEW_FBODY(NEW_METHOD(node, klass, noex), 0); - } - else { - body = 0; - } - - { - /* check re-definition */ - NODE *old_node; - - if (st_lookup(RCLASS(klass)->m_tbl, mid, (st_data_t *)&old_node)) { - if (old_node) { - if (nd_type(old_node->nd_body->nd_body) == NODE_CFUNC) { - rb_vm_check_redefinition_opt_method(old_node); - } - if (RTEST(ruby_verbose) && old_node->nd_cnt == 0 && old_node->nd_body) { - rb_warning("method redefined; discarding old %s", rb_id2name(mid)); - } - } - if (klass == rb_cObject && node && node->nd_mid == init) { - rb_warn("redefining Object#initialize may cause infinite loop"); - } - } - - if (mid == object_id || mid == __send || mid == __send_bang) { - if (node && nd_type(node) == RUBY_VM_METHOD_NODE) { - rb_warn("redefining `%s' may cause serious problem", - rb_id2name(mid)); - } - } - } - - st_insert(RCLASS(klass)->m_tbl, mid, (st_data_t) body); - - if (node && mid != ID_ALLOCATOR && ruby_running) { - if (FL_TEST(klass, FL_SINGLETON)) { - rb_funcall(rb_iv_get(klass, "__attached__"), singleton_added, 1, - ID2SYM(mid)); - } - else { - rb_funcall(klass, added, 1, ID2SYM(mid)); - } - } -} - -void -rb_define_alloc_func(VALUE klass, VALUE (*func) _((VALUE))) -{ - Check_Type(klass, T_CLASS); - rb_add_method(CLASS_OF(klass), ID_ALLOCATOR, NEW_CFUNC(func, 0), - NOEX_PRIVATE); -} - -void -rb_undef_alloc_func(VALUE klass) -{ - Check_Type(klass, T_CLASS); - rb_add_method(CLASS_OF(klass), ID_ALLOCATOR, 0, NOEX_UNDEF); -} - -static NODE * -search_method(VALUE klass, ID id, VALUE *klassp) -{ - NODE *body; - - if (!klass) { - return 0; - } - - while (!st_lookup(RCLASS(klass)->m_tbl, id, (st_data_t *) & body)) { - klass = RCLASS(klass)->super; - if (!klass) - return 0; - } - - if (klassp) { - *klassp = klass; - } - - return body; -} - -/* - * search method body (NODE_METHOD) - * with : klass and id - * without : method cache - * - * if you need method node with method cache, use - * rb_method_node() - */ -NODE * -rb_get_method_body(VALUE klass, ID id, ID *idp) -{ - NODE *volatile fbody, *body; - NODE *method; - - if ((fbody = search_method(klass, id, 0)) == 0 || !fbody->nd_body) { - /* store empty info in cache */ - struct cache_entry *ent; - ent = cache + EXPR1(klass, id); - ent->klass = klass; - ent->mid = ent->mid0 = id; - ent->method = 0; - return 0; - } - - method = fbody->nd_body; - - if (ruby_running) { - /* store in cache */ - struct cache_entry *ent; - ent = cache + EXPR1(klass, id); - ent->klass = klass; - ent->mid = id; - ent->mid0 = fbody->nd_oid; - ent->method = body = method; - } - else { - body = method; - } - - if (idp) { - *idp = fbody->nd_oid; - } - - return body; -} - -NODE * -rb_method_node(VALUE klass, ID id) -{ - struct cache_entry *ent; - - ent = cache + EXPR1(klass, id); - if (ent->mid == id && ent->klass == klass && ent->method) { - return ent->method; - } - - return rb_get_method_body(klass, id, 0); -} - -static void -remove_method(VALUE klass, ID mid) -{ - NODE *body; - - if (klass == rb_cObject) { - rb_secure(4); - } - if (rb_safe_level() >= 4 && !OBJ_TAINTED(klass)) { - rb_raise(rb_eSecurityError, "Insecure: can't remove method"); - } - if (OBJ_FROZEN(klass)) - rb_error_frozen("class/module"); - if (mid == object_id || mid == __send || mid == __send_bang || mid == init) { - rb_warn("removing `%s' may cause serious problem", rb_id2name(mid)); - } - if (!st_delete(RCLASS(klass)->m_tbl, &mid, (st_data_t *) & body) || - !body->nd_body) { - rb_name_error(mid, "method `%s' not defined in %s", - rb_id2name(mid), rb_class2name(klass)); - } - - if (nd_type(body->nd_body->nd_body) == NODE_CFUNC) { - rb_vm_check_redefinition_opt_method(body); - } - - rb_clear_cache_for_undef(klass, mid); - if (FL_TEST(klass, FL_SINGLETON)) { - rb_funcall(rb_iv_get(klass, "__attached__"), singleton_removed, 1, - ID2SYM(mid)); - } - else { - rb_funcall(klass, removed, 1, ID2SYM(mid)); - } -} - -void -rb_remove_method(VALUE klass, const char *name) -{ - remove_method(klass, rb_intern(name)); -} - -/* - * call-seq: - * remove_method(symbol) => self - * - * Removes the method identified by _symbol_ from the current - * class. For an example, see Module.undef_method. - */ - -static VALUE -rb_mod_remove_method(int argc, VALUE *argv, VALUE mod) -{ - int i; - - for (i = 0; i < argc; i++) { - remove_method(mod, rb_to_id(argv[i])); - } - return mod; -} - -#undef rb_disable_super -#undef rb_enable_super - -void -rb_disable_super(VALUE klass, const char *name) -{ - /* obsolete - no use */ -} - -void -rb_enable_super(VALUE klass, const char *name) -{ - rb_warning("rb_enable_super() is obsolete"); -} - -static void -rb_export_method(VALUE klass, ID name, ID noex) -{ - NODE *fbody; - VALUE origin; - - if (klass == rb_cObject) { - rb_secure(4); - } - fbody = search_method(klass, name, &origin); - if (!fbody && TYPE(klass) == T_MODULE) { - fbody = search_method(rb_cObject, name, &origin); - } - if (!fbody || !fbody->nd_body) { - print_undef(klass, name); - } - if (fbody->nd_body->nd_noex != noex) { - if (klass == origin) { - fbody->nd_body->nd_noex = noex; - } - else { - rb_add_method(klass, name, NEW_ZSUPER(), noex); - } - } -} - -int -rb_method_boundp(VALUE klass, ID id, int ex) -{ - NODE *method; - - if ((method = rb_method_node(klass, id)) != 0) { - if (ex && (method->nd_noex & NOEX_PRIVATE)) { - return Qfalse; - } - return Qtrue; - } - return Qfalse; -} - -void -rb_attr(VALUE klass, ID id, int read, int write, int ex) -{ - const char *name; - char *buf; - ID attriv; - int noex; - size_t len; - - if (!ex) { - noex = NOEX_PUBLIC; - } - else { - if (SCOPE_TEST(NOEX_PRIVATE)) { - noex = NOEX_PRIVATE; - rb_warning((SCOPE_CHECK(NOEX_MODFUNC)) ? - "attribute accessor as module_function" : - "private attribute?"); - } - else if (SCOPE_TEST(NOEX_PROTECTED)) { - noex = NOEX_PROTECTED; - } - else { - noex = NOEX_PUBLIC; - } - } - - if (!rb_is_local_id(id) && !rb_is_const_id(id)) { - rb_name_error(id, "invalid attribute name `%s'", rb_id2name(id)); - } - name = rb_id2name(id); - if (!name) { - rb_raise(rb_eArgError, "argument needs to be symbol or string"); - } - len = strlen(name) + 2; - buf = ALLOCA_N(char, len); - snprintf(buf, len, "@%s", name); - attriv = rb_intern(buf); - if (read) { - rb_add_method(klass, id, NEW_IVAR(attriv), noex); - } - if (write) { - rb_add_method(klass, rb_id_attrset(id), NEW_ATTRSET(attriv), noex); - } -} - -void -rb_undef(VALUE klass, ID id) -{ - VALUE origin; - NODE *body; - - if (ruby_cbase() == rb_cObject && klass == rb_cObject) { - rb_secure(4); - } - if (rb_safe_level() >= 4 && !OBJ_TAINTED(klass)) { - rb_raise(rb_eSecurityError, "Insecure: can't undef `%s'", - rb_id2name(id)); - } - rb_frozen_class_p(klass); - if (id == object_id || id == __send || id == __send_bang || id == init) { - rb_warn("undefining `%s' may cause serious problem", rb_id2name(id)); - } - body = search_method(klass, id, &origin); - if (!body || !body->nd_body) { - char *s0 = " class"; - VALUE c = klass; - - if (FL_TEST(c, FL_SINGLETON)) { - VALUE obj = rb_iv_get(klass, "__attached__"); - - switch (TYPE(obj)) { - case T_MODULE: - case T_CLASS: - c = obj; - s0 = ""; - } - } - else if (TYPE(c) == T_MODULE) { - s0 = " module"; - } - rb_name_error(id, "undefined method `%s' for%s `%s'", - rb_id2name(id), s0, rb_class2name(c)); - } - - rb_add_method(klass, id, 0, NOEX_PUBLIC); - - if (FL_TEST(klass, FL_SINGLETON)) { - rb_funcall(rb_iv_get(klass, "__attached__"), - singleton_undefined, 1, ID2SYM(id)); - } - else { - rb_funcall(klass, undefined, 1, ID2SYM(id)); - } -} - -/* - * call-seq: - * undef_method(symbol) => self - * - * Prevents the current class from responding to calls to the named - * method. Contrast this with remove_method, which deletes - * the method from the particular class; Ruby will still search - * superclasses and mixed-in modules for a possible receiver. - * - * class Parent - * def hello - * puts "In parent" - * end - * end - * class Child < Parent - * def hello - * puts "In child" - * end - * end - * - * - * c = Child.new - * c.hello - * - * - * class Child - * remove_method :hello # remove from child, still in parent - * end - * c.hello - * - * - * class Child - * undef_method :hello # prevent any calls to 'hello' - * end - * c.hello - * - * produces: - * - * In child - * In parent - * prog.rb:23: undefined method `hello' for # (NoMethodError) - */ - -static VALUE -rb_mod_undef_method(int argc, VALUE *argv, VALUE mod) -{ - int i; - for (i = 0; i < argc; i++) { - rb_undef(mod, rb_to_id(argv[i])); - } - return mod; -} - -void -rb_alias(VALUE klass, ID name, ID def) -{ - NODE *orig_fbody, *node; - VALUE singleton = 0; - - rb_frozen_class_p(klass); - if (name == def) - return; - if (klass == rb_cObject) { - rb_secure(4); - } - orig_fbody = search_method(klass, def, 0); - if (!orig_fbody || !orig_fbody->nd_body) { - if (TYPE(klass) == T_MODULE) { - orig_fbody = search_method(rb_cObject, def, 0); - } - } - if (!orig_fbody || !orig_fbody->nd_body) { - print_undef(klass, def); - } - if (FL_TEST(klass, FL_SINGLETON)) { - singleton = rb_iv_get(klass, "__attached__"); - } - - orig_fbody->nd_cnt++; - - if (st_lookup(RCLASS(klass)->m_tbl, name, (st_data_t *) & node)) { - if (node) { - if (RTEST(ruby_verbose) && node->nd_cnt == 0 && node->nd_body) { - rb_warning("discarding old %s", rb_id2name(name)); - } - if (nd_type(node->nd_body->nd_body) == NODE_CFUNC) { - rb_vm_check_redefinition_opt_method(node); - } - } - } - - st_insert(RCLASS(klass)->m_tbl, name, - (st_data_t) NEW_FBODY( - NEW_METHOD(orig_fbody->nd_body->nd_body, - orig_fbody->nd_body->nd_clss, - orig_fbody->nd_body->nd_noex), def)); - - rb_clear_cache_by_id(name); - - if (singleton) { - rb_funcall(singleton, singleton_added, 1, ID2SYM(name)); - } - else { - rb_funcall(klass, added, 1, ID2SYM(name)); - } -} - -/* - * call-seq: - * alias_method(new_name, old_name) => self - * - * Makes new_name a new copy of the method old_name. This can - * be used to retain access to methods that are overridden. - * - * module Mod - * alias_method :orig_exit, :exit - * def exit(code=0) - * puts "Exiting with code #{code}" - * orig_exit(code) - * end - * end - * include Mod - * exit(99) - * - * produces: - * - * Exiting with code 99 - */ - -static VALUE -rb_mod_alias_method(VALUE mod, VALUE newname, VALUE oldname) -{ - rb_alias(mod, rb_to_id(newname), rb_to_id(oldname)); - return mod; -} diff --git a/eval_safe.ci b/eval_safe.ci new file mode 100644 index 0000000000..aef5767da9 --- /dev/null +++ b/eval_safe.ci @@ -0,0 +1,109 @@ +/* + * This file is included by eval.c + */ + +/* safe-level: + 0 - strings from streams/environment/ARGV are tainted (default) + 1 - no dangerous operation by tainted value + 2 - process/file operations prohibited + 3 - all generated objects are tainted + 4 - no global (non-tainted) variable modification/no direct output +*/ + +#define SAFE_LEVEL_MAX 4 + +int +rb_safe_level(void) +{ + return GET_THREAD()->safe_level; +} + +void +rb_set_safe_level_force(int safe) +{ + GET_THREAD()->safe_level = safe; +} + +/* $SAFE accessor */ +void +rb_set_safe_level(int level) +{ + rb_thread_t *th = GET_THREAD(); + + if (level > th->safe_level) { + if (level > SAFE_LEVEL_MAX) { + level = SAFE_LEVEL_MAX; + } + th->safe_level = level; + } +} + +static VALUE +safe_getter(void) +{ + return INT2NUM(rb_safe_level()); +} + +static void +safe_setter(VALUE val) +{ + int level = NUM2INT(val); + rb_thread_t *th = GET_THREAD(); + + if (level < th->safe_level) { + rb_raise(rb_eSecurityError, + "tried to downgrade safe level from %d to %d", + th->safe_level, level); + } + if (level > SAFE_LEVEL_MAX) { + level = SAFE_LEVEL_MAX; + } + th->safe_level = level; +} + +void +rb_secure(int level) +{ + if (level <= rb_safe_level()) { + if (rb_frame_callee()) { + rb_raise(rb_eSecurityError, "Insecure operation `%s' at level %d", + rb_id2name(rb_frame_callee()), rb_safe_level()); + } + else { + rb_raise(rb_eSecurityError, "Insecure operation at level %d", + rb_safe_level()); + } + } +} + +void +rb_secure_update(VALUE obj) +{ + if (!OBJ_TAINTED(obj)) + rb_secure(4); +} + +void +rb_check_safe_obj(VALUE x) +{ + if (rb_safe_level() > 0 && OBJ_TAINTED(x)) { + if (rb_frame_callee()) { + rb_raise(rb_eSecurityError, "Insecure operation - %s", + rb_id2name(rb_frame_callee())); + } + else { + rb_raise(rb_eSecurityError, "Insecure operation: -r"); + } + } + rb_secure(4); +} + +void +rb_check_safe_str(VALUE x) +{ + rb_check_safe_obj(x); + if (TYPE(x) != T_STRING) { + rb_raise(rb_eTypeError, "wrong argument type %s (expected String)", + rb_obj_classname(x)); + } +} diff --git a/eval_safe.h b/eval_safe.h deleted file mode 100644 index 0566335bee..0000000000 --- a/eval_safe.h +++ /dev/null @@ -1,117 +0,0 @@ -/* - * This file is included by eval.c - */ - -/* safe-level: - 0 - strings from streams/environment/ARGV are tainted (default) - 1 - no dangerous operation by tainted value - 2 - process/file operations prohibited - 3 - all generated objects are tainted - 4 - no global (non-tainted) variable modification/no direct output -*/ - -int -rb_safe_level(void) -{ - return GET_THREAD()->safe_level; -} - -void -rb_set_safe_level_force(int safe) -{ - GET_THREAD()->safe_level = safe; -} - -static VALUE safe_getter _((void)); -static void safe_setter _((VALUE val)); - -#define PROC_TSHIFT (FL_USHIFT+1) -#define PROC_TMASK (FL_USER1|FL_USER2|FL_USER3) -#define PROC_TMAX (PROC_TMASK >> PROC_TSHIFT) -#define PROC_NOSAFE FL_USER4 - -#define SAFE_LEVEL_MAX PROC_TMASK - -/* $SAFE accessor */ -void -rb_set_safe_level(int level) -{ - rb_thread_t *th = GET_THREAD(); - - if (level > th->safe_level) { - if (level > SAFE_LEVEL_MAX) { - level = SAFE_LEVEL_MAX; - } - th->safe_level = level; - } -} - -static VALUE -safe_getter(void) -{ - return INT2NUM(rb_safe_level()); -} - -static void -safe_setter(VALUE val) -{ - int level = NUM2INT(val); - rb_thread_t *th = GET_THREAD(); - - if (level < th->safe_level) { - rb_raise(rb_eSecurityError, - "tried to downgrade safe level from %d to %d", - th->safe_level, level); - } - if (level > SAFE_LEVEL_MAX) { - level = SAFE_LEVEL_MAX; - } - th->safe_level = level; -} - -void -rb_secure(int level) -{ - if (level <= rb_safe_level()) { - if (rb_frame_callee()) { - rb_raise(rb_eSecurityError, "Insecure operation `%s' at level %d", - rb_id2name(rb_frame_callee()), rb_safe_level()); - } - else { - rb_raise(rb_eSecurityError, "Insecure operation at level %d", - rb_safe_level()); - } - } -} - -void -rb_secure_update(VALUE obj) -{ - if (!OBJ_TAINTED(obj)) - rb_secure(4); -} - -void -rb_check_safe_obj(VALUE x) -{ - if (rb_safe_level() > 0 && OBJ_TAINTED(x)) { - if (rb_frame_callee()) { - rb_raise(rb_eSecurityError, "Insecure operation - %s", - rb_id2name(rb_frame_callee())); - } - else { - rb_raise(rb_eSecurityError, "Insecure operation: -r"); - } - } - rb_secure(4); -} - -void -rb_check_safe_str(VALUE x) -{ - rb_check_safe_obj(x); - if (TYPE(x) != T_STRING) { - rb_raise(rb_eTypeError, "wrong argument type %s (expected String)", - rb_obj_classname(x)); - } -} diff --git a/proc.c b/proc.c index 18ffb76661..cb53a0f8ca 100644 --- a/proc.c +++ b/proc.c @@ -240,13 +240,6 @@ bind_eval(int argc, VALUE *argv, VALUE bindval) return rb_f_eval(argc+1, args, Qnil /* self will be searched in eval */); } -#define PROC_TSHIFT (FL_USHIFT+1) -#define PROC_TMASK (FL_USER1|FL_USER2|FL_USER3) -#define PROC_TMAX (PROC_TMASK >> PROC_TSHIFT) -#define PROC_NOSAFE FL_USER4 - -#define SAFE_LEVEL_MAX PROC_TMASK - static VALUE proc_new(VALUE klass, int is_lambda) { diff --git a/ruby.c b/ruby.c index fb9c5595d8..449df7a1e3 100644 --- a/ruby.c +++ b/ruby.c @@ -376,7 +376,6 @@ require_libraries(void) ruby_current_node = 0; Init_ext(); /* should be called here for some reason :-( */ ruby_current_node = save[1]; - ruby_set_current_source(); req_list_last = 0; while (list) { int state; @@ -390,7 +389,6 @@ require_libraries(void) free(list); list = tmp; ruby_current_node = save[1]; - ruby_set_current_source(); } req_list_head.next = 0; ruby_eval_tree = save[0]; -- cgit v1.2.3