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