runger_byebug 11.2.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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +954 -0
- data/CONTRIBUTING.md +58 -0
- data/GUIDE.md +1806 -0
- data/LICENSE +23 -0
- data/README.md +199 -0
- data/exe/byebug +6 -0
- data/ext/byebug/breakpoint.c +521 -0
- data/ext/byebug/byebug.c +900 -0
- data/ext/byebug/byebug.h +145 -0
- data/ext/byebug/context.c +687 -0
- data/ext/byebug/extconf.rb +12 -0
- data/ext/byebug/locker.c +96 -0
- data/ext/byebug/threads.c +241 -0
- data/lib/byebug/attacher.rb +48 -0
- data/lib/byebug/breakpoint.rb +94 -0
- data/lib/byebug/command.rb +111 -0
- data/lib/byebug/command_list.rb +34 -0
- data/lib/byebug/commands/break.rb +114 -0
- data/lib/byebug/commands/catch.rb +78 -0
- data/lib/byebug/commands/condition.rb +55 -0
- data/lib/byebug/commands/continue.rb +68 -0
- data/lib/byebug/commands/debug.rb +38 -0
- data/lib/byebug/commands/delete.rb +55 -0
- data/lib/byebug/commands/disable/breakpoints.rb +42 -0
- data/lib/byebug/commands/disable/display.rb +43 -0
- data/lib/byebug/commands/disable.rb +33 -0
- data/lib/byebug/commands/display.rb +66 -0
- data/lib/byebug/commands/down.rb +45 -0
- data/lib/byebug/commands/edit.rb +69 -0
- data/lib/byebug/commands/enable/breakpoints.rb +42 -0
- data/lib/byebug/commands/enable/display.rb +43 -0
- data/lib/byebug/commands/enable.rb +33 -0
- data/lib/byebug/commands/finish.rb +57 -0
- data/lib/byebug/commands/frame.rb +57 -0
- data/lib/byebug/commands/help.rb +64 -0
- data/lib/byebug/commands/history.rb +39 -0
- data/lib/byebug/commands/info/breakpoints.rb +65 -0
- data/lib/byebug/commands/info/display.rb +49 -0
- data/lib/byebug/commands/info/file.rb +80 -0
- data/lib/byebug/commands/info/line.rb +35 -0
- data/lib/byebug/commands/info/program.rb +49 -0
- data/lib/byebug/commands/info.rb +37 -0
- data/lib/byebug/commands/interrupt.rb +34 -0
- data/lib/byebug/commands/irb.rb +50 -0
- data/lib/byebug/commands/kill.rb +45 -0
- data/lib/byebug/commands/list.rb +159 -0
- data/lib/byebug/commands/method.rb +53 -0
- data/lib/byebug/commands/next.rb +40 -0
- data/lib/byebug/commands/pry.rb +41 -0
- data/lib/byebug/commands/quit.rb +42 -0
- data/lib/byebug/commands/restart.rb +64 -0
- data/lib/byebug/commands/save.rb +72 -0
- data/lib/byebug/commands/set.rb +79 -0
- data/lib/byebug/commands/show.rb +45 -0
- data/lib/byebug/commands/skip.rb +85 -0
- data/lib/byebug/commands/source.rb +40 -0
- data/lib/byebug/commands/step.rb +40 -0
- data/lib/byebug/commands/thread/current.rb +37 -0
- data/lib/byebug/commands/thread/list.rb +43 -0
- data/lib/byebug/commands/thread/resume.rb +45 -0
- data/lib/byebug/commands/thread/stop.rb +43 -0
- data/lib/byebug/commands/thread/switch.rb +46 -0
- data/lib/byebug/commands/thread.rb +34 -0
- data/lib/byebug/commands/tracevar.rb +54 -0
- data/lib/byebug/commands/undisplay.rb +51 -0
- data/lib/byebug/commands/untracevar.rb +36 -0
- data/lib/byebug/commands/up.rb +45 -0
- data/lib/byebug/commands/var/all.rb +41 -0
- data/lib/byebug/commands/var/args.rb +39 -0
- data/lib/byebug/commands/var/const.rb +49 -0
- data/lib/byebug/commands/var/global.rb +37 -0
- data/lib/byebug/commands/var/instance.rb +39 -0
- data/lib/byebug/commands/var/local.rb +39 -0
- data/lib/byebug/commands/var.rb +37 -0
- data/lib/byebug/commands/where.rb +64 -0
- data/lib/byebug/commands.rb +40 -0
- data/lib/byebug/context.rb +157 -0
- data/lib/byebug/core.rb +115 -0
- data/lib/byebug/errors.rb +29 -0
- data/lib/byebug/frame.rb +185 -0
- data/lib/byebug/helpers/bin.rb +47 -0
- data/lib/byebug/helpers/eval.rb +134 -0
- data/lib/byebug/helpers/file.rb +63 -0
- data/lib/byebug/helpers/frame.rb +75 -0
- data/lib/byebug/helpers/parse.rb +80 -0
- data/lib/byebug/helpers/path.rb +40 -0
- data/lib/byebug/helpers/reflection.rb +19 -0
- data/lib/byebug/helpers/string.rb +33 -0
- data/lib/byebug/helpers/thread.rb +67 -0
- data/lib/byebug/helpers/toggle.rb +62 -0
- data/lib/byebug/helpers/var.rb +70 -0
- data/lib/byebug/history.rb +130 -0
- data/lib/byebug/interface.rb +146 -0
- data/lib/byebug/interfaces/local_interface.rb +63 -0
- data/lib/byebug/interfaces/remote_interface.rb +50 -0
- data/lib/byebug/interfaces/script_interface.rb +33 -0
- data/lib/byebug/interfaces/test_interface.rb +67 -0
- data/lib/byebug/option_setter.rb +95 -0
- data/lib/byebug/printers/base.rb +68 -0
- data/lib/byebug/printers/plain.rb +44 -0
- data/lib/byebug/printers/texts/base.yml +115 -0
- data/lib/byebug/printers/texts/plain.yml +33 -0
- data/lib/byebug/processors/command_processor.rb +173 -0
- data/lib/byebug/processors/control_processor.rb +24 -0
- data/lib/byebug/processors/post_mortem_processor.rb +18 -0
- data/lib/byebug/processors/script_processor.rb +49 -0
- data/lib/byebug/remote/client.rb +57 -0
- data/lib/byebug/remote/server.rb +47 -0
- data/lib/byebug/remote.rb +85 -0
- data/lib/byebug/runner.rb +198 -0
- data/lib/byebug/setting.rb +79 -0
- data/lib/byebug/settings/autoirb.rb +29 -0
- data/lib/byebug/settings/autolist.rb +29 -0
- data/lib/byebug/settings/autopry.rb +29 -0
- data/lib/byebug/settings/autosave.rb +17 -0
- data/lib/byebug/settings/basename.rb +16 -0
- data/lib/byebug/settings/callstyle.rb +20 -0
- data/lib/byebug/settings/fullpath.rb +16 -0
- data/lib/byebug/settings/histfile.rb +20 -0
- data/lib/byebug/settings/histsize.rb +20 -0
- data/lib/byebug/settings/linetrace.rb +22 -0
- data/lib/byebug/settings/listsize.rb +21 -0
- data/lib/byebug/settings/post_mortem.rb +27 -0
- data/lib/byebug/settings/savefile.rb +20 -0
- data/lib/byebug/settings/stack_on_error.rb +15 -0
- data/lib/byebug/settings/width.rb +20 -0
- data/lib/byebug/source_file_formatter.rb +71 -0
- data/lib/byebug/subcommands.rb +54 -0
- data/lib/byebug/version.rb +8 -0
- data/lib/byebug.rb +3 -0
- metadata +194 -0
@@ -0,0 +1,521 @@
|
|
1
|
+
#include "byebug.h"
|
2
|
+
|
3
|
+
#ifdef _WIN32
|
4
|
+
#include <ctype.h>
|
5
|
+
#endif
|
6
|
+
|
7
|
+
#if defined DOSISH
|
8
|
+
#define isdirsep(x) ((x) == '/' || (x) == '\\')
|
9
|
+
#else
|
10
|
+
#define isdirsep(x) ((x) == '/')
|
11
|
+
#endif
|
12
|
+
|
13
|
+
static VALUE cBreakpoint;
|
14
|
+
static int breakpoint_max;
|
15
|
+
|
16
|
+
static ID idEval;
|
17
|
+
|
18
|
+
static VALUE
|
19
|
+
eval_expression(VALUE args)
|
20
|
+
{
|
21
|
+
return rb_funcall2(rb_mKernel, idEval, 2, RARRAY_PTR(args));
|
22
|
+
}
|
23
|
+
|
24
|
+
/*
|
25
|
+
* call-seq:
|
26
|
+
* breakpoint.enabled? -> bool
|
27
|
+
*
|
28
|
+
* Returns +true+ if breakpoint is enabled, false otherwise.
|
29
|
+
*/
|
30
|
+
static VALUE
|
31
|
+
brkpt_enabled(VALUE self)
|
32
|
+
{
|
33
|
+
breakpoint_t *breakpoint;
|
34
|
+
|
35
|
+
Data_Get_Struct(self, breakpoint_t, breakpoint);
|
36
|
+
return breakpoint->enabled;
|
37
|
+
}
|
38
|
+
|
39
|
+
/*
|
40
|
+
* call-seq:
|
41
|
+
* breakpoint.enabled = true | false
|
42
|
+
*
|
43
|
+
* Enables or disables breakpoint.
|
44
|
+
*/
|
45
|
+
static VALUE
|
46
|
+
brkpt_set_enabled(VALUE self, VALUE enabled)
|
47
|
+
{
|
48
|
+
breakpoint_t *breakpoint;
|
49
|
+
|
50
|
+
Data_Get_Struct(self, breakpoint_t, breakpoint);
|
51
|
+
return breakpoint->enabled = enabled;
|
52
|
+
}
|
53
|
+
|
54
|
+
/*
|
55
|
+
* call-seq:
|
56
|
+
* breakpoint.expr -> string
|
57
|
+
*
|
58
|
+
* Returns a conditional expression which indicates when this breakpoint should
|
59
|
+
* be activated.
|
60
|
+
*/
|
61
|
+
static VALUE
|
62
|
+
brkpt_expr(VALUE self)
|
63
|
+
{
|
64
|
+
breakpoint_t *breakpoint;
|
65
|
+
|
66
|
+
Data_Get_Struct(self, breakpoint_t, breakpoint);
|
67
|
+
return breakpoint->expr;
|
68
|
+
}
|
69
|
+
|
70
|
+
/*
|
71
|
+
* call-seq:
|
72
|
+
* breakpoint.expr = string | nil
|
73
|
+
*
|
74
|
+
* Sets or unsets the conditional expression which indicates when this
|
75
|
+
* breakpoint should be activated.
|
76
|
+
*/
|
77
|
+
static VALUE
|
78
|
+
brkpt_set_expr(VALUE self, VALUE expr)
|
79
|
+
{
|
80
|
+
breakpoint_t *breakpoint;
|
81
|
+
|
82
|
+
Data_Get_Struct(self, breakpoint_t, breakpoint);
|
83
|
+
breakpoint->expr = NIL_P(expr) ? expr : StringValue(expr);
|
84
|
+
return expr;
|
85
|
+
}
|
86
|
+
|
87
|
+
/*
|
88
|
+
* call-seq:
|
89
|
+
* breakpoint.hit_condition -> symbol
|
90
|
+
*
|
91
|
+
* Returns the hit condition of the breakpoint: +nil+ if it is an
|
92
|
+
* unconditional breakpoint, or :greater_or_equal, :equal or :modulo otherwise
|
93
|
+
*/
|
94
|
+
static VALUE
|
95
|
+
brkpt_hit_condition(VALUE self)
|
96
|
+
{
|
97
|
+
breakpoint_t *breakpoint;
|
98
|
+
|
99
|
+
Data_Get_Struct(self, breakpoint_t, breakpoint);
|
100
|
+
switch (breakpoint->hit_condition)
|
101
|
+
{
|
102
|
+
case HIT_COND_GE:
|
103
|
+
return ID2SYM(rb_intern("greater_or_equal"));
|
104
|
+
case HIT_COND_EQ:
|
105
|
+
return ID2SYM(rb_intern("equal"));
|
106
|
+
case HIT_COND_MOD:
|
107
|
+
return ID2SYM(rb_intern("modulo"));
|
108
|
+
case HIT_COND_NONE:
|
109
|
+
default:
|
110
|
+
return Qnil;
|
111
|
+
}
|
112
|
+
}
|
113
|
+
|
114
|
+
/*
|
115
|
+
* call-seq:
|
116
|
+
* breakpoint.hit_condition = symbol
|
117
|
+
*
|
118
|
+
* Sets the hit condition of the breakpoint which must be one of the following
|
119
|
+
* values:
|
120
|
+
*
|
121
|
+
* +nil+ if it is an unconditional breakpoint, or
|
122
|
+
* :greater_or_equal(:ge), :equal(:eq), :modulo(:mod)
|
123
|
+
*/
|
124
|
+
static VALUE
|
125
|
+
brkpt_set_hit_condition(VALUE self, VALUE value)
|
126
|
+
{
|
127
|
+
breakpoint_t *breakpoint;
|
128
|
+
ID id_value;
|
129
|
+
|
130
|
+
Data_Get_Struct(self, breakpoint_t, breakpoint);
|
131
|
+
|
132
|
+
if (NIL_P(value))
|
133
|
+
{
|
134
|
+
breakpoint->hit_condition = HIT_COND_NONE;
|
135
|
+
return value;
|
136
|
+
}
|
137
|
+
|
138
|
+
id_value = rb_to_id(value);
|
139
|
+
|
140
|
+
if (rb_intern("greater_or_equal") == id_value || rb_intern("ge") == id_value)
|
141
|
+
breakpoint->hit_condition = HIT_COND_GE;
|
142
|
+
else if (rb_intern("equal") == id_value || rb_intern("eq") == id_value)
|
143
|
+
breakpoint->hit_condition = HIT_COND_EQ;
|
144
|
+
else if (rb_intern("modulo") == id_value || rb_intern("mod") == id_value)
|
145
|
+
breakpoint->hit_condition = HIT_COND_MOD;
|
146
|
+
else
|
147
|
+
rb_raise(rb_eArgError, "Invalid condition parameter");
|
148
|
+
return value;
|
149
|
+
}
|
150
|
+
|
151
|
+
/*
|
152
|
+
* call-seq:
|
153
|
+
* breakpoint.hit_count -> int
|
154
|
+
*
|
155
|
+
* Returns the number of times this breakpoint has been hit.
|
156
|
+
*/
|
157
|
+
static VALUE
|
158
|
+
brkpt_hit_count(VALUE self)
|
159
|
+
{
|
160
|
+
breakpoint_t *breakpoint;
|
161
|
+
|
162
|
+
Data_Get_Struct(self, breakpoint_t, breakpoint);
|
163
|
+
return INT2FIX(breakpoint->hit_count);
|
164
|
+
}
|
165
|
+
|
166
|
+
/*
|
167
|
+
* call-seq:
|
168
|
+
* breakpoint.hit_value -> int
|
169
|
+
*
|
170
|
+
* Returns the hit value of the breakpoint, namely, a value to build a
|
171
|
+
* condition on the number of hits of the breakpoint.
|
172
|
+
*/
|
173
|
+
static VALUE
|
174
|
+
brkpt_hit_value(VALUE self)
|
175
|
+
{
|
176
|
+
breakpoint_t *breakpoint;
|
177
|
+
|
178
|
+
Data_Get_Struct(self, breakpoint_t, breakpoint);
|
179
|
+
return INT2FIX(breakpoint->hit_value);
|
180
|
+
}
|
181
|
+
|
182
|
+
/*
|
183
|
+
* call-seq:
|
184
|
+
* breakpoint.hit_value = int
|
185
|
+
*
|
186
|
+
* Sets the hit value of the breakpoint. This allows the user to set conditions
|
187
|
+
* on the number of hits to enable/disable the breakpoint.
|
188
|
+
*/
|
189
|
+
static VALUE
|
190
|
+
brkpt_set_hit_value(VALUE self, VALUE value)
|
191
|
+
{
|
192
|
+
breakpoint_t *breakpoint;
|
193
|
+
|
194
|
+
Data_Get_Struct(self, breakpoint_t, breakpoint);
|
195
|
+
breakpoint->hit_value = FIX2INT(value);
|
196
|
+
return value;
|
197
|
+
}
|
198
|
+
|
199
|
+
/*
|
200
|
+
* call-seq:
|
201
|
+
* breakpoint.id -> int
|
202
|
+
*
|
203
|
+
* Returns the id of the breakpoint.
|
204
|
+
*/
|
205
|
+
static VALUE
|
206
|
+
brkpt_id(VALUE self)
|
207
|
+
{
|
208
|
+
breakpoint_t *breakpoint;
|
209
|
+
|
210
|
+
Data_Get_Struct(self, breakpoint_t, breakpoint);
|
211
|
+
return INT2FIX(breakpoint->id);
|
212
|
+
}
|
213
|
+
|
214
|
+
/*
|
215
|
+
* call-seq:
|
216
|
+
* breakpoint.pos -> string or int
|
217
|
+
*
|
218
|
+
* Returns the position of this breakpoint, either a method name or a line
|
219
|
+
* number.
|
220
|
+
*/
|
221
|
+
static VALUE
|
222
|
+
brkpt_pos(VALUE self)
|
223
|
+
{
|
224
|
+
breakpoint_t *breakpoint;
|
225
|
+
|
226
|
+
Data_Get_Struct(self, breakpoint_t, breakpoint);
|
227
|
+
if (breakpoint->type == BP_METHOD_TYPE)
|
228
|
+
return rb_str_new2(rb_id2name(breakpoint->pos.mid));
|
229
|
+
else
|
230
|
+
return INT2FIX(breakpoint->pos.line);
|
231
|
+
}
|
232
|
+
|
233
|
+
/*
|
234
|
+
* call-seq:
|
235
|
+
* breakpoint.source -> string
|
236
|
+
*
|
237
|
+
* Returns the source file of the breakpoint.
|
238
|
+
*/
|
239
|
+
static VALUE
|
240
|
+
brkpt_source(VALUE self)
|
241
|
+
{
|
242
|
+
breakpoint_t *breakpoint;
|
243
|
+
|
244
|
+
Data_Get_Struct(self, breakpoint_t, breakpoint);
|
245
|
+
return breakpoint->source;
|
246
|
+
}
|
247
|
+
|
248
|
+
static void
|
249
|
+
mark_breakpoint(breakpoint_t *breakpoint)
|
250
|
+
{
|
251
|
+
rb_gc_mark(breakpoint->source);
|
252
|
+
rb_gc_mark(breakpoint->expr);
|
253
|
+
}
|
254
|
+
|
255
|
+
static VALUE
|
256
|
+
brkpt_create(VALUE klass)
|
257
|
+
{
|
258
|
+
breakpoint_t *breakpoint = ALLOC(breakpoint_t);
|
259
|
+
|
260
|
+
return Data_Wrap_Struct(klass, mark_breakpoint, xfree, breakpoint);
|
261
|
+
}
|
262
|
+
|
263
|
+
static VALUE
|
264
|
+
brkpt_initialize(VALUE self, VALUE source, VALUE pos, VALUE expr)
|
265
|
+
{
|
266
|
+
breakpoint_t *breakpoint;
|
267
|
+
|
268
|
+
Data_Get_Struct(self, breakpoint_t, breakpoint);
|
269
|
+
|
270
|
+
breakpoint->type = FIXNUM_P(pos) ? BP_POS_TYPE : BP_METHOD_TYPE;
|
271
|
+
if (breakpoint->type == BP_POS_TYPE)
|
272
|
+
breakpoint->pos.line = FIX2INT(pos);
|
273
|
+
else
|
274
|
+
breakpoint->pos.mid = SYM2ID(pos);
|
275
|
+
|
276
|
+
breakpoint->id = ++breakpoint_max;
|
277
|
+
breakpoint->source = StringValue(source);
|
278
|
+
breakpoint->enabled = Qtrue;
|
279
|
+
breakpoint->expr = NIL_P(expr) ? expr : StringValue(expr);
|
280
|
+
breakpoint->hit_count = 0;
|
281
|
+
breakpoint->hit_value = 0;
|
282
|
+
breakpoint->hit_condition = HIT_COND_NONE;
|
283
|
+
|
284
|
+
return Qnil;
|
285
|
+
}
|
286
|
+
|
287
|
+
static int
|
288
|
+
filename_cmp_impl(VALUE source, char *file)
|
289
|
+
{
|
290
|
+
char *source_ptr, *file_ptr;
|
291
|
+
long s_len, f_len, min_len;
|
292
|
+
long s, f;
|
293
|
+
int dirsep_flag = 0;
|
294
|
+
|
295
|
+
s_len = RSTRING_LEN(source);
|
296
|
+
f_len = strlen(file);
|
297
|
+
min_len = s_len < f_len ? s_len : f_len;
|
298
|
+
|
299
|
+
source_ptr = RSTRING_PTR(source);
|
300
|
+
file_ptr = file;
|
301
|
+
|
302
|
+
for (s = s_len - 1, f = f_len - 1;
|
303
|
+
s >= s_len - min_len && f >= f_len - min_len; s--, f--)
|
304
|
+
{
|
305
|
+
if ((source_ptr[s] == '.' || file_ptr[f] == '.') && dirsep_flag)
|
306
|
+
return 1;
|
307
|
+
if (isdirsep(source_ptr[s]) && isdirsep(file_ptr[f]))
|
308
|
+
dirsep_flag = 1;
|
309
|
+
#ifdef DOSISH_DRIVE_LETTER
|
310
|
+
else if (s == 0)
|
311
|
+
return (toupper(source_ptr[s]) == toupper(file_ptr[f]));
|
312
|
+
#endif
|
313
|
+
else if (source_ptr[s] != file_ptr[f])
|
314
|
+
return 0;
|
315
|
+
}
|
316
|
+
return 1;
|
317
|
+
}
|
318
|
+
|
319
|
+
static int
|
320
|
+
filename_cmp(VALUE source, char *file)
|
321
|
+
{
|
322
|
+
#ifdef _WIN32
|
323
|
+
return filename_cmp_impl(source, file);
|
324
|
+
#else
|
325
|
+
#ifdef PATH_MAX
|
326
|
+
char path[PATH_MAX + 1];
|
327
|
+
|
328
|
+
path[PATH_MAX] = 0;
|
329
|
+
return filename_cmp_impl(source, realpath(file, path) != NULL ? path : file);
|
330
|
+
#else
|
331
|
+
char *path;
|
332
|
+
int result;
|
333
|
+
|
334
|
+
path = realpath(file, NULL);
|
335
|
+
result = filename_cmp_impl(source, path == NULL ? file : path);
|
336
|
+
free(path);
|
337
|
+
return result;
|
338
|
+
#endif
|
339
|
+
#endif
|
340
|
+
}
|
341
|
+
|
342
|
+
static int
|
343
|
+
classname_cmp(VALUE name, VALUE klass)
|
344
|
+
{
|
345
|
+
VALUE mod_name;
|
346
|
+
VALUE class_name = NIL_P(name) ? rb_str_new2("main") : name;
|
347
|
+
|
348
|
+
if (NIL_P(klass))
|
349
|
+
return 0;
|
350
|
+
|
351
|
+
mod_name = rb_mod_name(klass);
|
352
|
+
return (!NIL_P(mod_name) && rb_str_cmp(class_name, mod_name) == 0);
|
353
|
+
}
|
354
|
+
|
355
|
+
static int
|
356
|
+
check_breakpoint_by_hit_condition(VALUE rb_breakpoint)
|
357
|
+
{
|
358
|
+
breakpoint_t *breakpoint;
|
359
|
+
|
360
|
+
if (NIL_P(rb_breakpoint))
|
361
|
+
return 0;
|
362
|
+
|
363
|
+
Data_Get_Struct(rb_breakpoint, breakpoint_t, breakpoint);
|
364
|
+
breakpoint->hit_count++;
|
365
|
+
|
366
|
+
if (Qtrue != breakpoint->enabled)
|
367
|
+
return 0;
|
368
|
+
|
369
|
+
switch (breakpoint->hit_condition)
|
370
|
+
{
|
371
|
+
case HIT_COND_NONE:
|
372
|
+
return 1;
|
373
|
+
case HIT_COND_GE: {
|
374
|
+
if (breakpoint->hit_count >= breakpoint->hit_value)
|
375
|
+
return 1;
|
376
|
+
break;
|
377
|
+
}
|
378
|
+
case HIT_COND_EQ: {
|
379
|
+
if (breakpoint->hit_count == breakpoint->hit_value)
|
380
|
+
return 1;
|
381
|
+
break;
|
382
|
+
}
|
383
|
+
case HIT_COND_MOD: {
|
384
|
+
if (breakpoint->hit_count % breakpoint->hit_value == 0)
|
385
|
+
return 1;
|
386
|
+
break;
|
387
|
+
}
|
388
|
+
}
|
389
|
+
return 0;
|
390
|
+
}
|
391
|
+
|
392
|
+
static int
|
393
|
+
check_breakpoint_by_pos(VALUE rb_breakpoint, char *file, int line)
|
394
|
+
{
|
395
|
+
breakpoint_t *breakpoint;
|
396
|
+
|
397
|
+
if (NIL_P(rb_breakpoint))
|
398
|
+
return 0;
|
399
|
+
|
400
|
+
Data_Get_Struct(rb_breakpoint, breakpoint_t, breakpoint);
|
401
|
+
|
402
|
+
if (Qfalse == breakpoint->enabled || breakpoint->type != BP_POS_TYPE
|
403
|
+
|| breakpoint->pos.line != line)
|
404
|
+
return 0;
|
405
|
+
|
406
|
+
return filename_cmp(breakpoint->source, file);
|
407
|
+
}
|
408
|
+
|
409
|
+
static int
|
410
|
+
check_breakpoint_by_method(VALUE rb_breakpoint, VALUE klass, ID mid, VALUE self)
|
411
|
+
{
|
412
|
+
breakpoint_t *breakpoint;
|
413
|
+
|
414
|
+
if (NIL_P(rb_breakpoint))
|
415
|
+
return 0;
|
416
|
+
|
417
|
+
Data_Get_Struct(rb_breakpoint, breakpoint_t, breakpoint);
|
418
|
+
|
419
|
+
if (Qfalse == breakpoint->enabled || breakpoint->type != BP_METHOD_TYPE
|
420
|
+
|| breakpoint->pos.mid != mid)
|
421
|
+
return 0;
|
422
|
+
|
423
|
+
if (classname_cmp(breakpoint->source, klass)
|
424
|
+
|| ((rb_type(self) == T_CLASS || rb_type(self) == T_MODULE)
|
425
|
+
&& classname_cmp(breakpoint->source, self)))
|
426
|
+
return 1;
|
427
|
+
|
428
|
+
return 0;
|
429
|
+
}
|
430
|
+
|
431
|
+
static int
|
432
|
+
check_breakpoint_by_expr(VALUE rb_breakpoint, VALUE bind)
|
433
|
+
{
|
434
|
+
breakpoint_t *breakpoint;
|
435
|
+
VALUE args, expr_result;
|
436
|
+
|
437
|
+
if (NIL_P(rb_breakpoint))
|
438
|
+
return 0;
|
439
|
+
|
440
|
+
Data_Get_Struct(rb_breakpoint, breakpoint_t, breakpoint);
|
441
|
+
|
442
|
+
if (Qfalse == breakpoint->enabled)
|
443
|
+
return 0;
|
444
|
+
|
445
|
+
if (NIL_P(breakpoint->expr))
|
446
|
+
return 1;
|
447
|
+
|
448
|
+
args = rb_ary_new3(2, breakpoint->expr, bind);
|
449
|
+
expr_result = rb_protect(eval_expression, args, 0);
|
450
|
+
|
451
|
+
return RTEST(expr_result);
|
452
|
+
}
|
453
|
+
|
454
|
+
extern VALUE
|
455
|
+
find_breakpoint_by_pos(VALUE breakpoints, VALUE source, VALUE pos, VALUE bind)
|
456
|
+
{
|
457
|
+
VALUE breakpoint;
|
458
|
+
char *file;
|
459
|
+
int line;
|
460
|
+
int i;
|
461
|
+
|
462
|
+
file = RSTRING_PTR(source);
|
463
|
+
line = FIX2INT(pos);
|
464
|
+
for (i = 0; i < RARRAY_LENINT(breakpoints); i++)
|
465
|
+
{
|
466
|
+
breakpoint = rb_ary_entry(breakpoints, i);
|
467
|
+
if (check_breakpoint_by_pos(breakpoint, file, line)
|
468
|
+
&& check_breakpoint_by_expr(breakpoint, bind)
|
469
|
+
&& check_breakpoint_by_hit_condition(breakpoint))
|
470
|
+
{
|
471
|
+
return breakpoint;
|
472
|
+
}
|
473
|
+
}
|
474
|
+
return Qnil;
|
475
|
+
}
|
476
|
+
|
477
|
+
extern VALUE
|
478
|
+
find_breakpoint_by_method(VALUE breakpoints, VALUE klass, ID mid, VALUE bind,
|
479
|
+
VALUE self)
|
480
|
+
{
|
481
|
+
VALUE breakpoint;
|
482
|
+
int i;
|
483
|
+
|
484
|
+
for (i = 0; i < RARRAY_LENINT(breakpoints); i++)
|
485
|
+
{
|
486
|
+
breakpoint = rb_ary_entry(breakpoints, i);
|
487
|
+
if (check_breakpoint_by_method(breakpoint, klass, mid, self)
|
488
|
+
&& check_breakpoint_by_expr(breakpoint, bind)
|
489
|
+
&& check_breakpoint_by_hit_condition(breakpoint))
|
490
|
+
{
|
491
|
+
return breakpoint;
|
492
|
+
}
|
493
|
+
}
|
494
|
+
return Qnil;
|
495
|
+
}
|
496
|
+
|
497
|
+
void
|
498
|
+
Init_byebug_breakpoint(VALUE mByebug)
|
499
|
+
{
|
500
|
+
breakpoint_max = 0;
|
501
|
+
|
502
|
+
cBreakpoint = rb_define_class_under(mByebug, "Breakpoint", rb_cObject);
|
503
|
+
|
504
|
+
rb_define_alloc_func(cBreakpoint, brkpt_create);
|
505
|
+
rb_define_method(cBreakpoint, "initialize", brkpt_initialize, 3);
|
506
|
+
|
507
|
+
rb_define_method(cBreakpoint, "enabled?", brkpt_enabled, 0);
|
508
|
+
rb_define_method(cBreakpoint, "enabled=", brkpt_set_enabled, 1);
|
509
|
+
rb_define_method(cBreakpoint, "expr", brkpt_expr, 0);
|
510
|
+
rb_define_method(cBreakpoint, "expr=", brkpt_set_expr, 1);
|
511
|
+
rb_define_method(cBreakpoint, "hit_count", brkpt_hit_count, 0);
|
512
|
+
rb_define_method(cBreakpoint, "hit_condition", brkpt_hit_condition, 0);
|
513
|
+
rb_define_method(cBreakpoint, "hit_condition=", brkpt_set_hit_condition, 1);
|
514
|
+
rb_define_method(cBreakpoint, "hit_value", brkpt_hit_value, 0);
|
515
|
+
rb_define_method(cBreakpoint, "hit_value=", brkpt_set_hit_value, 1);
|
516
|
+
rb_define_method(cBreakpoint, "id", brkpt_id, 0);
|
517
|
+
rb_define_method(cBreakpoint, "pos", brkpt_pos, 0);
|
518
|
+
rb_define_method(cBreakpoint, "source", brkpt_source, 0);
|
519
|
+
|
520
|
+
idEval = rb_intern("eval");
|
521
|
+
}
|