byebug 1.8.2 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +8 -1
  3. data/GUIDE.md +14 -22
  4. data/README.md +69 -6
  5. data/bin/byebug +3 -20
  6. data/ext/byebug/breakpoint.c +185 -101
  7. data/ext/byebug/byebug.c +393 -214
  8. data/ext/byebug/byebug.h +34 -15
  9. data/ext/byebug/context.c +327 -102
  10. data/ext/byebug/extconf.rb +1 -1
  11. data/ext/byebug/locker.c +54 -0
  12. data/ext/byebug/threads.c +113 -0
  13. data/lib/byebug.rb +19 -58
  14. data/lib/byebug/command.rb +18 -19
  15. data/lib/byebug/commands/breakpoints.rb +1 -4
  16. data/lib/byebug/commands/catchpoint.rb +1 -1
  17. data/lib/byebug/commands/condition.rb +1 -1
  18. data/lib/byebug/commands/control.rb +2 -3
  19. data/lib/byebug/commands/display.rb +2 -7
  20. data/lib/byebug/commands/edit.rb +1 -1
  21. data/lib/byebug/commands/enable.rb +12 -12
  22. data/lib/byebug/commands/eval.rb +4 -4
  23. data/lib/byebug/commands/finish.rb +1 -1
  24. data/lib/byebug/commands/frame.rb +12 -8
  25. data/lib/byebug/commands/info.rb +20 -52
  26. data/lib/byebug/commands/kill.rb +1 -5
  27. data/lib/byebug/commands/list.rb +2 -1
  28. data/lib/byebug/commands/quit.rb +1 -1
  29. data/lib/byebug/commands/repl.rb +2 -2
  30. data/lib/byebug/commands/save.rb +1 -1
  31. data/lib/byebug/commands/set.rb +84 -90
  32. data/lib/byebug/commands/show.rb +44 -53
  33. data/lib/byebug/commands/skip.rb +1 -1
  34. data/lib/byebug/commands/stepping.rb +5 -4
  35. data/lib/byebug/commands/threads.rb +202 -0
  36. data/lib/byebug/commands/trace.rb +1 -1
  37. data/lib/byebug/helper.rb +3 -3
  38. data/lib/byebug/interface.rb +2 -20
  39. data/lib/byebug/processor.rb +21 -100
  40. data/lib/byebug/remote.rb +3 -3
  41. data/lib/byebug/version.rb +1 -1
  42. data/old_doc/byebug.1 +0 -6
  43. data/old_doc/byebug.texi +29 -46
  44. data/test/breakpoints_test.rb +44 -65
  45. data/test/conditions_test.rb +0 -9
  46. data/test/continue_test.rb +2 -2
  47. data/test/display_test.rb +4 -23
  48. data/test/edit_test.rb +2 -16
  49. data/test/eval_test.rb +4 -13
  50. data/test/examples/thread.rb +32 -0
  51. data/test/finish_test.rb +1 -13
  52. data/test/frame_test.rb +5 -12
  53. data/test/help_test.rb +2 -12
  54. data/test/info_test.rb +8 -18
  55. data/test/kill_test.rb +1 -10
  56. data/test/list_test.rb +5 -14
  57. data/test/method_test.rb +1 -10
  58. data/test/post_mortem_test.rb +247 -14
  59. data/test/quit_test.rb +0 -9
  60. data/test/reload_test.rb +1 -15
  61. data/test/repl_test.rb +1 -9
  62. data/test/restart_test.rb +3 -18
  63. data/test/save_test.rb +1 -13
  64. data/test/set_test.rb +35 -32
  65. data/test/show_test.rb +8 -27
  66. data/test/source_test.rb +1 -8
  67. data/test/stepping_test.rb +65 -96
  68. data/test/support/test_dsl.rb +12 -17
  69. data/test/test_helper.rb +1 -1
  70. data/test/thread_test.rb +106 -0
  71. data/test/trace_test.rb +5 -17
  72. data/test/variables_test.rb +1 -10
  73. metadata +9 -7
  74. data/lib/byebug/commands/jump.rb +0 -52
  75. data/test/jump_test.rb +0 -77
  76. data/test/support/context.rb +0 -15
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6e50f515a828a79ec3a73e802a9b480b44d4aedb
4
- data.tar.gz: 3a613a22f8a9a5e6805899f646efbd8e5f29c5eb
3
+ metadata.gz: bb2fb8a1795fb10ac0b9a08f34c9384590f2ed68
4
+ data.tar.gz: ddcc06fdb4be593c69905dc4a0277ea5bf2d945e
5
5
  SHA512:
6
- metadata.gz: b1dea64be0bf3f4aa95986f80e4d468c810ce5ed6a3322a5a672d8db772548109a3c390d5a442bf0b91b6f934c2d6b18797b5782730b2b6f9a544f47ddb337f1
7
- data.tar.gz: 7962816e1385499dce322487b27be5ec25e71f8134f65c8d6b2970ab19257ee998c9f34c2f3208fa64e8349a20ea3b0b050406be1806222b24b8ce6f9af95f1b
6
+ metadata.gz: bd5bec3e835cec6a85de603e4437e013f86fa5e9f239a243fcfa9540b17324a27a075b3a7c78520d2390d8a32e698f8939006e46fbe7f56e547bd008ceb73958
7
+ data.tar.gz: de559dec1bf1265a8e8cacb7431b1617a53ad10dafb24c4ae728714116c5d80580d52e180665fe46632578e8bb198bc9fe8240f989e815f56a80240883c5cad9
@@ -1,3 +1,10 @@
1
+ # 2.0.0
2
+
3
+ * Various bug fixes
4
+ * "Official" definition of a command API
5
+ * Thread support
6
+
7
+
1
8
  ## 1.8.2
2
9
 
3
10
  * More user friendly regexps for commands
@@ -91,7 +98,7 @@ containing the character '%'
91
98
 
92
99
  ## 1.1.0
93
100
 
94
- * Post mortem support
101
+ * Post-mortem support
95
102
 
96
103
 
97
104
  ## 1.0.3
data/GUIDE.md CHANGED
@@ -589,7 +589,6 @@ byebug 1.6.1
589
589
  Usage: byebug [options] <script.rb> -- <script.rb parameters>
590
590
 
591
591
  Options:
592
- -A, --annotate LEVEL Set annotation level
593
592
  -d, --debug Set $DEBUG=true
594
593
  -I, --include PATH Add PATH (single or multiple:path:list) to $LOAD_PATH
595
594
  --no-quit Do not quit when script finishes
@@ -614,10 +613,6 @@ letter option name, such as `-h`. The list of options is detailed below:
614
613
  * **-h | --help**. It causes `byebug` to print some basic help and exit
615
614
  * **-v | --version**. It causes `byebug` to print its version number and
616
615
  exit.
617
- * **-A | --annotate <level>**. Set gdb-style annotation `level`, a number.
618
- Additional information is output automatically when program state is changed.
619
- This can be used by front-ends such as GNU Emacs to post this updated
620
- information without having to poll for it.
621
616
  * **-d | --debug**. Set `$DEBUG` to `true`. Compatible with Ruby's.
622
617
  * **-I | --include <path>**. Add `path` to load path. `path` can be a single
623
618
  path ar a colon separated path list.
@@ -674,8 +669,8 @@ puts "rocky's byebugrc run"
674
669
  Here are the default values in `options`
675
670
 
676
671
  ```
677
- #<OpenStruct annotate=nil, nx=false, quit=true, restart_script=nil, script=nil,
678
- stop=true, tracing=false, verbose_long=false>
672
+ #<OpenStruct nx=false, quit=true, restart_script=nil, script=nil, stop=true,
673
+ tracing=false, verbose_long=false>
679
674
  ```
680
675
 
681
676
  ### Command Files
@@ -819,9 +814,7 @@ be `(byebug:ctrl)` and in post-mortem debugging it will be
819
814
  `(byebug:post-mortem)`.
820
815
 
821
816
  Whenever `byebug` gives an error message such as for an invalid command or an invalid
822
- location position, it will generally preface the message with `***`. However if
823
- annotation mode is on then the message is put in a `begin-error` annotation and no
824
- `***` appears.
817
+ location position, it will generally preface the message with `***`.
825
818
 
826
819
  ### Command Help
827
820
 
@@ -834,12 +827,11 @@ short list of named classes of commands
834
827
  Type "help <command-name>" for help on a specific command
835
828
 
836
829
  Available commands:
837
- backtrace catch continue disable down enable exit frame
838
- info jump list next pp putl reload save
839
- show source trace up where break condition delete
840
- display edit eval finish help irb kill method
841
- p ps quit restart set skip step undisplay
842
- var
830
+ backtrace delete enable help method ps save step where
831
+ break disable eval info next putl set trace
832
+ catch display exit irb p quit show undisplay
833
+ condition down finish kill pp reload skip up
834
+ continue edit frame list pry restart source var
843
835
  ```
844
836
 
845
837
  With a command name as `help` argument, `byebug` displays short information on how to
@@ -859,11 +851,11 @@ A number of commands, namely `info`, `set`, `show`, `enable` and `disable`, have
859
851
  sub-parameters or _subcommands_. When you ask for help for one of these commands, you
860
852
  will get help for all of the subcommands that command offers. Sometimes you may want
861
853
  help only on a subcommand and to do this just follow the command with its subcommand
862
- name. For example `help set annotate` will just give help about the annotate command.
863
- Furthermore it will give longer help than the summary information that appears when
864
- you ask for help. You don't need to list the full subcommand name, just enough
865
- letters to make that subcommand distinct from others will do. For example,
866
- `help set an` is the same as `help set annotate`.
854
+ name. For example, `help info breakpoints`will just give help about the `info
855
+ breakpoints` command. Furthermore it will give longer help than the summary
856
+ information that appears when you ask for help. You don't need to list the full
857
+ subcommand name, just enough of the letters to make that subcommand distinct from
858
+ others will do. For example, `help info b` is the same as `help info breakpoints`.
867
859
 
868
860
  Some examples follow.
869
861
 
@@ -902,7 +894,7 @@ With an integer argument, list info on that breakpoint.
902
894
  ```
903
895
 
904
896
  ```bash
905
- (byebug) help info br
897
+ (byebug) help info b
906
898
  Status of user-settable breakpoints.
907
899
  Without argument, list info about all breakpoints.
908
900
  With an integer argument, list info on that breakpoint.
data/README.md CHANGED
@@ -8,8 +8,7 @@ _Debugging in Ruby 2.0_
8
8
  Byebug is a simple to use, feature rich debugger for Ruby 2.0. It uses the new
9
9
  TracePoint API for execution control and the new Debug Inspector API for call
10
10
  stack navigation, so it doesn't depend on internal core sources. It's developed
11
- as a C extension, so it's fast. And it has a full test suite so it's (I hope)
12
- reliable.
11
+ as a C extension, so it's fast. And it has a full test suite so it's reliable.
13
12
 
14
13
  It allows you to see what is going on _inside_ a Ruby program while it executes
15
14
  and can do four main kinds of things to help you catch bugs in the act:
@@ -52,7 +51,7 @@ Former [debugger](https://github.com/cldwalker/debugger) or
52
51
  [ruby-debug](https://github.com/mark-moseley/ruby-debug) users, notice:
53
52
 
54
53
  * Some gems (rails, rspec) implement debugging flags (-d, --debugger) that early
55
- require and start the debugger. This flags are a performance penalty and Byebug
54
+ require and start the debugger. These flags are a performance penalty and Byebug
56
55
  doesn't need them anymore so my recommendation is not to use them.
57
56
  * Stopping execution using the word `debugger` doesn't work anymore unless you
58
57
  explicitly alias it. Similarly, the startup configuration file is now called
@@ -66,7 +65,7 @@ no longer need to set them in the startup file.
66
65
  * Works on 2.0.0 and it doesn't on 1.9.x.
67
66
  * Has no MRI internal source code dependencies, just a clean API.
68
67
  * Fixes most of debugger's current open issues:
69
- - Post mortem mode segfaulting.
68
+ - Post-mortem mode segfaulting.
70
69
  - Line number wrongly shown as zero in backtrace.
71
70
  - Line tracing.
72
71
  - Colon delimited include paths.
@@ -76,11 +75,72 @@ no longer need to set them in the startup file.
76
75
  - `byebug` can now be placed at the end of a block or method call.
77
76
  * Very actively mantained.
78
77
  * Editor agnostic: no external editor built-in support.
79
- * No thread support. Haven't had time to look at it and I don't know whether
80
- the new debugging API supports it yet.
81
78
  * Pry command is built-in. No need of external gem like debugger-pry.
82
79
 
83
80
 
81
+ ## Semantic Versioning
82
+
83
+ Byebug tries to follow [semantic versioning](semver.org). Backwards
84
+ compatibility doesn't seem like a critic issue for a debugger because it's not
85
+ supposed to be used permanently by any program, let alone in production
86
+ environments. However, I still like the idea of giving some meaning to version
87
+ changes.
88
+
89
+ Byebug's public API is determined by its set of commands
90
+
91
+ +-----------+----------+------------------------------------------------+
92
+ | Command | Aliases | Subcommands |
93
+ +-----------+----------+------------------------------------------------+
94
+ | backtrace | bt|where | |
95
+ | break | | |
96
+ | catch | | |
97
+ | condition | | |
98
+ | continue | | |
99
+ | delete | | |
100
+ | disable | | breakpoints|display |
101
+ | display | | |
102
+ | down | | |
103
+ | edit | | |
104
+ | enable | | breakpoints|display |
105
+ | finish | | |
106
+ | frame | | |
107
+ | help | | |
108
+ | info | | args|breakpoints|catch|display|file|files |
109
+ | | | global_variables|instance_variables|line |
110
+ | | | locals|program|stack|variables |
111
+ | irb | | |
112
+ | kill | | |
113
+ | list | | |
114
+ | method | | instance|iv |
115
+ | next | | |
116
+ | p | eval | |
117
+ | pp | | |
118
+ | pry | | |
119
+ | ps | | |
120
+ | putl | | |
121
+ | quit | exit | |
122
+ | reload | | |
123
+ | restart | | |
124
+ | save | | |
125
+ | set | | args|autoeval|autoirb|autolist|autoreload |
126
+ | | | basename|callstyle|forcestep|fullpath|history |
127
+ | | | linetrace|linetrace_plus|listsize|post_mortem |
128
+ | | | stack_trace_on_error|testing|width |
129
+ | show | | args|autoeval|autoirb|autolist|autoreload |
130
+ | | | basename|callstyle|commands|forcestep|fullpath |
131
+ | | | history|linetrace|linetrace_plus|listsize |
132
+ | | | post_mortem|stack_trace_on_error|width |
133
+ | skip | | |
134
+ | source | | |
135
+ | step | | |
136
+ | thread | | current|list|resume|stop|switch |
137
+ | trace | | |
138
+ | undisplay | | |
139
+ | up | | |
140
+ | var | | class|constant|global|instance|local|ct |
141
+ +-----------+----------+------------------------------------------------+
142
+
143
+
84
144
  ## Getting Started
85
145
 
86
146
  A handful of commands are enough to get started using `byebug`. The following
@@ -241,6 +301,8 @@ quit without being prompted, suffix the command with an exclamation mark, e.g.,
241
301
  `step`, `finish`, `continue` and `break` commands to pry using byebug.
242
302
  * [ruby-debug-passenger](https://github.com/davejamesmiller/ruby-debug-passenger)
243
303
  adds a rake task that restarts Passenger with byebug connected.
304
+ * [minitest-byebug](https://github.com/kaspth/minitest-byebug) starts a byebug
305
+ session on minitest failures.
244
306
 
245
307
 
246
308
  ## Credits
@@ -255,6 +317,7 @@ software, specially:
255
317
  * Dennis Ushakov, author of [debase](https://github.com/denofevil/debase), the
256
318
  starting point of this.
257
319
  * Logo by [Ivlichev Victor Petrovich](http://www.aha-soft.com/)
320
+ * @kevjames3 for testing, bug reports and the interest in the project.
258
321
 
259
322
  [1]: https://badge.fury.io/rb/byebug.png
260
323
  [2]: http://badge.fury.io/rb/byebug
data/bin/byebug CHANGED
@@ -12,12 +12,6 @@
12
12
  #
13
13
  #=== Options
14
14
  #
15
- #<tt>-A | --annotate</tt> <i>level</i>::
16
- # Set gdb-style annotation to <i>level</i>, a number. Additional information
17
- # is output automatically when program state is changed. This can be used by
18
- # front-ends such as GNU Emacs to post this updated information without
19
- # having to poll for it.
20
- #
21
15
  #<tt>-d | --debug</tt>::
22
16
  # Set $DEBUG true.
23
17
  #
@@ -74,11 +68,8 @@ def debug_program(options)
74
68
  puts output
75
69
  exit $?.exitstatus
76
70
  end
77
- print "\032\032starting\n" if Byebug.annotate and Byebug.annotate > 2
78
-
79
71
  if bt = Byebug.debug_load(Byebug::PROG_SCRIPT, options.stop)
80
- print bt.backtrace.map{|l| "\t#{l}"}.join("\n"), "\n"
81
- print "Uncaught exception: #{bt}\n"
72
+ p bt, bt.backtrace
82
73
  end
83
74
  end
84
75
 
@@ -98,7 +89,6 @@ def whence_file(prog_script)
98
89
  end
99
90
 
100
91
  options = OpenStruct.new(
101
- 'annotate' => Byebug.annotate,
102
92
  'nx' => false,
103
93
  'post_mortem' => false,
104
94
  'quit' => true,
@@ -119,8 +109,6 @@ EOB
119
109
  opts.separator ""
120
110
  opts.separator "Options:"
121
111
 
122
- opts.on("-A", "--annotate LEVEL", Integer, "Set annotation level") {
123
- |annotate| Byebug.annotate = annotate }
124
112
  opts.on("-d", "--debug", "Set $DEBUG=true") {
125
113
  $DEBUG = true }
126
114
  opts.on('-I', '--include PATH', String,
@@ -246,14 +234,9 @@ Byebug.tracing = options.tracing
246
234
  loop do
247
235
  begin
248
236
  debug_program(options)
249
- rescue SyntaxError
250
- puts $!.backtrace.map{|l| "\t#{l}"}.join("\n")
251
- puts "Uncaught Syntax Error\n"
252
- rescue
253
- print $!.backtrace.map{|l| "\t#{l}"}.join("\n"), "\n"
254
- print "Uncaught exception: #{$!}\n"
237
+ rescue Exception
238
+ p $!, $@
255
239
  end
256
- print "The program finished.\n" unless Byebug.annotate.to_i > 1
257
240
 
258
241
  break if options.quit
259
242
 
@@ -21,37 +21,78 @@ eval_expression(VALUE args)
21
21
  return rb_funcall2(rb_mKernel, idEval, 2, RARRAY_PTR(args));
22
22
  }
23
23
 
24
+ /*
25
+ * call-seq:
26
+ * breakpoint.enabled? -> bool
27
+ *
28
+ * Returns +true+ if breakpoint is enabled, false otherwise.
29
+ */
24
30
  static VALUE
25
- Breakpoint_hit_count(VALUE self)
31
+ brkpt_enabled(VALUE self)
26
32
  {
27
33
  breakpoint_t *breakpoint;
28
34
 
29
35
  Data_Get_Struct(self, breakpoint_t, breakpoint);
30
- return INT2FIX(breakpoint->hit_count);
36
+ return breakpoint->enabled;
31
37
  }
32
38
 
33
-
39
+ /*
40
+ * call-seq:
41
+ * breakpoint.enabled = bool
42
+ *
43
+ * Enables or disables breakpoint.
44
+ */
34
45
  static VALUE
35
- Breakpoint_hit_value(VALUE self)
46
+ brkpt_set_enabled(VALUE self, VALUE bool)
36
47
  {
37
48
  breakpoint_t *breakpoint;
38
49
 
39
50
  Data_Get_Struct(self, breakpoint_t, breakpoint);
40
- return INT2FIX(breakpoint->hit_value);
51
+ return breakpoint->enabled = bool;
41
52
  }
42
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
+ */
43
61
  static VALUE
44
- Breakpoint_set_hit_value(VALUE self, VALUE value)
62
+ brkpt_expr(VALUE self)
45
63
  {
46
- breakpoint_t *breakpoint;
64
+ breakpoint_t *breakpoint;
47
65
 
48
- Data_Get_Struct(self, breakpoint_t, breakpoint);
49
- breakpoint->hit_value = FIX2INT(value);
50
- return value;
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;
51
85
  }
52
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
+ */
53
94
  static VALUE
54
- Breakpoint_hit_condition(VALUE self)
95
+ brkpt_hit_condition(VALUE self)
55
96
  {
56
97
  breakpoint_t *breakpoint;
57
98
 
@@ -70,8 +111,18 @@ Breakpoint_hit_condition(VALUE self)
70
111
  }
71
112
  }
72
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
+ */
73
124
  static VALUE
74
- Breakpoint_set_hit_condition(VALUE self, VALUE value)
125
+ brkpt_set_hit_condition(VALUE self, VALUE value)
75
126
  {
76
127
  breakpoint_t *breakpoint;
77
128
  ID id_value;
@@ -90,90 +141,78 @@ Breakpoint_set_hit_condition(VALUE self, VALUE value)
90
141
  return value;
91
142
  }
92
143
 
93
- static void
94
- Breakpoint_mark(breakpoint_t *breakpoint)
95
- {
96
- rb_gc_mark(breakpoint->source);
97
- rb_gc_mark(breakpoint->expr);
98
- }
99
-
100
- static VALUE
101
- Breakpoint_create(VALUE klass)
102
- {
103
- breakpoint_t *breakpoint = ALLOC(breakpoint_t);
104
-
105
- return Data_Wrap_Struct(klass, Breakpoint_mark, xfree, breakpoint);
106
- }
107
-
144
+ /*
145
+ * call-seq:
146
+ * breakpoint.hit_count -> int
147
+ *
148
+ * Returns the number of times this breakpoint has been hit.
149
+ */
108
150
  static VALUE
109
- Breakpoint_initialize(VALUE self, VALUE source, VALUE pos, VALUE expr)
151
+ brkpt_hit_count(VALUE self)
110
152
  {
111
153
  breakpoint_t *breakpoint;
112
154
 
113
155
  Data_Get_Struct(self, breakpoint_t, breakpoint);
114
-
115
- breakpoint->type = FIXNUM_P(pos) ? BP_POS_TYPE : BP_METHOD_TYPE;
116
- if(breakpoint->type == BP_POS_TYPE)
117
- breakpoint->pos.line = FIX2INT(pos);
118
- else
119
- breakpoint->pos.mid = SYM2ID(pos);
120
-
121
- breakpoint->id = ++breakpoint_max;
122
- breakpoint->source = StringValue(source);
123
- breakpoint->enabled = Qtrue;
124
- breakpoint->expr = NIL_P(expr) ? expr : StringValue(expr);
125
- breakpoint->hit_count = 0;
126
- breakpoint->hit_value = 0;
127
- breakpoint->hit_condition = HIT_COND_NONE;
128
-
129
- return Qnil;
156
+ return INT2FIX(breakpoint->hit_count);
130
157
  }
131
158
 
159
+ /*
160
+ * call-seq:
161
+ * breakpoint.hit_value -> int
162
+ *
163
+ * Returns the hit value of the breakpoint, namely, a value to build a
164
+ * condition on the number of hits of the breakpoint.
165
+ */
132
166
  static VALUE
133
- Breakpoint_remove(VALUE self, VALUE breakpoints, VALUE id_value)
167
+ brkpt_hit_value(VALUE self)
134
168
  {
135
- int i;
136
- int id;
137
- VALUE breakpoint_object;
138
- breakpoint_t *breakpoint;
139
-
140
- if (breakpoints == Qnil) return Qnil;
141
-
142
- id = FIX2INT(id_value);
169
+ breakpoint_t *breakpoint;
143
170
 
144
- for(i = 0; i < RARRAY_LEN(breakpoints); i++)
145
- {
146
- breakpoint_object = rb_ary_entry(breakpoints, i);
147
- Data_Get_Struct(breakpoint_object, breakpoint_t, breakpoint);
148
- if(breakpoint->id == id)
149
- {
150
- rb_ary_delete_at(breakpoints, i);
151
- return breakpoint_object;
152
- }
153
- }
154
- return Qnil;
171
+ Data_Get_Struct(self, breakpoint_t, breakpoint);
172
+ return INT2FIX(breakpoint->hit_value);
155
173
  }
156
174
 
175
+ /*
176
+ * call-seq:
177
+ * breakpoint.hit_value = int
178
+ *
179
+ * Sets the hit value of the breakpoint. This allows the user to set conditions
180
+ * on the number of hits to enable/disable the breakpoint.
181
+ */
157
182
  static VALUE
158
- Breakpoint_id(VALUE self)
183
+ brkpt_set_hit_value(VALUE self, VALUE value)
159
184
  {
160
- breakpoint_t *breakpoint;
185
+ breakpoint_t *breakpoint;
161
186
 
162
- Data_Get_Struct(self, breakpoint_t, breakpoint);
163
- return INT2FIX(breakpoint->id);
187
+ Data_Get_Struct(self, breakpoint_t, breakpoint);
188
+ breakpoint->hit_value = FIX2INT(value);
189
+ return value;
164
190
  }
165
191
 
192
+ /*
193
+ * call-seq:
194
+ * breakpoint.id -> int
195
+ *
196
+ * Returns the id of the breakpoint.
197
+ */
166
198
  static VALUE
167
- Breakpoint_source(VALUE self)
199
+ brkpt_id(VALUE self)
168
200
  {
169
201
  breakpoint_t *breakpoint;
170
202
 
171
203
  Data_Get_Struct(self, breakpoint_t, breakpoint);
172
- return breakpoint->source;
204
+ return INT2FIX(breakpoint->id);
173
205
  }
174
206
 
207
+ /*
208
+ * call-seq:
209
+ * breakpoint.pos -> string or int
210
+ *
211
+ * Returns the position of this breakpoint, either a method name or a line
212
+ * number.
213
+ */
175
214
  static VALUE
176
- Breakpoint_pos(VALUE self)
215
+ brkpt_pos(VALUE self)
177
216
  {
178
217
  breakpoint_t *breakpoint;
179
218
 
@@ -184,42 +223,83 @@ Breakpoint_pos(VALUE self)
184
223
  return INT2FIX(breakpoint->pos.line);
185
224
  }
186
225
 
187
-
226
+ /*
227
+ * call-seq:
228
+ * breakpoint.source -> string
229
+ *
230
+ * Returns the source file of the breakpoint.
231
+ */
188
232
  static VALUE
189
- Breakpoint_expr(VALUE self)
233
+ brkpt_source(VALUE self)
190
234
  {
191
235
  breakpoint_t *breakpoint;
192
236
 
193
237
  Data_Get_Struct(self, breakpoint_t, breakpoint);
194
- return breakpoint->expr;
238
+ return breakpoint->source;
239
+ }
240
+
241
+ static void
242
+ mark_breakpoint(breakpoint_t *breakpoint)
243
+ {
244
+ rb_gc_mark(breakpoint->source);
245
+ rb_gc_mark(breakpoint->expr);
195
246
  }
196
247
 
197
248
  static VALUE
198
- Breakpoint_set_expr(VALUE self, VALUE expr)
249
+ brkpt_create(VALUE klass)
199
250
  {
200
- breakpoint_t *breakpoint;
251
+ breakpoint_t *breakpoint = ALLOC(breakpoint_t);
201
252
 
202
- Data_Get_Struct(self, breakpoint_t, breakpoint);
203
- breakpoint->expr = NIL_P(expr) ? expr: StringValue(expr);
204
- return expr;
253
+ return Data_Wrap_Struct(klass, mark_breakpoint, xfree, breakpoint);
205
254
  }
206
255
 
207
256
  static VALUE
208
- Breakpoint_enabled(VALUE self)
257
+ brkpt_initialize(VALUE self, VALUE source, VALUE pos, VALUE expr)
209
258
  {
210
259
  breakpoint_t *breakpoint;
211
260
 
212
261
  Data_Get_Struct(self, breakpoint_t, breakpoint);
213
- return breakpoint->enabled;
262
+
263
+ breakpoint->type = FIXNUM_P(pos) ? BP_POS_TYPE : BP_METHOD_TYPE;
264
+ if(breakpoint->type == BP_POS_TYPE)
265
+ breakpoint->pos.line = FIX2INT(pos);
266
+ else
267
+ breakpoint->pos.mid = SYM2ID(pos);
268
+
269
+ breakpoint->id = ++breakpoint_max;
270
+ breakpoint->source = StringValue(source);
271
+ breakpoint->enabled = Qtrue;
272
+ breakpoint->expr = NIL_P(expr) ? expr : StringValue(expr);
273
+ breakpoint->hit_count = 0;
274
+ breakpoint->hit_value = 0;
275
+ breakpoint->hit_condition = HIT_COND_NONE;
276
+
277
+ return Qnil;
214
278
  }
215
279
 
216
280
  static VALUE
217
- Breakpoint_set_enabled(VALUE self, VALUE bool)
281
+ brkpt_remove(VALUE self, VALUE breakpoints, VALUE id_value)
218
282
  {
219
- breakpoint_t *breakpoint;
283
+ int i;
284
+ int id;
285
+ VALUE breakpoint_object;
286
+ breakpoint_t *breakpoint;
220
287
 
221
- Data_Get_Struct(self, breakpoint_t, breakpoint);
222
- return breakpoint->enabled = bool;
288
+ if (breakpoints == Qnil) return Qnil;
289
+
290
+ id = FIX2INT(id_value);
291
+
292
+ for(i = 0; i < RARRAY_LEN(breakpoints); i++)
293
+ {
294
+ breakpoint_object = rb_ary_entry(breakpoints, i);
295
+ Data_Get_Struct(breakpoint_object, breakpoint_t, breakpoint);
296
+ if(breakpoint->id == id)
297
+ {
298
+ rb_ary_delete_at(breakpoints, i);
299
+ return breakpoint_object;
300
+ }
301
+ }
302
+ return Qnil;
223
303
  }
224
304
 
225
305
  int
@@ -422,26 +502,30 @@ find_breakpoint_by_method(VALUE breakpoints, VALUE klass, ID mid, VALUE binding,
422
502
  return Qnil;
423
503
  }
424
504
 
425
- extern void
505
+ void
426
506
  Init_breakpoint(VALUE mByebug)
427
507
  {
428
508
  breakpoint_max = 0;
509
+
429
510
  cBreakpoint = rb_define_class_under(mByebug, "Breakpoint", rb_cObject);
430
- rb_define_singleton_method(cBreakpoint, "remove", Breakpoint_remove, 2);
431
- rb_define_method(cBreakpoint, "initialize", Breakpoint_initialize, 3);
432
- rb_define_method(cBreakpoint, "id", Breakpoint_id, 0);
433
- rb_define_method(cBreakpoint, "source", Breakpoint_source, 0);
434
- rb_define_method(cBreakpoint, "pos", Breakpoint_pos, 0);
435
- rb_define_method(cBreakpoint, "expr", Breakpoint_expr, 0);
436
- rb_define_method(cBreakpoint, "expr=", Breakpoint_set_expr, 1);
437
- rb_define_method(cBreakpoint, "hit_count", Breakpoint_hit_count, 0);
438
- rb_define_method(cBreakpoint, "hit_condition", Breakpoint_hit_condition, 0);
439
- rb_define_method(cBreakpoint, "hit_condition=", Breakpoint_set_hit_condition, 1);
440
- rb_define_method(cBreakpoint, "enabled?", Breakpoint_enabled, 0);
441
- rb_define_method(cBreakpoint, "enabled=", Breakpoint_set_enabled, 1);
442
- rb_define_method(cBreakpoint, "hit_value", Breakpoint_hit_value, 0);
443
- rb_define_method(cBreakpoint, "hit_value=", Breakpoint_set_hit_value, 1);
444
- rb_define_alloc_func(cBreakpoint, Breakpoint_create);
511
+
512
+ rb_define_alloc_func(cBreakpoint, brkpt_create);
513
+ rb_define_method(cBreakpoint, "initialize", brkpt_initialize, 3);
514
+
515
+ rb_define_singleton_method(cBreakpoint, "remove", brkpt_remove, 2);
516
+
517
+ rb_define_method(cBreakpoint, "enabled?" , brkpt_enabled , 0);
518
+ rb_define_method(cBreakpoint, "enabled=" , brkpt_set_enabled , 1);
519
+ rb_define_method(cBreakpoint, "expr" , brkpt_expr , 0);
520
+ rb_define_method(cBreakpoint, "expr=" , brkpt_set_expr , 1);
521
+ rb_define_method(cBreakpoint, "hit_count" , brkpt_hit_count , 0);
522
+ rb_define_method(cBreakpoint, "hit_condition" , brkpt_hit_condition , 0);
523
+ rb_define_method(cBreakpoint, "hit_condition=", brkpt_set_hit_condition, 1);
524
+ rb_define_method(cBreakpoint, "hit_value" , brkpt_hit_value , 0);
525
+ rb_define_method(cBreakpoint, "hit_value=" , brkpt_set_hit_value , 1);
526
+ rb_define_method(cBreakpoint, "id" , brkpt_id , 0);
527
+ rb_define_method(cBreakpoint, "pos" , brkpt_pos , 0);
528
+ rb_define_method(cBreakpoint, "source" , brkpt_source , 0);
445
529
 
446
530
  idEval = rb_intern("eval");
447
531
  }