Feature #3917 » 0001-add-Kernel-called_from-which-is-similar-to-caller.patch
vm.c | ||
---|---|---|
return TRUE;
|
||
}
|
||
static VALUE
|
||
vm_backtrace_get_location(rb_thread_t *th, int lev)
|
||
{
|
||
const rb_control_frame_t *limit_cfp = th->cfp;
|
||
const rb_control_frame_t *cfp = (void *)(th->stack + th->stack_size);
|
||
int line_no;
|
||
VALUE filename, name;
|
||
cfp -= 2;
|
||
while (lev-- >= 0) {
|
||
if (++limit_cfp > cfp) {
|
||
return Qnil;
|
||
}
|
||
}
|
||
if (limit_cfp->iseq == NULL) {
|
||
return Qnil;
|
||
}
|
||
line_no = rb_vm_get_sourceline(limit_cfp);
|
||
filename = limit_cfp->iseq->filename;
|
||
name = limit_cfp->iseq->name;
|
||
return rb_ary_new3(3, filename, line_no ? INT2NUM(line_no) : Qnil, name);
|
||
}
|
||
static void
|
||
vm_backtrace_alloc(void *arg)
|
||
{
|
vm_eval.c | ||
---|---|---|
static inline VALUE vm_backtrace(rb_thread_t *th, int lev);
|
||
static int vm_backtrace_each(rb_thread_t *th, int lev, void (*init)(void *), rb_backtrace_iter_func *iter, void *arg);
|
||
static NODE *vm_cref_push(rb_thread_t *th, VALUE klass, int noex, rb_block_t *blockptr);
|
||
static VALUE vm_backtrace_get_location(rb_thread_t *th, int lev);
|
||
static VALUE vm_exec(rb_thread_t *th);
|
||
static void vm_set_eval_stack(rb_thread_t * th, VALUE iseqval, const NODE *cref);
|
||
static int vm_collect_local_variables_in_heap(rb_thread_t *th, VALUE *dfp, VALUE ary);
|
||
... | ... | |
return vm_backtrace(GET_THREAD(), lev);
|
||
}
|
||
/*
|
||
* call-seq:
|
||
* called_from(start=1) -> array or nil
|
||
*
|
||
* Returns file name, line number, and method name of the stack.
|
||
* The optional _start_ parameter represents the number of stack
|
||
* entries to skip.
|
||
*
|
||
* Returns +nil+ if _start_ is greater than the size of
|
||
* current execution stack.
|
||
*
|
||
* Raises ArgumentError if _start_ is negative value.
|
||
*
|
||
* # example.rb
|
||
* 1: def f1()
|
||
* 2: f2()
|
||
* 3: end
|
||
* 4: def f2()
|
||
* 5: f3()
|
||
* 6: end
|
||
* 7: def f3()
|
||
* 8: p called_from() #=> ["example.rb", 5, "f2"]
|
||
* 9: p called_from(0) #=> ["example.rb", 9, "f3"]
|
||
* 10: p called_from(1) #=> ["example.rb", 5, "f2"]
|
||
* 11: p called_from(2) #=> ["example.rb", 2, "f1"]
|
||
* 12: p called_from(3) #=> ["example.rb", 15, "<main>"]
|
||
* 13: p called_from(4) #=> nil
|
||
* 14: end
|
||
* 15: f1()
|
||
*/
|
||
static VALUE
|
||
rb_f_called_from(int argc, VALUE *argv)
|
||
{
|
||
VALUE level;
|
||
int lev;
|
||
VALUE ary = Qnil;
|
||
rb_scan_args(argc, argv, "01", &level);
|
||
lev = NIL_P(level) ? 1 : NUM2INT(level);
|
||
if (lev < 0) rb_raise(rb_eArgError, "negative level (%d)", lev);
|
||
return vm_backtrace_get_location(GET_THREAD(), lev);
|
||
}
|
||
static int
|
||
print_backtrace(void *arg, VALUE file, int line, VALUE method)
|
||
{
|
||
... | ... | |
rb_define_method(rb_cModule, "class_eval", rb_mod_module_eval, -1);
|
||
rb_define_global_function("caller", rb_f_caller, -1);
|
||
rb_define_global_function("called_from", rb_f_called_from, -1);
|
||
}
|
||