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.
Files changed (132) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +954 -0
  3. data/CONTRIBUTING.md +58 -0
  4. data/GUIDE.md +1806 -0
  5. data/LICENSE +23 -0
  6. data/README.md +199 -0
  7. data/exe/byebug +6 -0
  8. data/ext/byebug/breakpoint.c +521 -0
  9. data/ext/byebug/byebug.c +900 -0
  10. data/ext/byebug/byebug.h +145 -0
  11. data/ext/byebug/context.c +687 -0
  12. data/ext/byebug/extconf.rb +12 -0
  13. data/ext/byebug/locker.c +96 -0
  14. data/ext/byebug/threads.c +241 -0
  15. data/lib/byebug/attacher.rb +48 -0
  16. data/lib/byebug/breakpoint.rb +94 -0
  17. data/lib/byebug/command.rb +111 -0
  18. data/lib/byebug/command_list.rb +34 -0
  19. data/lib/byebug/commands/break.rb +114 -0
  20. data/lib/byebug/commands/catch.rb +78 -0
  21. data/lib/byebug/commands/condition.rb +55 -0
  22. data/lib/byebug/commands/continue.rb +68 -0
  23. data/lib/byebug/commands/debug.rb +38 -0
  24. data/lib/byebug/commands/delete.rb +55 -0
  25. data/lib/byebug/commands/disable/breakpoints.rb +42 -0
  26. data/lib/byebug/commands/disable/display.rb +43 -0
  27. data/lib/byebug/commands/disable.rb +33 -0
  28. data/lib/byebug/commands/display.rb +66 -0
  29. data/lib/byebug/commands/down.rb +45 -0
  30. data/lib/byebug/commands/edit.rb +69 -0
  31. data/lib/byebug/commands/enable/breakpoints.rb +42 -0
  32. data/lib/byebug/commands/enable/display.rb +43 -0
  33. data/lib/byebug/commands/enable.rb +33 -0
  34. data/lib/byebug/commands/finish.rb +57 -0
  35. data/lib/byebug/commands/frame.rb +57 -0
  36. data/lib/byebug/commands/help.rb +64 -0
  37. data/lib/byebug/commands/history.rb +39 -0
  38. data/lib/byebug/commands/info/breakpoints.rb +65 -0
  39. data/lib/byebug/commands/info/display.rb +49 -0
  40. data/lib/byebug/commands/info/file.rb +80 -0
  41. data/lib/byebug/commands/info/line.rb +35 -0
  42. data/lib/byebug/commands/info/program.rb +49 -0
  43. data/lib/byebug/commands/info.rb +37 -0
  44. data/lib/byebug/commands/interrupt.rb +34 -0
  45. data/lib/byebug/commands/irb.rb +50 -0
  46. data/lib/byebug/commands/kill.rb +45 -0
  47. data/lib/byebug/commands/list.rb +159 -0
  48. data/lib/byebug/commands/method.rb +53 -0
  49. data/lib/byebug/commands/next.rb +40 -0
  50. data/lib/byebug/commands/pry.rb +41 -0
  51. data/lib/byebug/commands/quit.rb +42 -0
  52. data/lib/byebug/commands/restart.rb +64 -0
  53. data/lib/byebug/commands/save.rb +72 -0
  54. data/lib/byebug/commands/set.rb +79 -0
  55. data/lib/byebug/commands/show.rb +45 -0
  56. data/lib/byebug/commands/skip.rb +85 -0
  57. data/lib/byebug/commands/source.rb +40 -0
  58. data/lib/byebug/commands/step.rb +40 -0
  59. data/lib/byebug/commands/thread/current.rb +37 -0
  60. data/lib/byebug/commands/thread/list.rb +43 -0
  61. data/lib/byebug/commands/thread/resume.rb +45 -0
  62. data/lib/byebug/commands/thread/stop.rb +43 -0
  63. data/lib/byebug/commands/thread/switch.rb +46 -0
  64. data/lib/byebug/commands/thread.rb +34 -0
  65. data/lib/byebug/commands/tracevar.rb +54 -0
  66. data/lib/byebug/commands/undisplay.rb +51 -0
  67. data/lib/byebug/commands/untracevar.rb +36 -0
  68. data/lib/byebug/commands/up.rb +45 -0
  69. data/lib/byebug/commands/var/all.rb +41 -0
  70. data/lib/byebug/commands/var/args.rb +39 -0
  71. data/lib/byebug/commands/var/const.rb +49 -0
  72. data/lib/byebug/commands/var/global.rb +37 -0
  73. data/lib/byebug/commands/var/instance.rb +39 -0
  74. data/lib/byebug/commands/var/local.rb +39 -0
  75. data/lib/byebug/commands/var.rb +37 -0
  76. data/lib/byebug/commands/where.rb +64 -0
  77. data/lib/byebug/commands.rb +40 -0
  78. data/lib/byebug/context.rb +157 -0
  79. data/lib/byebug/core.rb +115 -0
  80. data/lib/byebug/errors.rb +29 -0
  81. data/lib/byebug/frame.rb +185 -0
  82. data/lib/byebug/helpers/bin.rb +47 -0
  83. data/lib/byebug/helpers/eval.rb +134 -0
  84. data/lib/byebug/helpers/file.rb +63 -0
  85. data/lib/byebug/helpers/frame.rb +75 -0
  86. data/lib/byebug/helpers/parse.rb +80 -0
  87. data/lib/byebug/helpers/path.rb +40 -0
  88. data/lib/byebug/helpers/reflection.rb +19 -0
  89. data/lib/byebug/helpers/string.rb +33 -0
  90. data/lib/byebug/helpers/thread.rb +67 -0
  91. data/lib/byebug/helpers/toggle.rb +62 -0
  92. data/lib/byebug/helpers/var.rb +70 -0
  93. data/lib/byebug/history.rb +130 -0
  94. data/lib/byebug/interface.rb +146 -0
  95. data/lib/byebug/interfaces/local_interface.rb +63 -0
  96. data/lib/byebug/interfaces/remote_interface.rb +50 -0
  97. data/lib/byebug/interfaces/script_interface.rb +33 -0
  98. data/lib/byebug/interfaces/test_interface.rb +67 -0
  99. data/lib/byebug/option_setter.rb +95 -0
  100. data/lib/byebug/printers/base.rb +68 -0
  101. data/lib/byebug/printers/plain.rb +44 -0
  102. data/lib/byebug/printers/texts/base.yml +115 -0
  103. data/lib/byebug/printers/texts/plain.yml +33 -0
  104. data/lib/byebug/processors/command_processor.rb +173 -0
  105. data/lib/byebug/processors/control_processor.rb +24 -0
  106. data/lib/byebug/processors/post_mortem_processor.rb +18 -0
  107. data/lib/byebug/processors/script_processor.rb +49 -0
  108. data/lib/byebug/remote/client.rb +57 -0
  109. data/lib/byebug/remote/server.rb +47 -0
  110. data/lib/byebug/remote.rb +85 -0
  111. data/lib/byebug/runner.rb +198 -0
  112. data/lib/byebug/setting.rb +79 -0
  113. data/lib/byebug/settings/autoirb.rb +29 -0
  114. data/lib/byebug/settings/autolist.rb +29 -0
  115. data/lib/byebug/settings/autopry.rb +29 -0
  116. data/lib/byebug/settings/autosave.rb +17 -0
  117. data/lib/byebug/settings/basename.rb +16 -0
  118. data/lib/byebug/settings/callstyle.rb +20 -0
  119. data/lib/byebug/settings/fullpath.rb +16 -0
  120. data/lib/byebug/settings/histfile.rb +20 -0
  121. data/lib/byebug/settings/histsize.rb +20 -0
  122. data/lib/byebug/settings/linetrace.rb +22 -0
  123. data/lib/byebug/settings/listsize.rb +21 -0
  124. data/lib/byebug/settings/post_mortem.rb +27 -0
  125. data/lib/byebug/settings/savefile.rb +20 -0
  126. data/lib/byebug/settings/stack_on_error.rb +15 -0
  127. data/lib/byebug/settings/width.rb +20 -0
  128. data/lib/byebug/source_file_formatter.rb +71 -0
  129. data/lib/byebug/subcommands.rb +54 -0
  130. data/lib/byebug/version.rb +8 -0
  131. data/lib/byebug.rb +3 -0
  132. 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
+ }