byebug 3.5.1 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (137) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +4 -1
  3. data/.rubocop.yml +18 -1
  4. data/.travis.yml +21 -1
  5. data/CHANGELOG.md +356 -308
  6. data/CONTRIBUTING.md +31 -15
  7. data/GUIDE.md +859 -475
  8. data/Gemfile +8 -10
  9. data/LICENSE +1 -1
  10. data/README.md +41 -45
  11. data/Rakefile +30 -28
  12. data/byebug.gemspec +18 -18
  13. data/ext/byebug/breakpoint.c +88 -75
  14. data/ext/byebug/byebug.c +253 -252
  15. data/ext/byebug/byebug.h +53 -53
  16. data/ext/byebug/context.c +188 -159
  17. data/ext/byebug/extconf.rb +9 -6
  18. data/ext/byebug/locker.c +53 -11
  19. data/ext/byebug/threads.c +137 -39
  20. data/lib/byebug/attacher.rb +7 -2
  21. data/lib/byebug/breakpoint.rb +30 -0
  22. data/lib/byebug/command.rb +36 -32
  23. data/lib/byebug/commands/break.rb +49 -48
  24. data/lib/byebug/commands/catch.rb +64 -0
  25. data/lib/byebug/commands/condition.rb +13 -9
  26. data/lib/byebug/commands/continue.rb +8 -4
  27. data/lib/byebug/commands/delete.rb +10 -4
  28. data/lib/byebug/commands/display.rb +33 -25
  29. data/lib/byebug/commands/edit.rb +18 -13
  30. data/lib/byebug/commands/enable_disable.rb +26 -24
  31. data/lib/byebug/commands/eval.rb +77 -35
  32. data/lib/byebug/commands/finish.rb +9 -5
  33. data/lib/byebug/commands/frame.rb +66 -125
  34. data/lib/byebug/commands/help.rb +14 -21
  35. data/lib/byebug/commands/history.rb +5 -1
  36. data/lib/byebug/commands/info.rb +41 -106
  37. data/lib/byebug/commands/interrupt.rb +6 -2
  38. data/lib/byebug/commands/irb.rb +5 -2
  39. data/lib/byebug/commands/kill.rb +6 -2
  40. data/lib/byebug/commands/list.rb +21 -14
  41. data/lib/byebug/commands/method.rb +17 -9
  42. data/lib/byebug/commands/pry.rb +13 -3
  43. data/lib/byebug/commands/quit.rb +10 -5
  44. data/lib/byebug/commands/restart.rb +12 -19
  45. data/lib/byebug/commands/save.rb +10 -6
  46. data/lib/byebug/commands/set.rb +15 -14
  47. data/lib/byebug/commands/show.rb +8 -8
  48. data/lib/byebug/commands/source.rb +14 -8
  49. data/lib/byebug/commands/stepping.rb +15 -29
  50. data/lib/byebug/commands/threads.rb +73 -49
  51. data/lib/byebug/commands/tracevar.rb +56 -0
  52. data/lib/byebug/commands/undisplay.rb +8 -4
  53. data/lib/byebug/commands/untracevar.rb +38 -0
  54. data/lib/byebug/commands/var.rb +107 -0
  55. data/lib/byebug/context.rb +78 -42
  56. data/lib/byebug/core.rb +78 -40
  57. data/lib/byebug/helper.rb +58 -42
  58. data/lib/byebug/history.rb +12 -1
  59. data/lib/byebug/interface.rb +91 -11
  60. data/lib/byebug/interfaces/local_interface.rb +12 -19
  61. data/lib/byebug/interfaces/remote_interface.rb +12 -15
  62. data/lib/byebug/interfaces/script_interface.rb +14 -18
  63. data/lib/byebug/interfaces/test_interface.rb +54 -0
  64. data/lib/byebug/printers/base.rb +64 -0
  65. data/lib/byebug/printers/plain.rb +53 -0
  66. data/lib/byebug/processor.rb +20 -1
  67. data/lib/byebug/processors/command_processor.rb +57 -172
  68. data/lib/byebug/processors/control_command_processor.rb +16 -43
  69. data/lib/byebug/remote.rb +13 -7
  70. data/lib/byebug/runner.rb +102 -54
  71. data/lib/byebug/setting.rb +45 -68
  72. data/lib/byebug/settings/autoeval.rb +2 -0
  73. data/lib/byebug/settings/autoirb.rb +3 -0
  74. data/lib/byebug/settings/autolist.rb +3 -0
  75. data/lib/byebug/settings/autosave.rb +2 -0
  76. data/lib/byebug/settings/basename.rb +2 -0
  77. data/lib/byebug/settings/callstyle.rb +2 -0
  78. data/lib/byebug/settings/fullpath.rb +2 -0
  79. data/lib/byebug/settings/histfile.rb +2 -0
  80. data/lib/byebug/settings/histsize.rb +2 -0
  81. data/lib/byebug/settings/linetrace.rb +2 -0
  82. data/lib/byebug/settings/listsize.rb +2 -0
  83. data/lib/byebug/settings/post_mortem.rb +7 -2
  84. data/lib/byebug/settings/stack_on_error.rb +2 -0
  85. data/lib/byebug/settings/verbose.rb +2 -0
  86. data/lib/byebug/settings/width.rb +2 -0
  87. data/lib/byebug/state.rb +12 -0
  88. data/lib/byebug/states/control_state.rb +26 -0
  89. data/lib/byebug/states/regular_state.rb +178 -0
  90. data/lib/byebug/version.rb +1 -1
  91. metadata +24 -109
  92. data/lib/byebug/commands/catchpoint.rb +0 -53
  93. data/lib/byebug/commands/reload.rb +0 -29
  94. data/lib/byebug/commands/trace.rb +0 -50
  95. data/lib/byebug/commands/variables.rb +0 -206
  96. data/lib/byebug/options.rb +0 -46
  97. data/lib/byebug/settings/autoreload.rb +0 -12
  98. data/lib/byebug/settings/forcestep.rb +0 -14
  99. data/lib/byebug/settings/testing.rb +0 -12
  100. data/lib/byebug/settings/tracing_plus.rb +0 -11
  101. data/test/commands/break_test.rb +0 -364
  102. data/test/commands/condition_test.rb +0 -85
  103. data/test/commands/continue_test.rb +0 -47
  104. data/test/commands/delete_test.rb +0 -26
  105. data/test/commands/display_test.rb +0 -37
  106. data/test/commands/edit_test.rb +0 -52
  107. data/test/commands/eval_test.rb +0 -89
  108. data/test/commands/finish_test.rb +0 -74
  109. data/test/commands/frame_test.rb +0 -223
  110. data/test/commands/help_test.rb +0 -66
  111. data/test/commands/history_test.rb +0 -61
  112. data/test/commands/info_test.rb +0 -238
  113. data/test/commands/interrupt_test.rb +0 -45
  114. data/test/commands/irb_test.rb +0 -28
  115. data/test/commands/kill_test.rb +0 -50
  116. data/test/commands/list_test.rb +0 -174
  117. data/test/commands/method_test.rb +0 -52
  118. data/test/commands/post_mortem_test.rb +0 -71
  119. data/test/commands/pry_test.rb +0 -26
  120. data/test/commands/quit_test.rb +0 -53
  121. data/test/commands/reload_test.rb +0 -39
  122. data/test/commands/restart_test.rb +0 -46
  123. data/test/commands/save_test.rb +0 -67
  124. data/test/commands/set_test.rb +0 -140
  125. data/test/commands/show_test.rb +0 -76
  126. data/test/commands/source_test.rb +0 -46
  127. data/test/commands/stepping_test.rb +0 -192
  128. data/test/commands/thread_test.rb +0 -164
  129. data/test/commands/trace_test.rb +0 -71
  130. data/test/commands/undisplay_test.rb +0 -75
  131. data/test/commands/variables_test.rb +0 -105
  132. data/test/debugger_alias_test.rb +0 -7
  133. data/test/runner_test.rb +0 -150
  134. data/test/support/matchers.rb +0 -65
  135. data/test/support/test_interface.rb +0 -59
  136. data/test/support/utils.rb +0 -122
  137. data/test/test_helper.rb +0 -58
@@ -4,19 +4,21 @@
4
4
  #include <ruby.h>
5
5
  #include <ruby/debug.h>
6
6
 
7
+ /* To prevent unused parameter warnings */
8
+ #define UNUSED(x) (void)(x)
9
+
7
10
  /* flags */
8
11
  #define CTX_FL_DEAD (1<<1) /* this context belonged to a dead thread */
9
- #define CTX_FL_ENABLE_BKPT (1<<2) /* can check for breakpoints */
10
- #define CTX_FL_FORCE_MOVE (1<<3) /* don't stop unless we've changed line */
11
- #define CTX_FL_IGNORE (1<<4) /* this context belongs to ignored thread */
12
- #define CTX_FL_SUSPEND (1<<5) /* thread currently suspended */
13
- #define CTX_FL_TRACING (1<<6) /* call at_tracing method */
14
- #define CTX_FL_WAS_RUNNING (1<<7) /* thread was previously running */
15
- #define CTX_FL_STOP_ON_RET (1<<8) /* can stop on method 'end' */
12
+ #define CTX_FL_IGNORE (1<<2) /* this context belongs to ignored thread */
13
+ #define CTX_FL_SUSPEND (1<<3) /* thread currently suspended */
14
+ #define CTX_FL_TRACING (1<<4) /* call at_tracing method */
15
+ #define CTX_FL_WAS_RUNNING (1<<5) /* thread was previously running */
16
+ #define CTX_FL_STOP_ON_RET (1<<6) /* can stop on method 'end' */
17
+ #define CTX_FL_IGNORE_STEPS (1<<7) /* doesn't countdown steps to break */
16
18
 
17
19
  /* macro functions */
18
- #define CTX_FL_TEST(c,f) ((c)->flags & (f))
19
- #define CTX_FL_SET(c,f) do { (c)->flags |= (f); } while (0)
20
+ #define CTX_FL_TEST(c,f) ((c)->flags & (f))
21
+ #define CTX_FL_SET(c,f) do { (c)->flags |= (f); } while (0)
20
22
  #define CTX_FL_UNSET(c,f) do { (c)->flags &= ~(f); } while (0)
21
23
 
22
24
  /* types */
@@ -40,9 +42,6 @@ typedef struct {
40
42
  int steps; /* # of steps before stopping */
41
43
  int steps_out; /* # of returns before stopping */
42
44
 
43
- VALUE last_file;
44
- VALUE last_line;
45
-
46
45
  VALUE backtrace; /* [[loc, self, klass, binding], ...] */
47
46
  } debug_context_t;
48
47
 
@@ -60,23 +59,45 @@ typedef struct {
60
59
  st_table *tbl;
61
60
  } threads_table_t;
62
61
 
62
+ enum bp_type { BP_POS_TYPE, BP_METHOD_TYPE };
63
+
64
+ enum hit_condition { HIT_COND_NONE, HIT_COND_GE, HIT_COND_EQ, HIT_COND_MOD };
65
+
66
+ typedef struct {
67
+ int id;
68
+ enum bp_type type;
69
+ VALUE source;
70
+ union
71
+ {
72
+ int line;
73
+ ID mid;
74
+ } pos;
75
+ VALUE expr;
76
+ VALUE enabled;
77
+ int hit_count;
78
+ int hit_value;
79
+ enum hit_condition hit_condition;
80
+ } breakpoint_t;
81
+
63
82
  /* functions from locker.c */
64
83
  extern int is_in_locked(VALUE thread_id);
65
84
  extern void add_to_locked(VALUE thread);
66
- extern VALUE remove_from_locked();
85
+ extern VALUE pop_from_locked();
86
+ extern void remove_from_locked(VALUE thread);
67
87
 
68
88
  /* functions from threads.c */
69
89
  extern void Init_threads_table(VALUE mByebug);
70
90
  extern VALUE create_threads_table(void);
71
- extern void check_threads_table(void);
72
91
  extern void thread_context_lookup(VALUE thread, VALUE *context);
73
- extern void halt_while_other_thread_is_active(debug_context_t *dc);
92
+ extern int is_living_thread(VALUE thread);
93
+ extern void acquire_lock(debug_context_t *dc);
94
+ extern void release_lock(void);
74
95
 
75
96
  /* global variables */
76
- extern VALUE locker;
77
97
  extern VALUE threads;
98
+ extern VALUE next_thread;
78
99
 
79
- /* functions */
100
+ /* functions from context.c */
80
101
  extern void Init_context(VALUE mByebug);
81
102
  extern VALUE context_create(VALUE thread);
82
103
  extern VALUE context_dup(debug_context_t *context);
@@ -85,42 +106,21 @@ extern VALUE call_with_debug_inspector(struct call_with_inspection_data *data);
85
106
  extern VALUE context_backtrace_set(const rb_debug_inspector_t *inspector,
86
107
  void *data);
87
108
 
88
- static inline int
89
- classname_cmp(VALUE name, VALUE klass)
90
- {
91
- VALUE mod_name;
92
- VALUE class_name = (Qnil == name) ? rb_str_new2("main") : name;
93
- if (klass == Qnil) return(0);
94
- mod_name = rb_mod_name(klass);
95
- return (mod_name != Qnil && rb_str_cmp(class_name, mod_name) == 0);
96
- }
97
-
98
- /* breakpoints & catchpoints */
99
- enum bp_type { BP_POS_TYPE, BP_METHOD_TYPE };
100
-
101
- enum hit_condition { HIT_COND_NONE, HIT_COND_GE, HIT_COND_EQ, HIT_COND_MOD };
102
-
103
- typedef struct {
104
- int id;
105
- enum bp_type type;
106
- VALUE source;
107
- union
108
- {
109
- int line;
110
- ID mid;
111
- } pos;
112
- VALUE expr;
113
- VALUE enabled;
114
- int hit_count;
115
- int hit_value;
116
- enum hit_condition hit_condition;
117
- } breakpoint_t;
118
-
109
+ /* functions from breakpoint.c */
119
110
  extern void Init_breakpoint(VALUE mByebug);
120
- extern VALUE catchpoint_hit_count(VALUE catchpoints, VALUE exception, VALUE *exception_name);
121
- extern VALUE find_breakpoint_by_pos(VALUE breakpoints, VALUE source, VALUE pos,
122
- VALUE binding);
123
- extern VALUE find_breakpoint_by_method(VALUE breakpoints, VALUE klass,
124
- VALUE mid, VALUE binding, VALUE self);
111
+ extern VALUE catchpoint_hit_count(VALUE catchpoints,
112
+ VALUE exception,
113
+ VALUE *exception_name);
114
+
115
+ extern VALUE find_breakpoint_by_pos(VALUE breakpoints,
116
+ VALUE source,
117
+ VALUE pos,
118
+ VALUE bind);
119
+
120
+ extern VALUE find_breakpoint_by_method(VALUE breakpoints,
121
+ VALUE klass,
122
+ VALUE mid,
123
+ VALUE bind,
124
+ VALUE self);
125
125
 
126
126
  #endif
@@ -7,12 +7,12 @@ static int thnum_max = 0;
7
7
  /* "Step", "Next" and "Finish" do their work by saving information about where
8
8
  * to stop next. reset_stepping_stop_points removes/resets this information. */
9
9
  extern void
10
- reset_stepping_stop_points(debug_context_t *context)
10
+ reset_stepping_stop_points(debug_context_t * context)
11
11
  {
12
- context->dest_frame = -1;
13
- context->lines = -1;
14
- context->steps = -1;
15
- context->steps_out = -1;
12
+ context->dest_frame = -1;
13
+ context->lines = -1;
14
+ context->steps = -1;
15
+ context->steps_out = -1;
16
16
  }
17
17
 
18
18
  /*
@@ -26,6 +26,7 @@ static inline VALUE
26
26
  Context_dead(VALUE self)
27
27
  {
28
28
  debug_context_t *context;
29
+
29
30
  Data_Get_Struct(self, debug_context_t, context);
30
31
  return CTX_FL_TEST(context, CTX_FL_DEAD) ? Qtrue : Qfalse;
31
32
  }
@@ -33,14 +34,25 @@ Context_dead(VALUE self)
33
34
  static void
34
35
  context_mark(void *data)
35
36
  {
36
- debug_context_t *context = (debug_context_t *)data;
37
+ debug_context_t *context = (debug_context_t *) data;
38
+
37
39
  rb_gc_mark(context->backtrace);
38
40
  }
39
41
 
42
+ static VALUE
43
+ dc_backtrace(const debug_context_t * context)
44
+ {
45
+ return context->backtrace;
46
+ }
47
+
40
48
  static int
41
- real_stack_size()
49
+ dc_stack_size(debug_context_t * context)
42
50
  {
43
- return FIX2INT(rb_funcall(cContext, rb_intern("stack_size"), 0));
51
+
52
+ if (NIL_P(dc_backtrace(context)))
53
+ return 0;
54
+
55
+ return RARRAY_LENINT(dc_backtrace(context));
44
56
  }
45
57
 
46
58
  extern VALUE
@@ -48,23 +60,23 @@ context_create(VALUE thread)
48
60
  {
49
61
  debug_context_t *context = ALLOC(debug_context_t);
50
62
 
51
- context->last_file = Qnil;
52
- context->last_line = Qnil;
53
- context->flags = 0;
54
- context->calced_stack_size = real_stack_size();
55
- context->thnum = ++thnum_max;
56
- context->thread = thread;
63
+ context->flags = 0;
64
+ context->thnum = ++thnum_max;
65
+ context->thread = thread;
57
66
  reset_stepping_stop_points(context);
58
- context->stop_reason = CTX_STOP_NONE;
59
- context->backtrace = Qnil;
67
+ context->stop_reason = CTX_STOP_NONE;
68
+
69
+ rb_debug_inspector_open(context_backtrace_set, (void *)context);
70
+ context->calced_stack_size = dc_stack_size(context) + 1;
60
71
 
61
- if (rb_obj_class(thread) == cDebugThread) CTX_FL_SET(context, CTX_FL_IGNORE);
72
+ if (rb_obj_class(thread) == cDebugThread)
73
+ CTX_FL_SET(context, CTX_FL_IGNORE);
62
74
 
63
75
  return Data_Wrap_Struct(cContext, context_mark, 0, context);
64
76
  }
65
77
 
66
78
  extern VALUE
67
- context_dup(debug_context_t *context)
79
+ context_dup(debug_context_t * context)
68
80
  {
69
81
  debug_context_t *new_context = ALLOC(debug_context_t);
70
82
 
@@ -76,15 +88,10 @@ context_dup(debug_context_t *context)
76
88
  return Data_Wrap_Struct(cContext, context_mark, 0, new_context);
77
89
  }
78
90
 
79
- static VALUE
80
- dc_backtrace(const debug_context_t *context)
81
- {
82
- return context->backtrace;
83
- }
84
91
 
85
92
  static VALUE
86
- dc_frame_get(const debug_context_t *context, int frame_index,
87
- enum frame_component type)
93
+ dc_frame_get(const debug_context_t * context, int frame_index,
94
+ enum frame_component type)
88
95
  {
89
96
  VALUE frame;
90
97
 
@@ -99,39 +106,40 @@ dc_frame_get(const debug_context_t *context, int frame_index,
99
106
  }
100
107
 
101
108
  static VALUE
102
- dc_frame_location(const debug_context_t *context, int frame_index)
109
+ dc_frame_location(const debug_context_t * context, int frame_index)
103
110
  {
104
111
  return dc_frame_get(context, frame_index, LOCATION);
105
112
  }
106
113
 
107
114
  static VALUE
108
- dc_frame_self(const debug_context_t *context, int frame_index)
115
+ dc_frame_self(const debug_context_t * context, int frame_index)
109
116
  {
110
117
  return dc_frame_get(context, frame_index, SELF);
111
118
  }
112
119
 
113
120
  static VALUE
114
- dc_frame_class(const debug_context_t *context, int frame_index)
121
+ dc_frame_class(const debug_context_t * context, int frame_index)
115
122
  {
116
123
  return dc_frame_get(context, frame_index, CLASS);
117
124
  }
118
125
 
119
126
  static VALUE
120
- dc_frame_binding(const debug_context_t *context, int frame_index)
127
+ dc_frame_binding(const debug_context_t * context, int frame_index)
121
128
  {
122
129
  return dc_frame_get(context, frame_index, BINDING);
123
130
  }
124
131
 
125
132
  static VALUE
126
- load_backtrace(const rb_debug_inspector_t *inspector)
133
+ load_backtrace(const rb_debug_inspector_t * inspector)
127
134
  {
128
135
  VALUE backtrace = rb_ary_new();
129
136
  VALUE locs = rb_debug_inspector_backtrace_locations(inspector);
130
137
  int i;
131
138
 
132
- for (i=0; i<RARRAY_LENINT(locs); i++)
139
+ for (i = 0; i < RARRAY_LENINT(locs); i++)
133
140
  {
134
141
  VALUE frame = rb_ary_new();
142
+
135
143
  rb_ary_push(frame, rb_ary_entry(locs, i));
136
144
  rb_ary_push(frame, rb_debug_inspector_frame_self_get(inspector, i));
137
145
  rb_ary_push(frame, rb_debug_inspector_frame_class_get(inspector, i));
@@ -144,19 +152,21 @@ load_backtrace(const rb_debug_inspector_t *inspector)
144
152
  }
145
153
 
146
154
  extern VALUE
147
- context_backtrace_set(const rb_debug_inspector_t *inspector, void *data)
155
+ context_backtrace_set(const rb_debug_inspector_t * inspector, void *data)
148
156
  {
149
- debug_context_t *dc = (debug_context_t *)data;
157
+ debug_context_t *dc = (debug_context_t *) data;
158
+
150
159
  dc->backtrace = load_backtrace(inspector);
151
160
 
152
161
  return Qnil;
153
162
  }
154
163
 
155
164
  static VALUE
156
- open_debug_inspector_i(const rb_debug_inspector_t *inspector, void *data)
165
+ open_debug_inspector_i(const rb_debug_inspector_t * inspector, void *data)
157
166
  {
158
167
  struct call_with_inspection_data *cwi =
159
168
  (struct call_with_inspection_data *)data;
169
+
160
170
  cwi->dc->backtrace = load_backtrace(inspector);
161
171
 
162
172
  return rb_funcall2(cwi->context_obj, cwi->id, cwi->argc, cwi->argv);
@@ -178,8 +188,8 @@ close_debug_inspector(struct call_with_inspection_data *cwi)
178
188
  extern VALUE
179
189
  call_with_debug_inspector(struct call_with_inspection_data *data)
180
190
  {
181
- return rb_ensure(open_debug_inspector, (VALUE)data,
182
- close_debug_inspector, (VALUE)data);
191
+ return rb_ensure(open_debug_inspector, (VALUE) data, close_debug_inspector,
192
+ (VALUE) data);
183
193
  }
184
194
 
185
195
  #define FRAME_SETUP \
@@ -199,9 +209,9 @@ call_with_debug_inspector(struct call_with_inspection_data *data)
199
209
  * Returns frame's binding.
200
210
  */
201
211
  static VALUE
202
- Context_frame_binding(int argc, VALUE *argv, VALUE self)
212
+ Context_frame_binding(int argc, VALUE * argv, VALUE self)
203
213
  {
204
- FRAME_SETUP
214
+ FRAME_SETUP;
205
215
 
206
216
  return dc_frame_binding(context, frame_n);
207
217
  }
@@ -213,9 +223,9 @@ Context_frame_binding(int argc, VALUE *argv, VALUE self)
213
223
  * Returns frame's defined class.
214
224
  */
215
225
  static VALUE
216
- Context_frame_class(int argc, VALUE *argv, VALUE self)
226
+ Context_frame_class(int argc, VALUE * argv, VALUE self)
217
227
  {
218
- FRAME_SETUP
228
+ FRAME_SETUP;
219
229
 
220
230
  return dc_frame_class(context, frame_n);
221
231
  }
@@ -227,29 +237,34 @@ Context_frame_class(int argc, VALUE *argv, VALUE self)
227
237
  * Returns the name of the file in the frame.
228
238
  */
229
239
  static VALUE
230
- Context_frame_file(int argc, VALUE *argv, VALUE self)
240
+ Context_frame_file(int argc, VALUE * argv, VALUE self)
231
241
  {
232
- VALUE loc;
242
+ VALUE loc, absolute_path;
233
243
 
234
- FRAME_SETUP
244
+ FRAME_SETUP;
235
245
 
236
246
  loc = dc_frame_location(context, frame_n);
237
247
 
248
+ absolute_path = rb_funcall(loc, rb_intern("absolute_path"), 0);
249
+
250
+ if (!NIL_P(absolute_path))
251
+ return absolute_path;
252
+
238
253
  return rb_funcall(loc, rb_intern("path"), 0);
239
254
  }
240
255
 
241
256
  /*
242
257
  * call-seq:
243
- * context.frame_line(frame_position) -> int
258
+ * context.frame_line(frame_position = 0) -> int
244
259
  *
245
260
  * Returns the line number in the file.
246
261
  */
247
262
  static VALUE
248
- Context_frame_line(int argc, VALUE *argv, VALUE self)
263
+ Context_frame_line(int argc, VALUE * argv, VALUE self)
249
264
  {
250
265
  VALUE loc;
251
266
 
252
- FRAME_SETUP
267
+ FRAME_SETUP;
253
268
 
254
269
  loc = dc_frame_location(context, frame_n);
255
270
 
@@ -258,16 +273,16 @@ Context_frame_line(int argc, VALUE *argv, VALUE self)
258
273
 
259
274
  /*
260
275
  * call-seq:
261
- * context.frame_method(frame_position=0) -> sym
276
+ * context.frame_method(frame_position = 0) -> sym
262
277
  *
263
278
  * Returns the sym of the called method.
264
279
  */
265
280
  static VALUE
266
- Context_frame_method(int argc, VALUE *argv, VALUE self)
281
+ Context_frame_method(int argc, VALUE * argv, VALUE self)
267
282
  {
268
283
  VALUE loc;
269
284
 
270
- FRAME_SETUP
285
+ FRAME_SETUP;
271
286
 
272
287
  loc = dc_frame_location(context, frame_n);
273
288
 
@@ -276,14 +291,14 @@ Context_frame_method(int argc, VALUE *argv, VALUE self)
276
291
 
277
292
  /*
278
293
  * call-seq:
279
- * context.frame_self(frame_postion=0) -> obj
294
+ * context.frame_self(frame_postion = 0) -> obj
280
295
  *
281
296
  * Returns self object of the frame.
282
297
  */
283
298
  static VALUE
284
- Context_frame_self(int argc, VALUE *argv, VALUE self)
299
+ Context_frame_self(int argc, VALUE * argv, VALUE self)
285
300
  {
286
- FRAME_SETUP
301
+ FRAME_SETUP;
287
302
 
288
303
  return dc_frame_self(context, frame_n);
289
304
  }
@@ -299,21 +314,11 @@ static inline VALUE
299
314
  Context_ignored(VALUE self)
300
315
  {
301
316
  debug_context_t *context;
317
+
302
318
  Data_Get_Struct(self, debug_context_t, context);
303
319
  return CTX_FL_TEST(context, CTX_FL_IGNORE) ? Qtrue : Qfalse;
304
320
  }
305
321
 
306
- static void
307
- context_resume_0(debug_context_t *context)
308
- {
309
- if (!CTX_FL_TEST(context, CTX_FL_SUSPEND)) return;
310
-
311
- CTX_FL_UNSET(context, CTX_FL_SUSPEND);
312
-
313
- if (CTX_FL_TEST(context, CTX_FL_WAS_RUNNING))
314
- rb_thread_wakeup(context->thread);
315
- }
316
-
317
322
  /*
318
323
  * call-seq:
319
324
  * context.resume -> nil
@@ -323,34 +328,35 @@ context_resume_0(debug_context_t *context)
323
328
  static VALUE
324
329
  Context_resume(VALUE self)
325
330
  {
326
- debug_context_t *context;
331
+ debug_context_t *context;
327
332
 
328
- Data_Get_Struct(self, debug_context_t, context);
333
+ Data_Get_Struct(self, debug_context_t, context);
329
334
 
330
- if (!CTX_FL_TEST(context, CTX_FL_SUSPEND))
331
- rb_raise(rb_eRuntimeError, "Thread is not suspended.");
335
+ if (!CTX_FL_TEST(context, CTX_FL_SUSPEND))
336
+ return Qnil;
332
337
 
333
- context_resume_0(context);
338
+ CTX_FL_UNSET(context, CTX_FL_SUSPEND);
334
339
 
335
- return Qnil;
340
+ if (CTX_FL_TEST(context, CTX_FL_WAS_RUNNING))
341
+ rb_thread_wakeup(context->thread);
342
+
343
+ return Qnil;
336
344
  }
337
345
 
338
346
  /*
339
347
  * call-seq:
340
- * context.calced_stack_size-> int
348
+ * context.backtrace-> int
341
349
  *
342
- * Returns the calculated size of the context stack.
343
- *
344
- * NOTE: it shouldn't be necessary to expose this, this is only done to ease
345
- * the detection of TracePoint API bugs.
350
+ * Returns the frame stack of a context.
346
351
  */
347
352
  static inline VALUE
348
- Context_calced_stack_size(VALUE self)
353
+ Context_backtrace(VALUE self)
349
354
  {
350
355
  debug_context_t *context;
356
+
351
357
  Data_Get_Struct(self, debug_context_t, context);
352
358
 
353
- return INT2FIX(context->calced_stack_size);
359
+ return dc_backtrace(context);
354
360
  }
355
361
 
356
362
  static VALUE
@@ -363,49 +369,59 @@ Context_stop_reason(VALUE self)
363
369
 
364
370
  if (CTX_FL_TEST(context, CTX_FL_DEAD))
365
371
  symbol = "post-mortem";
366
- else switch (context->stop_reason)
367
- {
368
- case CTX_STOP_STEP:
369
- symbol = "step";
370
- break;
371
- case CTX_STOP_BREAKPOINT:
372
- symbol = "breakpoint";
373
- break;
374
- case CTX_STOP_CATCHPOINT:
375
- symbol = "catchpoint";
376
- break;
377
- case CTX_STOP_NONE:
378
- default:
379
- symbol = "none";
380
- }
372
+ else
373
+ switch (context->stop_reason)
374
+ {
375
+ case CTX_STOP_STEP:
376
+ symbol = "step";
377
+ break;
378
+ case CTX_STOP_BREAKPOINT:
379
+ symbol = "breakpoint";
380
+ break;
381
+ case CTX_STOP_CATCHPOINT:
382
+ symbol = "catchpoint";
383
+ break;
384
+ case CTX_STOP_NONE:
385
+ default:
386
+ symbol = "none";
387
+ }
381
388
  return ID2SYM(rb_intern(symbol));
382
389
  }
383
390
 
384
391
  /*
385
392
  * call-seq:
386
- * context.step_into(steps, force = false)
393
+ * context.step_into(steps, frame = 0)
387
394
  *
388
- * Stops the current context after a number of +steps+ are made.
389
- * +force+ parameter (if true) ensures that the cursor moves away from the
390
- * current line.
395
+ * Stops the current context after a number of +steps+ are made from frame
396
+ * +frame+ (by default the newest one).
391
397
  */
392
398
  static VALUE
393
- Context_step_into(int argc, VALUE *argv, VALUE self)
399
+ Context_step_into(int argc, VALUE * argv, VALUE self)
394
400
  {
395
- VALUE steps, force;
401
+ VALUE steps, v_frame;
402
+ int n_args, from_frame;
396
403
  debug_context_t *context;
397
404
 
398
- rb_scan_args(argc, argv, "11", &steps, &force);
399
- if (FIX2INT(steps) < 0)
405
+ Data_Get_Struct(self, debug_context_t, context);
406
+
407
+ if (context->calced_stack_size == 0)
408
+ rb_raise(rb_eRuntimeError, "No frames collected.");
409
+
410
+ n_args = rb_scan_args(argc, argv, "11", &steps, &v_frame);
411
+
412
+ if (FIX2INT(steps) <= 0)
400
413
  rb_raise(rb_eRuntimeError, "Steps argument can't be negative.");
401
414
 
402
- Data_Get_Struct(self, debug_context_t, context);
403
- context->steps = FIX2INT(steps);
415
+ from_frame = n_args == 1 ? 0 : FIX2INT(v_frame);
404
416
 
405
- if (RTEST(force))
406
- CTX_FL_SET(context, CTX_FL_FORCE_MOVE);
407
- else
408
- CTX_FL_UNSET(context, CTX_FL_FORCE_MOVE);
417
+ if (from_frame < 0 || from_frame >= context->calced_stack_size)
418
+ rb_raise(rb_eRuntimeError, "Destination frame (%d) is out of range (%d)",
419
+ from_frame, context->calced_stack_size);
420
+ else if (from_frame > 0)
421
+ CTX_FL_SET(context, CTX_FL_IGNORE_STEPS);
422
+
423
+ context->steps = FIX2INT(steps);
424
+ context->dest_frame = context->calced_stack_size - from_frame;
409
425
 
410
426
  return steps;
411
427
  }
@@ -420,7 +436,7 @@ Context_step_into(int argc, VALUE *argv, VALUE self)
420
436
  * event for that frame is triggered.
421
437
  */
422
438
  static VALUE
423
- Context_step_out(int argc, VALUE *argv, VALUE self)
439
+ Context_step_out(int argc, VALUE * argv, VALUE self)
424
440
  {
425
441
  int n_args, n_frames;
426
442
  VALUE v_frames, force;
@@ -433,7 +449,7 @@ Context_step_out(int argc, VALUE *argv, VALUE self)
433
449
 
434
450
  if (n_frames < 0 || n_frames > context->calced_stack_size)
435
451
  rb_raise(rb_eRuntimeError,
436
- "You wan't to finish %d frames, but stack size is only %d",
452
+ "You want to finish %d frames, but stack size is only %d",
437
453
  n_frames, context->calced_stack_size);
438
454
 
439
455
  context->steps_out = n_frames;
@@ -447,18 +463,16 @@ Context_step_out(int argc, VALUE *argv, VALUE self)
447
463
 
448
464
  /*
449
465
  * call-seq:
450
- * context.step_over(lines, frame = 0, force = false)
466
+ * context.step_over(lines, frame = 0)
451
467
  *
452
- * Steps over +lines+ lines.
453
- * Make step over operation on +frame+, by default the newest frame.
454
- * +force+ parameter (if true) ensures that the cursor moves away from the
455
- * current line.
468
+ * Steps over +lines+ lines in frame +frame+ (by default the newest one) or
469
+ * higher (if frame +frame+ finishes).
456
470
  */
457
471
  static VALUE
458
- Context_step_over(int argc, VALUE *argv, VALUE self)
472
+ Context_step_over(int argc, VALUE * argv, VALUE self)
459
473
  {
460
474
  int n_args, frame;
461
- VALUE lines, v_frame, force;
475
+ VALUE lines, v_frame;
462
476
  debug_context_t *context;
463
477
 
464
478
  Data_Get_Struct(self, debug_context_t, context);
@@ -466,56 +480,66 @@ Context_step_over(int argc, VALUE *argv, VALUE self)
466
480
  if (context->calced_stack_size == 0)
467
481
  rb_raise(rb_eRuntimeError, "No frames collected.");
468
482
 
469
- n_args = rb_scan_args(argc, argv, "12", &lines, &v_frame, &force);
483
+ n_args = rb_scan_args(argc, argv, "11", &lines, &v_frame);
470
484
  frame = n_args == 1 ? 0 : FIX2INT(v_frame);
471
485
 
472
486
  if (frame < 0 || frame >= context->calced_stack_size)
473
- rb_raise(rb_eRuntimeError,
474
- "Destination frame (%d) is out of range (%d)",
487
+ rb_raise(rb_eRuntimeError, "Destination frame (%d) is out of range (%d)",
475
488
  frame, context->calced_stack_size);
476
489
 
477
490
  context->lines = FIX2INT(lines);
478
491
  context->dest_frame = context->calced_stack_size - frame;
479
492
 
480
- if (n_args == 3 && RTEST(force))
481
- CTX_FL_SET(context, CTX_FL_FORCE_MOVE);
482
- else
483
- CTX_FL_UNSET(context, CTX_FL_FORCE_MOVE);
484
-
485
493
  return Qnil;
486
494
  }
487
495
 
488
- static void
489
- context_suspend_0(debug_context_t *context)
496
+ /*
497
+ * call-seq:
498
+ * context.suspend -> nil
499
+ *
500
+ * Suspends the thread when it is running.
501
+ */
502
+ static VALUE
503
+ Context_suspend(VALUE self)
490
504
  {
491
- VALUE status = rb_funcall(context->thread, rb_intern("status"), 0);
505
+ VALUE status;
506
+ debug_context_t *context;
507
+
508
+ Data_Get_Struct(self, debug_context_t, context);
509
+
510
+ status = rb_funcall(context->thread, rb_intern("status"), 0);
492
511
 
493
512
  if (rb_str_cmp(status, rb_str_new2("run")) == 0)
494
513
  CTX_FL_SET(context, CTX_FL_WAS_RUNNING);
495
514
  else if (rb_str_cmp(status, rb_str_new2("sleep")) == 0)
496
515
  CTX_FL_UNSET(context, CTX_FL_WAS_RUNNING);
497
516
  else
498
- return;
517
+ return Qnil;
499
518
 
500
519
  CTX_FL_SET(context, CTX_FL_SUSPEND);
520
+
521
+ return Qnil;
501
522
  }
502
523
 
503
524
  /*
504
525
  * call-seq:
505
- * context.suspend -> nil
526
+ * context.switch -> nil
506
527
  *
507
- * Suspends the thread when it is running.
528
+ * Switches execution to this context.
508
529
  */
509
530
  static VALUE
510
- Context_suspend(VALUE self)
531
+ Context_switch(VALUE self)
511
532
  {
512
533
  debug_context_t *context;
534
+
513
535
  Data_Get_Struct(self, debug_context_t, context);
514
536
 
515
- if (CTX_FL_TEST(context, CTX_FL_SUSPEND))
516
- rb_raise(rb_eRuntimeError, "Already suspended.");
537
+ next_thread = context->thread;
538
+
539
+ context->steps = 1;
540
+ context->steps_out = 0;
541
+ CTX_FL_SET(context, CTX_FL_STOP_ON_RET);
517
542
 
518
- context_suspend_0(context);
519
543
  return Qnil;
520
544
  }
521
545
 
@@ -529,6 +553,7 @@ static VALUE
529
553
  Context_is_suspended(VALUE self)
530
554
  {
531
555
  debug_context_t *context;
556
+
532
557
  Data_Get_Struct(self, debug_context_t, context);
533
558
 
534
559
  return CTX_FL_TEST(context, CTX_FL_SUSPEND) ? Qtrue : Qfalse;
@@ -541,8 +566,10 @@ Context_is_suspended(VALUE self)
541
566
  * Returns the context's number.
542
567
  */
543
568
  static inline VALUE
544
- Context_thnum(VALUE self) {
569
+ Context_thnum(VALUE self)
570
+ {
545
571
  debug_context_t *context;
572
+
546
573
  Data_Get_Struct(self, debug_context_t, context);
547
574
  return INT2FIX(context->thnum);
548
575
  }
@@ -557,6 +584,7 @@ static inline VALUE
557
584
  Context_thread(VALUE self)
558
585
  {
559
586
  debug_context_t *context;
587
+
560
588
  Data_Get_Struct(self, debug_context_t, context);
561
589
  return context->thread;
562
590
  }
@@ -590,15 +618,15 @@ Context_set_tracing(VALUE self, VALUE value)
590
618
  Data_Get_Struct(self, debug_context_t, context);
591
619
 
592
620
  if (RTEST(value))
593
- CTX_FL_SET(context, CTX_FL_TRACING);
621
+ CTX_FL_SET(context, CTX_FL_TRACING);
594
622
  else
595
- CTX_FL_UNSET(context, CTX_FL_TRACING);
623
+ CTX_FL_UNSET(context, CTX_FL_TRACING);
596
624
  return value;
597
625
  }
598
626
 
599
627
  /* :nodoc: */
600
628
  static VALUE
601
- DebugThread_inherited(VALUE klass)
629
+ dt_inherited(VALUE klass)
602
630
  {
603
631
  rb_raise(rb_eRuntimeError, "Can't inherit Byebug::DebugThread class");
604
632
 
@@ -617,27 +645,28 @@ Init_context(VALUE mByebug)
617
645
  {
618
646
  cContext = rb_define_class_under(mByebug, "Context", rb_cObject);
619
647
 
620
- rb_define_method(cContext, "dead?" , Context_dead , 0);
621
- rb_define_method(cContext, "frame_binding" , Context_frame_binding , -1);
622
- rb_define_method(cContext, "frame_class" , Context_frame_class , -1);
623
- rb_define_method(cContext, "frame_file" , Context_frame_file , -1);
624
- rb_define_method(cContext, "frame_line" , Context_frame_line , -1);
625
- rb_define_method(cContext, "frame_method" , Context_frame_method , -1);
626
- rb_define_method(cContext, "frame_self" , Context_frame_self , -1);
627
- rb_define_method(cContext, "ignored?" , Context_ignored , 0);
628
- rb_define_method(cContext, "resume" , Context_resume , 0);
629
- rb_define_method(cContext, "calced_stack_size", Context_calced_stack_size, 0);
630
- rb_define_method(cContext, "step_into" , Context_step_into , -1);
631
- rb_define_method(cContext, "step_out" , Context_step_out , -1);
632
- rb_define_method(cContext, "step_over" , Context_step_over , -1);
633
- rb_define_method(cContext, "stop_reason" , Context_stop_reason , 0);
634
- rb_define_method(cContext, "suspend" , Context_suspend , 0);
635
- rb_define_method(cContext, "suspended?" , Context_is_suspended , 0);
636
- rb_define_method(cContext, "thnum" , Context_thnum , 0);
637
- rb_define_method(cContext, "thread" , Context_thread , 0);
638
- rb_define_method(cContext, "tracing" , Context_tracing , 0);
639
- rb_define_method(cContext, "tracing=" , Context_set_tracing , 1);
640
-
641
- cDebugThread = rb_define_class_under(mByebug, "DebugThread", rb_cThread);
642
- rb_define_singleton_method(cDebugThread, "inherited", DebugThread_inherited, 1);
648
+ rb_define_method(cContext, "backtrace", Context_backtrace, 0);
649
+ rb_define_method(cContext, "dead?", Context_dead, 0);
650
+ rb_define_method(cContext, "frame_binding", Context_frame_binding, -1);
651
+ rb_define_method(cContext, "frame_class", Context_frame_class, -1);
652
+ rb_define_method(cContext, "frame_file", Context_frame_file, -1);
653
+ rb_define_method(cContext, "frame_line", Context_frame_line, -1);
654
+ rb_define_method(cContext, "frame_method", Context_frame_method, -1);
655
+ rb_define_method(cContext, "frame_self", Context_frame_self, -1);
656
+ rb_define_method(cContext, "ignored?", Context_ignored, 0);
657
+ rb_define_method(cContext, "resume", Context_resume, 0);
658
+ rb_define_method(cContext, "step_into", Context_step_into, -1);
659
+ rb_define_method(cContext, "step_out", Context_step_out, -1);
660
+ rb_define_method(cContext, "step_over", Context_step_over, -1);
661
+ rb_define_method(cContext, "stop_reason", Context_stop_reason, 0);
662
+ rb_define_method(cContext, "suspend", Context_suspend, 0);
663
+ rb_define_method(cContext, "suspended?", Context_is_suspended, 0);
664
+ rb_define_method(cContext, "switch", Context_switch, 0);
665
+ rb_define_method(cContext, "thnum", Context_thnum, 0);
666
+ rb_define_method(cContext, "thread", Context_thread, 0);
667
+ rb_define_method(cContext, "tracing", Context_tracing, 0);
668
+ rb_define_method(cContext, "tracing=", Context_set_tracing, 1);
669
+
670
+ cDebugThread = rb_define_class_under(mByebug, "DebugThread", rb_cThread);
671
+ rb_define_singleton_method(cDebugThread, "inherited", dt_inherited, 1);
643
672
  }