Exemple #1
0
static VALUE
Context_step_over(int argc, VALUE *argv, VALUE self)
{
  VALUE lines, frame, force;
  debug_context_t *context;

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

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

  return Qnil;
}
Exemple #2
0
static void
save_current_position(debug_context_t *dc, VALUE file, VALUE line)
{
  dc->last_file = file;
  dc->last_line = line;
  CTX_FL_UNSET(dc, CTX_FL_ENABLE_BKPT);
  CTX_FL_UNSET(dc, CTX_FL_FORCE_MOVE);
}
Exemple #3
0
/*
 *  call-seq:
 *    context.step_out(n_frames = 1, force = false)
 *
 *  Stops after +n_frames+ frames are finished. +force+ parameter (if true)
 *  ensures that the execution will stop in the specified frame even when there
 *  are no more instructions to run. In that case, it will stop when the return
 *  event for that frame is triggered.
 */
static VALUE
Context_step_out(int argc, VALUE * argv, VALUE self)
{
  int n_args, n_frames;
  VALUE v_frames, force;
  debug_context_t *context;

  n_args = rb_scan_args(argc, argv, "02", &v_frames, &force);
  n_frames = n_args == 0 ? 1 : FIX2INT(v_frames);

  Data_Get_Struct(self, debug_context_t, context);

  if (n_frames < 0 || n_frames > context->calced_stack_size)
    rb_raise(rb_eRuntimeError,
             "You want to finish %d frames, but stack size is only %d",
             n_frames, context->calced_stack_size);

  context->steps_out = n_frames;
  if (n_args == 2 && RTEST(force))
    CTX_FL_SET(context, CTX_FL_STOP_ON_RET);
  else
    CTX_FL_UNSET(context, CTX_FL_STOP_ON_RET);

  return Qnil;
}
Exemple #4
0
/*
 *  call-seq:
 *    context.tracing = bool
 *
 *  Controls the tracing for this context.
 */
static VALUE
Context_set_tracing(VALUE self, VALUE value)
{
  debug_context_t *context;

  Data_Get_Struct(self, debug_context_t, context);

  if (RTEST(value))
    CTX_FL_SET(context, CTX_FL_TRACING);
  else
    CTX_FL_UNSET(context, CTX_FL_TRACING);
  return value;
}
Exemple #5
0
/*
 *  call-seq:
 *    context.resume -> nil
 *
 *  Resumes thread from the suspended mode.
 */
static VALUE
Context_resume(VALUE self)
{
  debug_context_t *context;

  Data_Get_Struct(self, debug_context_t, context);

  if (!CTX_FL_TEST(context, CTX_FL_SUSPEND))
    return Qnil;

  CTX_FL_UNSET(context, CTX_FL_SUSPEND);

  if (CTX_FL_TEST(context, CTX_FL_WAS_RUNNING))
    rb_thread_wakeup(context->thread);

  return Qnil;
}
Exemple #6
0
static VALUE
Context_stop_next(int argc, VALUE *argv, VALUE self)
{
  VALUE steps;
  VALUE force;
  debug_context_t *context;

  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, context);
  context->stop_next = FIX2INT(steps);
  if(RTEST(force))
      CTX_FL_SET(context, CTX_FL_FORCE_MOVE);
  else
      CTX_FL_UNSET(context, CTX_FL_FORCE_MOVE);

  return steps;
}
Exemple #7
0
static void
call_event(VALUE trace_point, void *data)
{
  VALUE brkpnt, klass, msym, mid, binding, self, file, line;

  EVENT_SETUP;

  if (dc->calced_stack_size <= dc->dest_frame)
    CTX_FL_UNSET(dc, CTX_FL_IGNORE_STEPS);

  dc->calced_stack_size++;

  dc->steps_out = dc->steps_out <= 0 ? -1 : dc->steps_out + 1;

  /* nil method_id means we are at top level so there can't be a method
   * breakpoint here. Just leave then. */
  msym = rb_tracearg_method_id(trace_arg);
  if (NIL_P(msym))
  {
    EVENT_TEARDOWN;
    return;
  }

  mid = SYM2ID(msym);
  klass = rb_tracearg_defined_class(trace_arg);
  binding = rb_tracearg_binding(trace_arg);
  self = rb_tracearg_self(trace_arg);
  file = rb_tracearg_path(trace_arg);
  line = rb_tracearg_lineno(trace_arg);

  brkpnt = Qnil;

  if (!NIL_P(breakpoints))
    brkpnt = find_breakpoint_by_method(breakpoints, klass, mid, binding, self);

  if (!NIL_P(brkpnt))
  {
    call_at_breakpoint(context, dc, brkpnt);
    call_at_line(context, dc, file, line);
  }

  EVENT_TEARDOWN;
}
Exemple #8
0
/*
 *  call-seq:
 *    context.suspend -> nil
 *
 *  Suspends the thread when it is running.
 */
static VALUE
Context_suspend(VALUE self)
{
  VALUE status;
  debug_context_t *context;

  Data_Get_Struct(self, debug_context_t, context);

  status = rb_funcall(context->thread, rb_intern("status"), 0);

  if (rb_str_cmp(status, rb_str_new2("run")) == 0)
    CTX_FL_SET(context, CTX_FL_WAS_RUNNING);
  else if (rb_str_cmp(status, rb_str_new2("sleep")) == 0)
    CTX_FL_UNSET(context, CTX_FL_WAS_RUNNING);
  else
    return Qnil;

  CTX_FL_SET(context, CTX_FL_SUSPEND);

  return Qnil;
}
Exemple #9
0
static void
line_event(VALUE trace_point, void *data)
{
  VALUE brkpnt, file, line, binding;

  EVENT_SETUP;

  file = rb_tracearg_path(trace_arg);
  line = rb_tracearg_lineno(trace_arg);
  binding = rb_tracearg_binding(trace_arg);

  if (RTEST(tracing))
    call_at_tracing(context, dc);

  if (!CTX_FL_TEST(dc, CTX_FL_IGNORE_STEPS))
    dc->steps = dc->steps <= 0 ? -1 : dc->steps - 1;

  if (dc->calced_stack_size <= dc->dest_frame)
  {
    dc->dest_frame = dc->calced_stack_size;
    CTX_FL_UNSET(dc, CTX_FL_IGNORE_STEPS);

    dc->lines = dc->lines <= 0 ? -1 : dc->lines - 1;
  }

  if (dc->steps == 0 || dc->lines == 0)
    call_at_line_check(context, dc, Qnil);
  else
  {
    brkpnt = Qnil;

    if (!NIL_P(breakpoints))
      brkpnt = find_breakpoint_by_pos(breakpoints, file, line, binding);

    if (!NIL_P(brkpnt))
      call_at_line_check(context, dc, brkpnt);
  }

  EVENT_TEARDOWN;
}
Exemple #10
0
static VALUE
call_at_return(VALUE context_obj, debug_context_t *dc, VALUE file, VALUE line)
{
  CTX_FL_UNSET(dc, CTX_FL_STOP_ON_RET);
  return call_at(context_obj, dc, rb_intern("at_return"), 2, file, line);
}