Class: Debugger::Context

Inherits:
Object
  • Object
show all
Defined in:
lib/ruby-debug-base.rb,
lib/debugger/test/context.rb,
ext/ruby_debug/192/ruby_debug.c,
ext/ruby_debug/193/ruby_debug.c,
ext/ruby_debug/200/ruby_debug.c,
ext/ruby_debug/210/ruby_debug.c

Instance Method Summary collapse

Instance Method Details

#__c_frame_bindingObject



19
# File 'lib/ruby-debug-base.rb', line 19

alias __c_frame_binding frame_binding

#breakpointObject

Returns a context-specific temporary Breakpoint object.



267
268
269
270
271
272
273
274
275
276
# File 'ext/ruby_debug/192/breakpoint.c', line 267

VALUE
context_breakpoint(VALUE self)
{
    debug_context_t *debug_context;

    debug_check_started();

    Data_Get_Struct(self, debug_context_t, debug_context);
    return debug_context->breakpoint;
}

#dead?Boolean

Returns true if context doesn’t represent a live context and is created during post-mortem exception handling.

Returns:

  • (Boolean)


2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
# File 'ext/ruby_debug/192/ruby_debug.c', line 2277

static VALUE
context_dead(VALUE self)
{
    debug_context_t *debug_context;

    debug_check_started();

    Data_Get_Struct(self, debug_context_t, debug_context);
    return CTX_FL_TEST(debug_context, CTX_FL_DEAD) ? Qtrue : Qfalse;
}

#frame_args(frame_position = 0) ⇒ Object

Returns frame’s argument parameters



2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
# File 'ext/ruby_debug/192/ruby_debug.c', line 2010

static VALUE
context_frame_args(int argc, VALUE *argv, VALUE self)
{
    VALUE frame;
    debug_context_t *debug_context;
    debug_frame_t *debug_frame;

    debug_check_started();
    frame = optional_frame_position(argc, argv);
    Data_Get_Struct(self, debug_context_t, debug_context);

    debug_frame = GET_FRAME;
    if (debug_frame->dead)
        return debug_frame->info.copy.args;
    else
        return context_copy_args(debug_frame);
}

#frame_args_info(frame_position = 0) ⇒ Object #track_frame_argsObject

Returns info saved about call arguments (if any saved).



1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
# File 'ext/ruby_debug/192/ruby_debug.c', line 1742

static VALUE
context_frame_args_info(int argc, VALUE *argv, VALUE self)
{
    VALUE frame;
    debug_context_t *debug_context;

    debug_check_started();
    frame = optional_frame_position(argc, argv);
    Data_Get_Struct(self, debug_context_t, debug_context);

    return RTEST(track_frame_args) ? GET_FRAME->arg_ary : Qnil;
}

#frame_binding(frame_position = 0) ⇒ Binding

Returns frame’s binding.

Returns:

  • (Binding)


1761
1762
1763
# File 'ext/ruby_debug/192/ruby_debug.c', line 1761

def frame_binding(frame)
  __c_frame_binding(frame) || hbinding(frame)
end

#frame_class(frame_position) ⇒ Object

Returns the real class of the frame. It could be different than context.frame_self(frame).class

Returns:

  • (Object)


2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
# File 'ext/ruby_debug/192/ruby_debug.c', line 2056

static VALUE
context_frame_class(int argc, VALUE *argv, VALUE self)
{
    VALUE klass;
    VALUE frame;
    debug_context_t *debug_context;
    debug_frame_t *debug_frame;
    rb_control_frame_t *cfp;
    
    debug_check_started();
    frame = optional_frame_position(argc, argv);
    Data_Get_Struct(self, debug_context_t, debug_context);

    debug_frame = GET_FRAME;

    rb_iseq_t *iseq = debug_frame->info.runtime.cfp->iseq;
    if (iseq) {
        klass = real_class(iseq->klass);
        if (TYPE(klass) == T_CLASS || TYPE(klass) == T_MODULE) {
            return klass;
        }
    }
    return Qnil;
}

#frame_file(frame_position) ⇒ String

Returns the name of the file.

Returns:

  • (String)


1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
# File 'ext/ruby_debug/192/ruby_debug.c', line 1837

static VALUE
context_frame_file(int argc, VALUE *argv, VALUE self)
{
    VALUE frame;
    debug_context_t *debug_context;

    debug_check_started();
    frame = optional_frame_position(argc, argv);
    Data_Get_Struct(self, debug_context_t, debug_context);

    rb_iseq_t *iseq = GET_FRAME->info.runtime.cfp->iseq;
    if (iseq) {
        return iseq->filename;
    } else {
        return Qnil;
    }
}

#frame_method(frame_position = 0) ⇒ Object

Returns the sym of the called method.



1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
# File 'ext/ruby_debug/192/ruby_debug.c', line 1779

static VALUE
context_frame_id(int argc, VALUE *argv, VALUE self)
{
    ID id;
    VALUE frame;
    debug_context_t *debug_context;

    debug_check_started();
    frame = optional_frame_position(argc, argv);
    Data_Get_Struct(self, debug_context_t, debug_context);

    rb_iseq_t *iseq = GET_FRAME->info.runtime.cfp->iseq;
    if (iseq) {
        id = iseq->defined_method_id;
        return id ? ID2SYM(id): Qnil;
    } else {
        return Qnil;
    }
}

#frame_line(frame_position) ⇒ Integer

Returns the line number in the file.

Returns:

  • (Integer)


1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
# File 'ext/ruby_debug/192/ruby_debug.c', line 1805

static VALUE
context_frame_line(int argc, VALUE *argv, VALUE self)
{
    VALUE frame;
    debug_context_t *debug_context;
    rb_thread_t *th;
    rb_control_frame_t *cfp;
    VALUE *pc;

    debug_check_started();
    frame = optional_frame_position(argc, argv);
    Data_Get_Struct(self, debug_context_t, debug_context);
    GetThreadPtr(context_thread_0(debug_context), th);

    pc = GET_FRAME->info.runtime.last_pc;
    cfp = GET_FRAME->info.runtime.cfp;
    while (cfp >= th->cfp)
    {
        if ((cfp->iseq) && (pc >= cfp->iseq->iseq_encoded) && (pc < cfp->iseq->iseq_encoded + cfp->iseq->iseq_size))
            return(INT2FIX(rb_vm_get_sourceline(cfp)));
        cfp = RUBY_VM_NEXT_CONTROL_FRAME(cfp);
    }

    return(INT2FIX(0));
}

#frame_locals(frame) ⇒ Hash

Returns frame’s local variables.

Returns:

  • (Hash)


1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
# File 'ext/ruby_debug/192/ruby_debug.c', line 1986

static VALUE
context_frame_locals(int argc, VALUE *argv, VALUE self)
{
    VALUE frame;
    debug_context_t *debug_context;
    debug_frame_t *debug_frame;
    
    debug_check_started();
    frame = optional_frame_position(argc, argv);
    Data_Get_Struct(self, debug_context_t, debug_context);

    debug_frame = GET_FRAME;
    if (debug_frame->dead)
        return debug_frame->info.copy.locals;
    else
        return context_copy_locals(debug_context, debug_frame, self);
}

#frame_method(frame_position = 0) ⇒ Object

Returns the sym of the called method.



1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
# File 'ext/ruby_debug/192/ruby_debug.c', line 1779

static VALUE
context_frame_id(int argc, VALUE *argv, VALUE self)
{
    ID id;
    VALUE frame;
    debug_context_t *debug_context;

    debug_check_started();
    frame = optional_frame_position(argc, argv);
    Data_Get_Struct(self, debug_context_t, debug_context);

    rb_iseq_t *iseq = GET_FRAME->info.runtime.cfp->iseq;
    if (iseq) {
        id = iseq->defined_method_id;
        return id ? ID2SYM(id): Qnil;
    } else {
        return Qnil;
    }
}

#frame_self(frame_postion = 0) ⇒ Object

Returns self object of the frame.

Returns:

  • (Object)


2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
# File 'ext/ruby_debug/192/ruby_debug.c', line 2034

static VALUE
context_frame_self(int argc, VALUE *argv, VALUE self)
{
    VALUE frame;
    debug_context_t *debug_context;
    debug_frame_t *debug_frame;
    
    debug_check_started();
    frame = optional_frame_position(argc, argv);
    Data_Get_Struct(self, debug_context_t, debug_context);

    debug_frame = GET_FRAME;
    return(debug_frame->self);
}

#ignored?Boolean

Returns the ignore flag for the current context.

Returns:

  • (Boolean)


2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
# File 'ext/ruby_debug/192/ruby_debug.c', line 2259

static VALUE
context_ignored(VALUE self)
{
    debug_context_t *debug_context;

    debug_check_started();

    Data_Get_Struct(self, debug_context_t, debug_context);
    return CTX_FL_TEST(debug_context, CTX_FL_IGNORE) ? Qtrue : Qfalse;
}

#inspectObject



4
5
6
7
8
9
10
11
# File 'lib/debugger/test/context.rb', line 4

def inspect
  values = %w{
    thread thnum stop_reason suspended? tracing ignored? stack_size dead? frame_line frame_file frame_self
  }.map do |field|
    "#{field}: #{send(field)}"
  end.join(", ")
  "#<Debugger::Context #{values}>"
end

#interruptObject



15
16
17
# File 'lib/ruby-debug-base.rb', line 15

def interrupt
  self.stop_next = 1
end

#jump(line, file) ⇒ Boolean

Returns true if jump to line in filename file was successful.

Returns:

  • (Boolean)


2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
# File 'ext/ruby_debug/192/ruby_debug.c', line 2397

static VALUE
context_jump(VALUE self, VALUE line, VALUE file)
{
    debug_context_t *debug_context;
    debug_frame_t *debug_frame;
    int i;
    rb_thread_t *th;
    rb_control_frame_t *cfp;
    rb_control_frame_t *cfp_end;
    rb_control_frame_t *cfp_start = NULL;

    debug_check_started();

    Data_Get_Struct(self, debug_context_t, debug_context);
    GetThreadPtr(context_thread_0(debug_context), th);
    debug_frame = get_top_frame(debug_context);
    if (debug_frame == NULL)
        rb_raise(rb_eRuntimeError, "No frames collected.");

    line = FIX2INT(line);

    /* find topmost frame of the debugged code */
    cfp = th->cfp;
    cfp_end = RUBY_VM_END_CONTROL_FRAME(th);
    while (RUBY_VM_VALID_CONTROL_FRAME_P(cfp, cfp_end))
    {
        if (cfp->pc == debug_frame->info.runtime.last_pc)
        {
            cfp_start = cfp;
            if ((cfp->pc - cfp->iseq->iseq_encoded) >= (cfp->iseq->iseq_size - 1))
                return(INT2FIX(1)); /* no space for opt_call_c_function hijack */
            break;
        }
        cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
    }
    if (cfp_start == NULL)
        return(INT2FIX(2)); /* couldn't find frame; should never happen */

    /* find target frame to jump to */
    while (RUBY_VM_VALID_CONTROL_FRAME_P(cfp, cfp_end))
    {
        if ((cfp->iseq != NULL) && (rb_str_cmp(file, cfp->iseq->filename) == 0))
        {
            for (i = 0; i < cfp->iseq->insn_info_size; i++)
            {
                if (cfp->iseq->insn_info_table[i].line_no != line)
                    continue;

                /* hijack the currently running code so that we can change the frame PC */
                debug_context->saved_jump_ins[0] = cfp_start->pc[0];
                debug_context->saved_jump_ins[1] = cfp_start->pc[1];
                cfp_start->pc[0] = opt_call_c_function;
                cfp_start->pc[1] = (VALUE)do_jump;

                debug_context->jump_cfp = cfp;
                debug_context->jump_pc =
                    cfp->iseq->iseq_encoded + cfp->iseq->insn_info_table[i].position;

                return(INT2FIX(0)); /* success */
            }
        }

        cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
    }

    return(INT2FIX(3)); /* couldn't find a line and file frame match */
}

#breakBoolean

Returns true if context is currently running and set flag to break it at next line

Returns:

  • (Boolean)


2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
# File 'ext/ruby_debug/192/ruby_debug.c', line 2471

static VALUE
context_pause(VALUE self)
{
    debug_context_t *debug_context;
    rb_thread_t *th;

    debug_check_started();

    Data_Get_Struct(self, debug_context_t, debug_context);
    if (CTX_FL_TEST(debug_context, CTX_FL_DEAD))
        return(Qfalse);

    GetThreadPtr(context_thread_0(debug_context), th);
    if (th == GET_THREAD())
        return(Qfalse);

    debug_context->thread_pause = 1;
    return(Qtrue);
}

#resumenil

Resumes the thread from the suspended mode.

Returns:

  • (nil)


2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
# File 'ext/ruby_debug/192/ruby_debug.c', line 2201

static VALUE
context_resume(VALUE self)
{
    debug_context_t *debug_context;

    debug_check_started();

    Data_Get_Struct(self, debug_context_t, debug_context);
    if(!CTX_FL_TEST(debug_context, CTX_FL_SUSPEND))
        rb_raise(rb_eRuntimeError, "Thread is not suspended.");
    context_resume_0(debug_context);
    return Qnil;
}

#set_breakpoint(source, pos, condition = nil) ⇒ Object

Sets a context-specific temporary breakpoint, which can be used to implement ‘Run to Cursor’ debugger function. When this breakpoint is reached, it will be cleared out.

source is a name of a file or a class. pos is a line number or a method name if source is a class name. condition is a string which is evaluated to true when this breakpoint is activated.



291
292
293
294
295
296
297
298
299
300
301
302
303
# File 'ext/ruby_debug/192/breakpoint.c', line 291

VALUE
context_set_breakpoint(int argc, VALUE *argv, VALUE self)
{
    VALUE result;
    debug_context_t *debug_context;

    debug_check_started();

    Data_Get_Struct(self, debug_context_t, debug_context);
    result = create_breakpoint_from_args(argc, argv, 0);
    debug_context->breakpoint = result;
    return result;
}

#stack_sizeObject

Returns the size of the context stack.



2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
# File 'ext/ruby_debug/192/ruby_debug.c', line 2088

static VALUE
context_stack_size(VALUE self)
{
    debug_context_t *debug_context;

    debug_check_started();
    Data_Get_Struct(self, debug_context_t, debug_context);

    return INT2FIX(debug_context->stack_size);
}

#step(steps, force = false) ⇒ Object

Stops the current context after a number of steps are made. force parameter (if true) ensures that the cursor moves from the current line.



1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
# File 'ext/ruby_debug/192/ruby_debug.c', line 1627

static VALUE
context_stop_next(int argc, VALUE *argv, VALUE self)
{
    VALUE steps, force;
    debug_context_t *debug_context;

    debug_check_started();

    rb_scan_args(argc, argv, "11", &steps, &force);
    if(FIX2INT(steps) < 0)
        rb_raise(rb_eRuntimeError, "Steps argument can't be negative.");

    Data_Get_Struct(self, debug_context_t, debug_context);
    debug_context->stop_next = FIX2INT(steps);
    if(RTEST(force))
        CTX_FL_SET(debug_context, CTX_FL_FORCE_MOVE);
    else
        CTX_FL_UNSET(debug_context, CTX_FL_FORCE_MOVE);

    return steps;
}

#step_over(steps, frame = nil, force = false) ⇒ Object

Steps over a steps number of times. Make step over operation on frame, by default the current frame. force parameter (if true) ensures that the cursor moves from the current line.



1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
# File 'ext/ruby_debug/192/ruby_debug.c', line 1657

static VALUE
context_step_over(int argc, VALUE *argv, VALUE self)
{
    VALUE lines, frame, force;
    debug_context_t *debug_context;

    debug_check_started();
    Data_Get_Struct(self, debug_context_t, debug_context);
    if(debug_context->stack_size == 0)
        rb_raise(rb_eRuntimeError, "No frames collected.");

    rb_scan_args(argc, argv, "12", &lines, &frame, &force);
    debug_context->stop_line = FIX2INT(lines);
    CTX_FL_UNSET(debug_context, CTX_FL_STEPPED);
    if(frame == Qnil)
    {
        debug_context->dest_frame = debug_context->stack_size;
    }
    else
    {
        if(FIX2INT(frame) < 0 && FIX2INT(frame) >= debug_context->stack_size)
            rb_raise(rb_eRuntimeError, "Destination frame is out of range.");
        debug_context->dest_frame = debug_context->stack_size - FIX2INT(frame);
    }
    if(RTEST(force))
        CTX_FL_SET(debug_context, CTX_FL_FORCE_MOVE);
    else
        CTX_FL_UNSET(debug_context, CTX_FL_FORCE_MOVE);

    return Qnil;
}

#stop_frame(frame) ⇒ Object

Stops when a frame with number frame is activated. Implements finish and next commands.



1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
# File 'ext/ruby_debug/192/ruby_debug.c', line 1695

static VALUE
context_stop_frame(VALUE self, VALUE frame)
{
    debug_context_t *debug_context;

    debug_check_started();
    Data_Get_Struct(self, debug_context_t, debug_context);
    if(FIX2INT(frame) < 0 && FIX2INT(frame) >= debug_context->stack_size)
        rb_raise(rb_eRuntimeError, "Stop frame is out of range.");
    debug_context->stop_frame = debug_context->stack_size - FIX2INT(frame);

    return frame;
}

#step(steps, force = false) ⇒ Object

Stops the current context after a number of steps are made. force parameter (if true) ensures that the cursor moves from the current line.



1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
# File 'ext/ruby_debug/192/ruby_debug.c', line 1627

static VALUE
context_stop_next(int argc, VALUE *argv, VALUE self)
{
    VALUE steps, force;
    debug_context_t *debug_context;

    debug_check_started();

    rb_scan_args(argc, argv, "11", &steps, &force);
    if(FIX2INT(steps) < 0)
        rb_raise(rb_eRuntimeError, "Steps argument can't be negative.");

    Data_Get_Struct(self, debug_context_t, debug_context);
    debug_context->stop_next = FIX2INT(steps);
    if(RTEST(force))
        CTX_FL_SET(debug_context, CTX_FL_FORCE_MOVE);
    else
        CTX_FL_UNSET(debug_context, CTX_FL_FORCE_MOVE);

    return steps;
}

#stop_reasonObject

Returns the reason for the stop. It maybe of the following values: :initial, :step, :breakpoint, :catchpoint, :post-mortem



2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
# File 'ext/ruby_debug/192/ruby_debug.c', line 2295

static VALUE
context_stop_reason(VALUE self)
{
    debug_context_t *debug_context;
    const char * sym_name;

    debug_check_started();

    Data_Get_Struct(self, debug_context_t, debug_context);
    
    switch(debug_context->stop_reason)
    {
        case CTX_STOP_STEP:
            sym_name = "step";
            break;
        case CTX_STOP_BREAKPOINT:
            sym_name = "breakpoint";
            break;
        case CTX_STOP_CATCHPOINT:
            sym_name = "catchpoint";
            break;
        case CTX_STOP_NONE:
        default:
            sym_name = "none";
    }
    if(CTX_FL_TEST(debug_context, CTX_FL_DEAD))
        sym_name = "post-mortem";
    
    return ID2SYM(rb_intern(sym_name));
}

#suspendnil

Suspends the thread when it is running.

Returns:

  • (nil)


2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
# File 'ext/ruby_debug/192/ruby_debug.c', line 2164

static VALUE
context_suspend(VALUE self)
{
    debug_context_t *debug_context;

    debug_check_started();

    Data_Get_Struct(self, debug_context_t, debug_context);
    if(CTX_FL_TEST(debug_context, CTX_FL_SUSPEND))
        rb_raise(rb_eRuntimeError, "Already suspended.");
    context_suspend_0(debug_context);
    return Qnil;
}

#suspended?Boolean

Returns true if the thread is suspended by debugger.

Returns:

  • (Boolean)


2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
# File 'ext/ruby_debug/192/ruby_debug.c', line 2184

static VALUE
context_is_suspended(VALUE self)
{
    debug_context_t *debug_context;

    debug_check_started();

    Data_Get_Struct(self, debug_context_t, debug_context);
    return CTX_FL_TEST(debug_context, CTX_FL_SUSPEND) ? Qtrue : Qfalse;
}

#thnumInteger

Returns the context’s number.

Returns:

  • (Integer)


2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
# File 'ext/ruby_debug/192/ruby_debug.c', line 2122

static VALUE
context_thnum(VALUE self)
{
    debug_context_t *debug_context;

    debug_check_started();
    Data_Get_Struct(self, debug_context_t, debug_context);
    
    return INT2FIX(debug_context->thnum);
}

#threadObject

Returns a thread this context is associated with.



2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
# File 'ext/ruby_debug/192/ruby_debug.c', line 2105

static VALUE
context_thread(VALUE self)
{
    debug_context_t *debug_context;

    debug_check_started();
    Data_Get_Struct(self, debug_context_t, debug_context);

    return(id2ref(debug_context->thread_id));
}

#tracingBoolean

Returns the tracing flag for the current context.

Returns:

  • (Boolean)


2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
# File 'ext/ruby_debug/192/ruby_debug.c', line 2221

static VALUE
context_tracing(VALUE self)
{
    debug_context_t *debug_context;

    debug_check_started();

    Data_Get_Struct(self, debug_context_t, debug_context);
    return CTX_FL_TEST(debug_context, CTX_FL_TRACING) ? Qtrue : Qfalse;
}

#tracing=(bool) ⇒ Object

Controls the tracing for this context.



2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
# File 'ext/ruby_debug/192/ruby_debug.c', line 2238

static VALUE
context_set_tracing(VALUE self, VALUE value)
{
    debug_context_t *debug_context;

    debug_check_started();

    Data_Get_Struct(self, debug_context_t, debug_context);
    if(RTEST(value))
        CTX_FL_SET(debug_context, CTX_FL_TRACING);
    else
        CTX_FL_UNSET(debug_context, CTX_FL_TRACING);
    return value;
}