00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "eval_intern.h"
00015 #include "iseq.h"
00016 #include "gc.h"
00017 #include "ruby/vm.h"
00018 #include "ruby/encoding.h"
00019 #include "internal.h"
00020 #include "vm_core.h"
00021
00022 #define numberof(array) (int)(sizeof(array) / sizeof((array)[0]))
00023
00024 NORETURN(void rb_raise_jump(VALUE));
00025
00026 VALUE rb_eLocalJumpError;
00027 VALUE rb_eSysStackError;
00028
00029 #define exception_error GET_VM()->special_exceptions[ruby_error_reenter]
00030
00031 #include "eval_error.c"
00032 #include "eval_jump.c"
00033
00034
00035
00036 void
00037 ruby_init(void)
00038 {
00039 static int initialized = 0;
00040 int state;
00041
00042 if (initialized)
00043 return;
00044 initialized = 1;
00045
00046 ruby_init_stack((void *)&state);
00047 Init_BareVM();
00048 Init_heap();
00049
00050 PUSH_TAG();
00051 if ((state = EXEC_TAG()) == 0) {
00052 rb_call_inits();
00053 ruby_prog_init();
00054 }
00055 POP_TAG();
00056
00057 if (state) {
00058 error_print();
00059 exit(EXIT_FAILURE);
00060 }
00061 GET_VM()->running = 1;
00062 }
00063
00064 void *
00065 ruby_options(int argc, char **argv)
00066 {
00067 int state;
00068 void *volatile iseq = 0;
00069
00070 ruby_init_stack((void *)&iseq);
00071 PUSH_TAG();
00072 if ((state = EXEC_TAG()) == 0) {
00073 SAVE_ROOT_JMPBUF(GET_THREAD(), iseq = ruby_process_options(argc, argv));
00074 }
00075 else {
00076 rb_clear_trace_func();
00077 state = error_handle(state);
00078 iseq = (void *)INT2FIX(state);
00079 }
00080 POP_TAG();
00081 return iseq;
00082 }
00083
00084 static void
00085 ruby_finalize_0(void)
00086 {
00087 PUSH_TAG();
00088 if (EXEC_TAG() == 0) {
00089 rb_trap_exit();
00090 }
00091 POP_TAG();
00092 rb_exec_end_proc();
00093 rb_clear_trace_func();
00094 }
00095
00096 static void
00097 ruby_finalize_1(void)
00098 {
00099 ruby_sig_finalize();
00100 GET_THREAD()->errinfo = Qnil;
00101 rb_gc_call_finalizer_at_exit();
00102 }
00103
00104 void
00105 ruby_finalize(void)
00106 {
00107 ruby_finalize_0();
00108 ruby_finalize_1();
00109 }
00110
00111 int
00112 ruby_cleanup(volatile int ex)
00113 {
00114 int state;
00115 volatile VALUE errs[2];
00116 rb_thread_t *th = GET_THREAD();
00117 int nerr;
00118
00119 rb_threadptr_interrupt(th);
00120 rb_threadptr_check_signal(th);
00121 PUSH_TAG();
00122 if ((state = EXEC_TAG()) == 0) {
00123 SAVE_ROOT_JMPBUF(th, { RUBY_VM_CHECK_INTS(); });
00124 }
00125 POP_TAG();
00126
00127 errs[1] = th->errinfo;
00128 th->safe_level = 0;
00129 ruby_init_stack(&errs[STACK_UPPER(errs, 0, 1)]);
00130
00131 PUSH_TAG();
00132 if ((state = EXEC_TAG()) == 0) {
00133 SAVE_ROOT_JMPBUF(th, ruby_finalize_0());
00134 }
00135 POP_TAG();
00136
00137 errs[0] = th->errinfo;
00138 PUSH_TAG();
00139 if ((state = EXEC_TAG()) == 0) {
00140 SAVE_ROOT_JMPBUF(th, rb_thread_terminate_all());
00141 }
00142 else if (ex == 0) {
00143 ex = state;
00144 }
00145 th->errinfo = errs[1];
00146 ex = error_handle(ex);
00147 ruby_finalize_1();
00148
00149
00150 rb_threadptr_unlock_all_locking_mutexes(GET_THREAD());
00151 POP_TAG();
00152 rb_thread_stop_timer_thread(1);
00153
00154 #if EXIT_SUCCESS != 0 || EXIT_FAILURE != 1
00155 switch (ex) {
00156 #if EXIT_SUCCESS != 0
00157 case 0: ex = EXIT_SUCCESS; break;
00158 #endif
00159 #if EXIT_FAILURE != 1
00160 case 1: ex = EXIT_FAILURE; break;
00161 #endif
00162 }
00163 #endif
00164
00165 state = 0;
00166 for (nerr = 0; nerr < numberof(errs); ++nerr) {
00167 VALUE err = errs[nerr];
00168
00169 if (!RTEST(err)) continue;
00170
00171
00172 if (TYPE(err) == T_NODE) continue;
00173
00174 if (rb_obj_is_kind_of(err, rb_eSystemExit)) {
00175 ex = sysexit_status(err);
00176 break;
00177 }
00178 else if (rb_obj_is_kind_of(err, rb_eSignal)) {
00179 VALUE sig = rb_iv_get(err, "signo");
00180 state = NUM2INT(sig);
00181 break;
00182 }
00183 else if (ex == EXIT_SUCCESS) {
00184 ex = EXIT_FAILURE;
00185 }
00186 }
00187 ruby_vm_destruct(GET_VM());
00188 if (state) ruby_default_signal(state);
00189
00190 return ex;
00191 }
00192
00193 static int
00194 ruby_exec_internal(void *n)
00195 {
00196 volatile int state;
00197 VALUE iseq = (VALUE)n;
00198 rb_thread_t *th = GET_THREAD();
00199
00200 if (!n) return 0;
00201
00202 PUSH_TAG();
00203 if ((state = EXEC_TAG()) == 0) {
00204 SAVE_ROOT_JMPBUF(th, {
00205 th->base_block = 0;
00206 rb_iseq_eval_main(iseq);
00207 });
00208 }
00209 POP_TAG();
00210 return state;
00211 }
00212
00213 void
00214 ruby_stop(int ex)
00215 {
00216 exit(ruby_cleanup(ex));
00217 }
00218
00219 int
00220 ruby_executable_node(void *n, int *status)
00221 {
00222 VALUE v = (VALUE)n;
00223 int s;
00224
00225 switch (v) {
00226 case Qtrue: s = EXIT_SUCCESS; break;
00227 case Qfalse: s = EXIT_FAILURE; break;
00228 default:
00229 if (!FIXNUM_P(v)) return TRUE;
00230 s = FIX2INT(v);
00231 }
00232 if (status) *status = s;
00233 return FALSE;
00234 }
00235
00236 int
00237 ruby_run_node(void *n)
00238 {
00239 int status;
00240 if (!ruby_executable_node(n, &status)) {
00241 ruby_cleanup(0);
00242 return status;
00243 }
00244 return ruby_cleanup(ruby_exec_node(n));
00245 }
00246
00247 int
00248 ruby_exec_node(void *n)
00249 {
00250 ruby_init_stack((void *)&n);
00251 return ruby_exec_internal(n);
00252 }
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269 static VALUE
00270 rb_mod_nesting(void)
00271 {
00272 VALUE ary = rb_ary_new();
00273 const NODE *cref = rb_vm_cref();
00274
00275 while (cref && cref->nd_next) {
00276 VALUE klass = cref->nd_clss;
00277 if (!(cref->flags & NODE_FL_CREF_PUSHED_BY_EVAL) &&
00278 !NIL_P(klass)) {
00279 rb_ary_push(ary, klass);
00280 }
00281 cref = cref->nd_next;
00282 }
00283 return ary;
00284 }
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308 static VALUE
00309 rb_mod_s_constants(int argc, VALUE *argv, VALUE mod)
00310 {
00311 const NODE *cref = rb_vm_cref();
00312 VALUE klass;
00313 VALUE cbase = 0;
00314 void *data = 0;
00315
00316 if (argc > 0 || mod != rb_cModule) {
00317 return rb_mod_constants(argc, argv, mod);
00318 }
00319
00320 while (cref) {
00321 klass = cref->nd_clss;
00322 if (!(cref->flags & NODE_FL_CREF_PUSHED_BY_EVAL) &&
00323 !NIL_P(klass)) {
00324 data = rb_mod_const_at(cref->nd_clss, data);
00325 if (!cbase) {
00326 cbase = klass;
00327 }
00328 }
00329 cref = cref->nd_next;
00330 }
00331
00332 if (cbase) {
00333 data = rb_mod_const_of(cbase, data);
00334 }
00335 return rb_const_list(data);
00336 }
00337
00338 void
00339 rb_frozen_class_p(VALUE klass)
00340 {
00341 const char *desc = "something(?!)";
00342
00343 if (OBJ_FROZEN(klass)) {
00344 if (FL_TEST(klass, FL_SINGLETON))
00345 desc = "object";
00346 else {
00347 switch (TYPE(klass)) {
00348 case T_MODULE:
00349 case T_ICLASS:
00350 desc = "module";
00351 break;
00352 case T_CLASS:
00353 desc = "class";
00354 break;
00355 }
00356 }
00357 rb_error_frozen(desc);
00358 }
00359 }
00360
00361 NORETURN(static void rb_longjmp(int, volatile VALUE));
00362
00363 static void
00364 setup_exception(rb_thread_t *th, int tag, volatile VALUE mesg)
00365 {
00366 VALUE at;
00367 VALUE e;
00368 const char *file;
00369 volatile int line = 0;
00370
00371 if (NIL_P(mesg)) {
00372 mesg = th->errinfo;
00373 if (INTERNAL_EXCEPTION_P(mesg)) JUMP_TAG(TAG_FATAL);
00374 }
00375 if (NIL_P(mesg)) {
00376 mesg = rb_exc_new(rb_eRuntimeError, 0, 0);
00377 }
00378
00379 file = rb_sourcefile();
00380 if (file) line = rb_sourceline();
00381 if (file && !NIL_P(mesg)) {
00382 if (mesg == sysstack_error) {
00383 at = rb_enc_sprintf(rb_usascii_encoding(), "%s:%d", file, line);
00384 at = rb_ary_new3(1, at);
00385 rb_iv_set(mesg, "bt", at);
00386 }
00387 else {
00388 at = get_backtrace(mesg);
00389 if (NIL_P(at)) {
00390 at = rb_make_backtrace();
00391 if (OBJ_FROZEN(mesg)) {
00392 mesg = rb_obj_dup(mesg);
00393 }
00394 set_backtrace(mesg, at);
00395 }
00396 }
00397 }
00398 if (!NIL_P(mesg)) {
00399 th->errinfo = mesg;
00400 }
00401
00402 if (RTEST(ruby_debug) && !NIL_P(e = th->errinfo) &&
00403 !rb_obj_is_kind_of(e, rb_eSystemExit)) {
00404 int status;
00405
00406 PUSH_TAG();
00407 if ((status = EXEC_TAG()) == 0) {
00408 RB_GC_GUARD(e) = rb_obj_as_string(e);
00409 if (file && line) {
00410 warn_printf("Exception `%s' at %s:%d - %s\n",
00411 rb_obj_classname(th->errinfo),
00412 file, line, RSTRING_PTR(e));
00413 }
00414 else if (file) {
00415 warn_printf("Exception `%s' at %s - %s\n",
00416 rb_obj_classname(th->errinfo),
00417 file, RSTRING_PTR(e));
00418 }
00419 else {
00420 warn_printf("Exception `%s' - %s\n",
00421 rb_obj_classname(th->errinfo),
00422 RSTRING_PTR(e));
00423 }
00424 }
00425 POP_TAG();
00426 if (status == TAG_FATAL && th->errinfo == exception_error) {
00427 th->errinfo = mesg;
00428 }
00429 else if (status) {
00430 rb_threadptr_reset_raised(th);
00431 JUMP_TAG(status);
00432 }
00433 }
00434
00435 if (rb_threadptr_set_raised(th)) {
00436 th->errinfo = exception_error;
00437 rb_threadptr_reset_raised(th);
00438 JUMP_TAG(TAG_FATAL);
00439 }
00440
00441 rb_trap_restore_mask();
00442
00443 if (tag != TAG_FATAL) {
00444 EXEC_EVENT_HOOK(th, RUBY_EVENT_RAISE, th->cfp->self, 0, 0);
00445 }
00446 }
00447
00448 static void
00449 rb_longjmp(int tag, volatile VALUE mesg)
00450 {
00451 rb_thread_t *th = GET_THREAD();
00452 setup_exception(th, tag, mesg);
00453 rb_thread_raised_clear(th);
00454 JUMP_TAG(tag);
00455 }
00456
00457 static VALUE make_exception(int argc, VALUE *argv, int isstr);
00458
00459 void
00460 rb_exc_raise(VALUE mesg)
00461 {
00462 if (!NIL_P(mesg)) {
00463 mesg = make_exception(1, &mesg, FALSE);
00464 }
00465 rb_longjmp(TAG_RAISE, mesg);
00466 }
00467
00468 void
00469 rb_exc_fatal(VALUE mesg)
00470 {
00471 if (!NIL_P(mesg)) {
00472 mesg = make_exception(1, &mesg, FALSE);
00473 }
00474 rb_longjmp(TAG_FATAL, mesg);
00475 }
00476
00477 void
00478 rb_interrupt(void)
00479 {
00480 rb_raise(rb_eInterrupt, "%s", "");
00481 }
00482
00483 static VALUE get_errinfo(void);
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509 static VALUE
00510 rb_f_raise(int argc, VALUE *argv)
00511 {
00512 VALUE err;
00513 if (argc == 0) {
00514 err = get_errinfo();
00515 if (!NIL_P(err)) {
00516 argc = 1;
00517 argv = &err;
00518 }
00519 }
00520 rb_raise_jump(rb_make_exception(argc, argv));
00521 return Qnil;
00522 }
00523
00524 static VALUE
00525 make_exception(int argc, VALUE *argv, int isstr)
00526 {
00527 VALUE mesg;
00528 ID exception;
00529 int n;
00530
00531 mesg = Qnil;
00532 switch (argc) {
00533 case 0:
00534 break;
00535 case 1:
00536 if (NIL_P(argv[0]))
00537 break;
00538 if (isstr) {
00539 mesg = rb_check_string_type(argv[0]);
00540 if (!NIL_P(mesg)) {
00541 mesg = rb_exc_new3(rb_eRuntimeError, mesg);
00542 break;
00543 }
00544 }
00545 n = 0;
00546 goto exception_call;
00547
00548 case 2:
00549 case 3:
00550 n = 1;
00551 exception_call:
00552 if (argv[0] == sysstack_error) return argv[0];
00553 CONST_ID(exception, "exception");
00554 mesg = rb_check_funcall(argv[0], exception, n, argv+1);
00555 if (mesg == Qundef) {
00556 rb_raise(rb_eTypeError, "exception class/object expected");
00557 }
00558 break;
00559 default:
00560 rb_raise(rb_eArgError, "wrong number of arguments (%d for 0..3)", argc);
00561 break;
00562 }
00563 if (argc > 0) {
00564 if (!rb_obj_is_kind_of(mesg, rb_eException))
00565 rb_raise(rb_eTypeError, "exception object expected");
00566 if (argc > 2)
00567 set_backtrace(mesg, argv[2]);
00568 }
00569
00570 return mesg;
00571 }
00572
00573 VALUE
00574 rb_make_exception(int argc, VALUE *argv)
00575 {
00576 return make_exception(argc, argv, TRUE);
00577 }
00578
00579 void
00580 rb_raise_jump(VALUE mesg)
00581 {
00582 rb_thread_t *th = GET_THREAD();
00583 rb_control_frame_t *cfp = th->cfp;
00584 VALUE klass = cfp->me->klass;
00585 VALUE self = cfp->self;
00586 ID mid = cfp->me->called_id;
00587
00588 th->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp);
00589
00590 setup_exception(th, TAG_RAISE, mesg);
00591
00592 EXEC_EVENT_HOOK(th, RUBY_EVENT_C_RETURN, self, mid, klass);
00593 rb_thread_raised_clear(th);
00594 JUMP_TAG(TAG_RAISE);
00595 }
00596
00597 void
00598 rb_jump_tag(int tag)
00599 {
00600 JUMP_TAG(tag);
00601 }
00602
00603 int
00604 rb_block_given_p(void)
00605 {
00606 rb_thread_t *th = GET_THREAD();
00607
00608 if ((th->cfp->lfp[0] & 0x02) == 0 &&
00609 GC_GUARDED_PTR_REF(th->cfp->lfp[0])) {
00610 return TRUE;
00611 }
00612 else {
00613 return FALSE;
00614 }
00615 }
00616
00617 int
00618 rb_iterator_p(void)
00619 {
00620 return rb_block_given_p();
00621 }
00622
00623 VALUE rb_eThreadError;
00624
00625 void
00626 rb_need_block(void)
00627 {
00628 if (!rb_block_given_p()) {
00629 rb_vm_localjump_error("no block given", Qnil, 0);
00630 }
00631 }
00632
00633 VALUE
00634 rb_rescue2(VALUE (* b_proc) (ANYARGS), VALUE data1,
00635 VALUE (* r_proc) (ANYARGS), VALUE data2, ...)
00636 {
00637 int state;
00638 rb_thread_t *th = GET_THREAD();
00639 rb_control_frame_t *cfp = th->cfp;
00640 volatile VALUE result;
00641 volatile VALUE e_info = th->errinfo;
00642 va_list args;
00643
00644 PUSH_TAG();
00645 if ((state = EXEC_TAG()) == 0) {
00646 retry_entry:
00647 result = (*b_proc) (data1);
00648 }
00649 else {
00650 th->cfp = cfp;
00651
00652 if (state == TAG_RAISE) {
00653 int handle = FALSE;
00654 VALUE eclass;
00655
00656 va_init_list(args, data2);
00657 while ((eclass = va_arg(args, VALUE)) != 0) {
00658 if (rb_obj_is_kind_of(th->errinfo, eclass)) {
00659 handle = TRUE;
00660 break;
00661 }
00662 }
00663 va_end(args);
00664
00665 if (handle) {
00666 if (r_proc) {
00667 PUSH_TAG();
00668 if ((state = EXEC_TAG()) == 0) {
00669 result = (*r_proc) (data2, th->errinfo);
00670 }
00671 POP_TAG();
00672 if (state == TAG_RETRY) {
00673 state = 0;
00674 th->errinfo = Qnil;
00675 goto retry_entry;
00676 }
00677 }
00678 else {
00679 result = Qnil;
00680 state = 0;
00681 }
00682 if (state == 0) {
00683 th->errinfo = e_info;
00684 }
00685 }
00686 }
00687 }
00688 POP_TAG();
00689 if (state)
00690 JUMP_TAG(state);
00691
00692 return result;
00693 }
00694
00695 VALUE
00696 rb_rescue(VALUE (* b_proc)(ANYARGS), VALUE data1,
00697 VALUE (* r_proc)(ANYARGS), VALUE data2)
00698 {
00699 return rb_rescue2(b_proc, data1, r_proc, data2, rb_eStandardError,
00700 (VALUE)0);
00701 }
00702
00703 VALUE
00704 rb_protect(VALUE (* proc) (VALUE), VALUE data, int * state)
00705 {
00706 volatile VALUE result = Qnil;
00707 int status;
00708 rb_thread_t *th = GET_THREAD();
00709 rb_control_frame_t *cfp = th->cfp;
00710 struct rb_vm_protect_tag protect_tag;
00711 rb_jmpbuf_t org_jmpbuf;
00712
00713 protect_tag.prev = th->protect_tag;
00714
00715 PUSH_TAG();
00716 th->protect_tag = &protect_tag;
00717 MEMCPY(&org_jmpbuf, &(th)->root_jmpbuf, rb_jmpbuf_t, 1);
00718 if ((status = EXEC_TAG()) == 0) {
00719 SAVE_ROOT_JMPBUF(th, result = (*proc) (data));
00720 }
00721 MEMCPY(&(th)->root_jmpbuf, &org_jmpbuf, rb_jmpbuf_t, 1);
00722 th->protect_tag = protect_tag.prev;
00723 POP_TAG();
00724
00725 if (state) {
00726 *state = status;
00727 }
00728 if (status != 0) {
00729 th->cfp = cfp;
00730 return Qnil;
00731 }
00732
00733 return result;
00734 }
00735
00736 VALUE
00737 rb_ensure(VALUE (*b_proc)(ANYARGS), VALUE data1, VALUE (*e_proc)(ANYARGS), VALUE data2)
00738 {
00739 int state;
00740 volatile VALUE result = Qnil;
00741
00742 PUSH_TAG();
00743 if ((state = EXEC_TAG()) == 0) {
00744 result = (*b_proc) (data1);
00745 }
00746 POP_TAG();
00747
00748
00749 (*e_proc) (data2);
00750 if (state)
00751 JUMP_TAG(state);
00752 return result;
00753 }
00754
00755 static const rb_method_entry_t *
00756 method_entry_of_iseq(rb_control_frame_t *cfp, rb_iseq_t *iseq)
00757 {
00758 rb_thread_t *th = GET_THREAD();
00759 rb_control_frame_t *cfp_limit;
00760
00761 cfp_limit = (rb_control_frame_t *)(th->stack + th->stack_size);
00762 while (cfp_limit > cfp) {
00763 if (cfp->iseq == iseq)
00764 return cfp->me;
00765 cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
00766 }
00767 return 0;
00768 }
00769
00770 static ID
00771 frame_func_id(rb_control_frame_t *cfp)
00772 {
00773 const rb_method_entry_t *me_local;
00774 rb_iseq_t *iseq = cfp->iseq;
00775 if (cfp->me) {
00776 return cfp->me->def->original_id;
00777 }
00778 while (iseq) {
00779 if (RUBY_VM_IFUNC_P(iseq)) {
00780 NODE *ifunc = (NODE *)iseq;
00781 if (ifunc->nd_aid) return ifunc->nd_aid;
00782 return rb_intern("<ifunc>");
00783 }
00784 me_local = method_entry_of_iseq(cfp, iseq);
00785 if (me_local) {
00786 cfp->me = me_local;
00787 return me_local->def->original_id;
00788 }
00789 if (iseq->defined_method_id) {
00790 return iseq->defined_method_id;
00791 }
00792 if (iseq->local_iseq == iseq) {
00793 break;
00794 }
00795 iseq = iseq->parent_iseq;
00796 }
00797 return 0;
00798 }
00799
00800 ID
00801 rb_frame_this_func(void)
00802 {
00803 return frame_func_id(GET_THREAD()->cfp);
00804 }
00805
00806 ID
00807 rb_frame_callee(void)
00808 {
00809 return frame_func_id(GET_THREAD()->cfp);
00810 }
00811
00812 static ID
00813 rb_frame_caller(void)
00814 {
00815 rb_thread_t *th = GET_THREAD();
00816 rb_control_frame_t *prev_cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp);
00817
00818 if ((void *)(th->stack + th->stack_size) == (void *)(prev_cfp)) {
00819 return 0;
00820 }
00821 return frame_func_id(prev_cfp);
00822 }
00823
00824 void
00825 rb_frame_pop(void)
00826 {
00827 rb_thread_t *th = GET_THREAD();
00828 th->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp);
00829 }
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843 static VALUE
00844 rb_mod_append_features(VALUE module, VALUE include)
00845 {
00846 switch (TYPE(include)) {
00847 case T_CLASS:
00848 case T_MODULE:
00849 break;
00850 default:
00851 Check_Type(include, T_CLASS);
00852 break;
00853 }
00854 rb_include_module(include, module);
00855
00856 return module;
00857 }
00858
00859
00860
00861
00862
00863
00864
00865
00866 static VALUE
00867 rb_mod_include(int argc, VALUE *argv, VALUE module)
00868 {
00869 int i;
00870
00871 for (i = 0; i < argc; i++)
00872 Check_Type(argv[i], T_MODULE);
00873 while (argc--) {
00874 rb_funcall(argv[argc], rb_intern("append_features"), 1, module);
00875 rb_funcall(argv[argc], rb_intern("included"), 1, module);
00876 }
00877 return module;
00878 }
00879
00880 void
00881 rb_obj_call_init(VALUE obj, int argc, VALUE *argv)
00882 {
00883 PASS_PASSED_BLOCK();
00884 rb_funcall2(obj, idInitialize, argc, argv);
00885 }
00886
00887 void
00888 rb_extend_object(VALUE obj, VALUE module)
00889 {
00890 rb_include_module(rb_singleton_class(obj), module);
00891 }
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920 static VALUE
00921 rb_mod_extend_object(VALUE mod, VALUE obj)
00922 {
00923 rb_extend_object(obj, mod);
00924 return obj;
00925 }
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952 static VALUE
00953 rb_obj_extend(int argc, VALUE *argv, VALUE obj)
00954 {
00955 int i;
00956
00957 if (argc == 0) {
00958 rb_raise(rb_eArgError, "wrong number of arguments (at least 1)");
00959 }
00960 for (i = 0; i < argc; i++)
00961 Check_Type(argv[i], T_MODULE);
00962 while (argc--) {
00963 rb_funcall(argv[argc], rb_intern("extend_object"), 1, obj);
00964 rb_funcall(argv[argc], rb_intern("extended"), 1, obj);
00965 }
00966 return obj;
00967 }
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978 static VALUE
00979 top_include(int argc, VALUE *argv, VALUE self)
00980 {
00981 rb_thread_t *th = GET_THREAD();
00982
00983 rb_secure(4);
00984 if (th->top_wrapper) {
00985 rb_warning
00986 ("main#include in the wrapped load is effective only in wrapper module");
00987 return rb_mod_include(argc, argv, th->top_wrapper);
00988 }
00989 return rb_mod_include(argc, argv, rb_cObject);
00990 }
00991
00992 static VALUE *
00993 errinfo_place(rb_thread_t *th)
00994 {
00995 rb_control_frame_t *cfp = th->cfp;
00996 rb_control_frame_t *end_cfp = RUBY_VM_END_CONTROL_FRAME(th);
00997
00998 while (RUBY_VM_VALID_CONTROL_FRAME_P(cfp, end_cfp)) {
00999 if (RUBY_VM_NORMAL_ISEQ_P(cfp->iseq)) {
01000 if (cfp->iseq->type == ISEQ_TYPE_RESCUE) {
01001 return &cfp->dfp[-2];
01002 }
01003 else if (cfp->iseq->type == ISEQ_TYPE_ENSURE &&
01004 TYPE(cfp->dfp[-2]) != T_NODE &&
01005 !FIXNUM_P(cfp->dfp[-2])) {
01006 return &cfp->dfp[-2];
01007 }
01008 }
01009 cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
01010 }
01011 return 0;
01012 }
01013
01014 static VALUE
01015 get_thread_errinfo(rb_thread_t *th)
01016 {
01017 VALUE *ptr = errinfo_place(th);
01018 if (ptr) {
01019 return *ptr;
01020 }
01021 else {
01022 return th->errinfo;
01023 }
01024 }
01025
01026 static VALUE
01027 get_errinfo(void)
01028 {
01029 return get_thread_errinfo(GET_THREAD());
01030 }
01031
01032 static VALUE
01033 errinfo_getter(ID id)
01034 {
01035 return get_errinfo();
01036 }
01037
01038 #if 0
01039 static void
01040 errinfo_setter(VALUE val, ID id, VALUE *var)
01041 {
01042 if (!NIL_P(val) && !rb_obj_is_kind_of(val, rb_eException)) {
01043 rb_raise(rb_eTypeError, "assigning non-exception to $!");
01044 }
01045 else {
01046 VALUE *ptr = errinfo_place(GET_THREAD());
01047 if (ptr) {
01048 *ptr = val;
01049 }
01050 else {
01051 rb_raise(rb_eRuntimeError, "errinfo_setter: not in rescue clause.");
01052 }
01053 }
01054 }
01055 #endif
01056
01057 VALUE
01058 rb_errinfo(void)
01059 {
01060 rb_thread_t *th = GET_THREAD();
01061 return th->errinfo;
01062 }
01063
01064 void
01065 rb_set_errinfo(VALUE err)
01066 {
01067 if (!NIL_P(err) && !rb_obj_is_kind_of(err, rb_eException)) {
01068 rb_raise(rb_eTypeError, "assigning non-exception to $!");
01069 }
01070 GET_THREAD()->errinfo = err;
01071 }
01072
01073 VALUE
01074 rb_rubylevel_errinfo(void)
01075 {
01076 return get_errinfo();
01077 }
01078
01079 static VALUE
01080 errat_getter(ID id)
01081 {
01082 VALUE err = get_errinfo();
01083 if (!NIL_P(err)) {
01084 return get_backtrace(err);
01085 }
01086 else {
01087 return Qnil;
01088 }
01089 }
01090
01091 static void
01092 errat_setter(VALUE val, ID id, VALUE *var)
01093 {
01094 VALUE err = get_errinfo();
01095 if (NIL_P(err)) {
01096 rb_raise(rb_eArgError, "$! not set");
01097 }
01098 set_backtrace(err, val);
01099 }
01100
01101
01102
01103
01104
01105
01106
01107
01108
01109
01110
01111 static VALUE
01112 rb_f_method_name(void)
01113 {
01114 ID fname = rb_frame_caller();
01115
01116 if (fname) {
01117 return ID2SYM(fname);
01118 }
01119 else {
01120 return Qnil;
01121 }
01122 }
01123
01124 void
01125 Init_eval(void)
01126 {
01127 rb_define_virtual_variable("$@", errat_getter, errat_setter);
01128 rb_define_virtual_variable("$!", errinfo_getter, 0);
01129
01130 rb_define_global_function("raise", rb_f_raise, -1);
01131 rb_define_global_function("fail", rb_f_raise, -1);
01132
01133 rb_define_global_function("global_variables", rb_f_global_variables, 0);
01134
01135 rb_define_global_function("__method__", rb_f_method_name, 0);
01136 rb_define_global_function("__callee__", rb_f_method_name, 0);
01137
01138 rb_define_private_method(rb_cModule, "append_features", rb_mod_append_features, 1);
01139 rb_define_private_method(rb_cModule, "extend_object", rb_mod_extend_object, 1);
01140 rb_define_private_method(rb_cModule, "include", rb_mod_include, -1);
01141
01142 rb_undef_method(rb_cClass, "module_function");
01143
01144 Init_vm_eval();
01145 Init_eval_method();
01146
01147 rb_define_singleton_method(rb_cModule, "nesting", rb_mod_nesting, 0);
01148 rb_define_singleton_method(rb_cModule, "constants", rb_mod_s_constants, -1);
01149
01150 rb_define_singleton_method(rb_vm_top_self(), "include", top_include, -1);
01151
01152 rb_define_method(rb_mKernel, "extend", rb_obj_extend, -1);
01153
01154 rb_define_global_function("trace_var", rb_f_trace_var, -1);
01155 rb_define_global_function("untrace_var", rb_f_untrace_var, -1);
01156
01157 exception_error = rb_exc_new3(rb_eFatal,
01158 rb_obj_freeze(rb_str_new2("exception reentered")));
01159 OBJ_TAINT(exception_error);
01160 OBJ_FREEZE(exception_error);
01161 }
01162