Project

General

Profile

Feature #3917 ยป 0001-add-Kernel-called_from-which-is-similar-to-caller.patch

code (patch for 1.9.2-p0) - kwatch (makoto kuwata), 10/08/2010 08:45 AM

View differences:

vm.c
748 748
    return TRUE;
749 749
}
750 750

  
751
static VALUE
752
vm_backtrace_get_location(rb_thread_t *th, int lev)
753
{
754
    const rb_control_frame_t *limit_cfp = th->cfp;
755
    const rb_control_frame_t *cfp = (void *)(th->stack + th->stack_size);
756
    int line_no;
757
    VALUE filename, name;
758

  
759
    cfp -= 2;
760
    while (lev-- >= 0) {
761
	if (++limit_cfp > cfp) {
762
	    return Qnil;
763
	}
764
    }
765
    if (limit_cfp->iseq == NULL) {
766
	return Qnil;
767
    }
768
    line_no  = rb_vm_get_sourceline(limit_cfp);
769
    filename = limit_cfp->iseq->filename;
770
    name     = limit_cfp->iseq->name;
771
    return rb_ary_new3(3, filename, line_no ? INT2NUM(line_no) : Qnil, name);
772
}
773

  
751 774
static void
752 775
vm_backtrace_alloc(void *arg)
753 776
{
vm_eval.c
18 18
static inline VALUE vm_backtrace(rb_thread_t *th, int lev);
19 19
static int vm_backtrace_each(rb_thread_t *th, int lev, void (*init)(void *), rb_backtrace_iter_func *iter, void *arg);
20 20
static NODE *vm_cref_push(rb_thread_t *th, VALUE klass, int noex, rb_block_t *blockptr);
21
static VALUE vm_backtrace_get_location(rb_thread_t *th, int lev);
21 22
static VALUE vm_exec(rb_thread_t *th);
22 23
static void vm_set_eval_stack(rb_thread_t * th, VALUE iseqval, const NODE *cref);
23 24
static int vm_collect_local_variables_in_heap(rb_thread_t *th, VALUE *dfp, VALUE ary);
......
1583 1584
    return vm_backtrace(GET_THREAD(), lev);
1584 1585
}
1585 1586

  
1587
/*
1588
 *  call-seq:
1589
 *     called_from(start=1)    -> array or nil
1590
 *
1591
 *  Returns file name, line number, and method name of the stack.
1592
 *  The optional _start_ parameter represents the number of stack
1593
 *  entries to skip.
1594
 *
1595
 *  Returns +nil+ if _start_ is greater than the size of
1596
 *  current execution stack.
1597
 *
1598
 *  Raises ArgumentError if _start_ is negative value.
1599
 *
1600
 *     # example.rb
1601
 *      1:  def f1()
1602
 *      2:    f2()
1603
 *      3:  end
1604
 *      4:  def f2()
1605
 *      5:    f3()
1606
 *      6:  end
1607
 *      7:  def f3()
1608
 *      8:    p called_from()    #=> ["example.rb", 5, "f2"]
1609
 *      9:    p called_from(0)   #=> ["example.rb", 9, "f3"]
1610
 *     10:    p called_from(1)   #=> ["example.rb", 5, "f2"]
1611
 *     11:    p called_from(2)   #=> ["example.rb", 2, "f1"]
1612
 *     12:    p called_from(3)   #=> ["example.rb", 15, "<main>"]
1613
 *     13:    p called_from(4)   #=> nil
1614
 *     14:  end
1615
 *     15:  f1()
1616
 */
1617
static VALUE
1618
rb_f_called_from(int argc, VALUE *argv)
1619
{
1620
    VALUE level;
1621
    int lev;
1622
    VALUE ary = Qnil;
1623

  
1624
    rb_scan_args(argc, argv, "01", &level);
1625
    lev = NIL_P(level) ? 1 : NUM2INT(level);
1626
    if (lev < 0) rb_raise(rb_eArgError, "negative level (%d)", lev);
1627

  
1628
    return vm_backtrace_get_location(GET_THREAD(), lev);
1629
}
1630

  
1586 1631
static int
1587 1632
print_backtrace(void *arg, VALUE file, int line, VALUE method)
1588 1633
{
......
1774 1819
    rb_define_method(rb_cModule, "class_eval", rb_mod_module_eval, -1);
1775 1820

  
1776 1821
    rb_define_global_function("caller", rb_f_caller, -1);
1822
    rb_define_global_function("called_from", rb_f_called_from, -1);
1777 1823
}
1778 1824

  
1779
-