byebug 1.0.3 → 1.1.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 (52) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +5 -0
  3. data/README.md +13 -11
  4. data/Rakefile +0 -6
  5. data/bin/byebug +83 -136
  6. data/ext/byebug/byebug.c +182 -96
  7. data/ext/byebug/byebug.h +5 -7
  8. data/ext/byebug/context.c +52 -40
  9. data/lib/byebug.rb +81 -81
  10. data/lib/byebug/command.rb +18 -35
  11. data/lib/byebug/commands/control.rb +1 -1
  12. data/lib/byebug/commands/display.rb +0 -2
  13. data/lib/byebug/commands/enable.rb +4 -16
  14. data/lib/byebug/commands/eval.rb +5 -3
  15. data/lib/byebug/commands/frame.rb +68 -69
  16. data/lib/byebug/commands/help.rb +2 -1
  17. data/lib/byebug/commands/info.rb +43 -42
  18. data/lib/byebug/commands/method.rb +4 -3
  19. data/lib/byebug/commands/set.rb +10 -19
  20. data/lib/byebug/commands/show.rb +6 -13
  21. data/lib/byebug/interface.rb +1 -1
  22. data/lib/byebug/processor.rb +14 -17
  23. data/lib/byebug/version.rb +1 -2
  24. data/old_doc/byebug.texi +576 -847
  25. data/test/breakpoints_test.rb +0 -1
  26. data/test/conditions_test.rb +35 -33
  27. data/test/display_test.rb +14 -13
  28. data/test/edit_test.rb +28 -25
  29. data/test/eval_test.rb +0 -2
  30. data/test/finish_test.rb +4 -3
  31. data/test/frame_test.rb +20 -21
  32. data/test/help_test.rb +26 -23
  33. data/test/info_test.rb +105 -108
  34. data/test/irb_test.rb +26 -25
  35. data/test/kill_test.rb +19 -19
  36. data/test/list_test.rb +140 -156
  37. data/test/method_test.rb +21 -22
  38. data/test/post_mortem_test.rb +2 -5
  39. data/test/quit_test.rb +16 -17
  40. data/test/reload_test.rb +2 -2
  41. data/test/restart_test.rb +0 -1
  42. data/test/save_test.rb +31 -32
  43. data/test/set_test.rb +50 -47
  44. data/test/show_test.rb +67 -66
  45. data/test/source_test.rb +31 -34
  46. data/test/stepping_test.rb +32 -34
  47. data/test/support/test_dsl.rb +1 -1
  48. data/test/trace_test.rb +1 -2
  49. data/test/variables_test.rb +36 -34
  50. metadata +2 -4
  51. data/lib/byebug/commands/tmate.rb +0 -36
  52. data/test/tmate_test.rb +0 -44
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: db82855de95f0558289aa633b2432e871bf4a3bb
4
- data.tar.gz: 805e3ed4d731545dd2a7f5d9a60ecfe4925e4fdd
3
+ metadata.gz: dc04cc8b68063ec31b6318a54bd88e1d4ee354be
4
+ data.tar.gz: 070611b0dbc7fcc7f6fa276b588b32297c5d5588
5
5
  SHA512:
6
- metadata.gz: 5662e984cfcb5562c7afe0ccfcb79b926e19ff8fefbf2cb55fae3f18705650983a5385daf5b1545c9dea85bb6d783a46e9ddc0204f08c3116a66e9cc1522a8f6
7
- data.tar.gz: 2fe8c9c5934687b8dfdfccdec322a227a0892662010bc08db4be14ac5af4b49b674868da94773517691e57f6b4f4d3b53794e3c819cd9ccd1979092ed816a21e
6
+ metadata.gz: 1434e8a81a8f62b6af39ba73ba527c44b77c9219d06760ac36cc392d98de069f007d3a3b65f56c3f4db6b6ae3fcd3034fc660d8d9fa01781f677a53df2538bac
7
+ data.tar.gz: e679189a446359f9d98b18f086472129826218f57d1e1cc0c8d71fa186c146a917b0efafed1c4cc9a991d88f2390fff41c36d160a8f3a4ab2fb23f1ceacd1b90
@@ -1,3 +1,8 @@
1
+ ## 1.1.0
2
+
3
+ * Post mortem support
4
+
5
+
1
6
  ## 1.0.3
2
7
 
3
8
  * "autoreload" is set by default now
data/README.md CHANGED
@@ -5,24 +5,26 @@ A Ruby 2.0 debugger.
5
5
 
6
6
  ## Install
7
7
 
8
- Just type
8
+ Just type `gem install byebug` or drop `gem 'byebug'` in your Gemfile and run
9
+ `bundle install`.
9
10
 
10
- $ gem install byebug
11
11
 
12
- or if you use bundler, drop
13
-
14
- gem 'byebug'
15
-
16
- in your Gemfile
12
+ ## Usage
17
13
 
14
+ Simply drop `byebug` wherever you want to start debugging and the execution
15
+ stop there. If you are debugging rails, start the server in normal mode with
16
+ `rails server` and once the execution get to your `byebug` command you will get
17
+ a debugging terminal.
18
18
 
19
- ## Usage
20
19
 
21
- Wherever you want to start debugging, simply drop:
20
+ ## Configuration
22
21
 
23
- byebug
22
+ You can automatically load some configurations at startup by dropping them in
23
+ the startup file `.byebugrc`, for example, `set listsize 20`. If you are coming
24
+ from [debugger](https://github.com/cldwalker/debugger), notice however that you
25
+ no longer need `set autolist`, `set autoreload` and `set autoeval` because they
26
+ are default options in byebug.
24
27
 
25
- and the execution will stop and allow you to start debugging.
26
28
 
27
29
  ## Credits
28
30
 
data/Rakefile CHANGED
@@ -1,7 +1,6 @@
1
1
  # -*- Ruby -*-
2
2
  require 'rake/testtask'
3
3
  require 'rake/extensiontask'
4
- require 'rubygems/package_task'
5
4
  require 'bundler/gem_tasks'
6
5
 
7
6
  Rake::ExtensionTask.new('byebug')
@@ -18,9 +17,4 @@ end
18
17
 
19
18
  base_spec = eval(File.read('byebug.gemspec'), binding, 'byebug.gemspec')
20
19
 
21
- # Rake task to build the default package
22
- Gem::PackageTask.new(base_spec) do |pkg|
23
- pkg.need_tar = true
24
- end
25
-
26
20
  task :default => :test
data/bin/byebug CHANGED
@@ -13,14 +13,15 @@
13
13
  #=== Options
14
14
  #
15
15
  #<tt>-A | --annotate</tt> <i>level</i>::
16
- # Set gdb-style annotation to <i>level</i>, a number. Additional
17
- # information is output automatically when program state is changed. This
18
- # can be used by front-ends such as GNU Emacs to post this updated
19
- # information without having to poll for it.
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
20
  #
21
21
  #<tt>--client</tt>::
22
22
  # Connect to a remote byebug. Used with another byebug invocation using
23
- # <tt>--server</tt>. See also <tt>--host</tt> and <tt>--cport</tt> options
23
+ # <tt>--server</tt>. See also <tt>--host</tt>, <tt>--port</tt> and
24
+ # <tt>--cport</tt> options.
24
25
  #
25
26
  #<tt>--cport=</tt><i>port</i>::
26
27
  # Use port <i>port</i> for access to byebug control.
@@ -28,75 +29,65 @@
28
29
  #<tt>-d | --debug</tt>::
29
30
  # Set $DEBUG true.
30
31
  #
31
- #<tt>--emacs</tt>::
32
- # Activates full GNU Emacs mode. Is the equivalent of setting the options
33
- # <tt>--emacs-basic --annotate=3 --no-stop --no-control --post-mortem</tt>.
34
- #
35
- #<tt>--emacs-basic</tt>::
36
- # Activates GNU Emacs mode. Byebug prompts are prefaced with two octal 032
37
- # characters.
38
- #
39
32
  #<tt>-h | --host=</tt><i>host</i>::
40
- # Use host name <i>host</i> for remote debugging.
33
+ # Use host name <i>host</i> for remote debugging.
34
+ #
35
+ #<tt>--help</tt>::
36
+ # Show invocation help and exit.
41
37
  #
42
38
  #<tt>-I | --include</tt> <i>path</i>
43
- # Add <i>path</i> to <tt>$LOAD_PATH</tt>
39
+ # Add <i>path</i> to <tt>$LOAD_PATH</tt>
40
+ #
41
+ #<tt>--keep-frame-binding</tt>::
42
+ # Keep frame bindings.
44
43
  #
45
44
  #<tt>-m | --post-mortem</tt>::
46
- # Activate post-mortem mode.
45
+ # Activate post-mortem mode.
47
46
  #
48
47
  #<tt>--no-control</tt>::
49
- # Do not automatically start control thread.
48
+ # Do not automatically start control thread.
49
+ #
50
+ #<tt>--no-quit</tt>::
51
+ # Do not quit when script terminates. Instead rerun the program.
50
52
  #
51
53
  #<tt>--no-stop</tt>::
52
- # Do not stop when script is loaded.
54
+ # Do not stop when script is loaded.
55
+ #
56
+ #<tt>--nx</tt>::
57
+ # Don’t execute commands found in any initialization files like
58
+ # <tt>.byebugrc</tt>.
53
59
  #
54
60
  #<tt>-p | --port=PORT</tt>::
55
- # Host name used for remote debugging.
61
+ # Use port <i>port</i> for remote debugging.
56
62
  #
57
63
  #<tt>-r | --require</tt><i>script</i>::
58
- # Require the library, before executing your script.
59
- #
60
- #<tt>--script</tt> <i>file</i>::
61
- # Run byebug script file <i>file</i>
62
- #
63
- #<tt>-x | --trace</tt>::
64
- # Show lines before executing them.
64
+ # Require the library, before executing your script.
65
65
  #
66
- #<tt>--no-quit</tt>::
67
- # Do not quit when script terminates. Instead rerun the program.
66
+ #<tt>-s | --server</tt>::
67
+ # Listen for remote connections. Another byebug session accesses using the
68
+ # <tt>--client</tt> option. See also the <tt>--host</tt>, <tt>--port</tt>
69
+ # and <tt>--cport</tt> options
68
70
  #
69
- #<tt>--version</tt>::
70
- # Show the version number and exit.
71
- #
72
- #<tt>--verbose</tt>::
73
- # Turn on verbose mode.
71
+ #<tt>--script</tt>=<i>file</i>::
72
+ # Run script file <i>file</i>
74
73
  #
75
74
  #<tt>--v</tt>::
76
- # Print the version number, then turn on verbose mode if a script name is
77
- # given. If no script name is given just exit after printing the version
78
- # number.
79
- #
80
- #<tt>--nx</tt>::
81
- # Don’t execute commands found in any initialization files like
82
- # <tt>.byebugrc</tt>.
75
+ # Print the version number, then turn on verbose mode if a script name is
76
+ # given. If no script name is given just exit after printing the version
77
+ # number.
83
78
  #
84
- #<tt>--keep-frame-binding</tt>::
85
- # Keep frame bindings.
86
- #
87
- #<tt>--script=</tt><i>file</i>::
88
- # Name of the script file to run.
79
+ #<tt>--verbose</tt>::
80
+ # Turn on verbose mode.
89
81
  #
90
- #<tt>-s | --server</tt>::
91
- # Listen for remote connections. Another byebug session accesses using the
92
- # <tt>--client</tt> option. See also the <tt>--host</tt>, <tt>--port</tt>
93
- # and <tt>--cport</tt> options
82
+ #<tt>--version</tt>::
83
+ # Show the version number and exit.
94
84
  #
95
85
  #<tt>-w | --wait</tt>::
96
86
  # Wait for a client connection; implies <tt>-s</tt> option.
97
87
  #
98
- #<tt>--help</tt>::
99
- # Show invocation help and exit.
88
+ #<tt>-x | --trace</tt>::
89
+ # Show lines before executing them.
90
+ #
100
91
 
101
92
  require 'optparse'
102
93
  require 'ostruct'
@@ -140,9 +131,9 @@ end
140
131
  options = OpenStruct.new(
141
132
  'annotate' => Byebug.annotate,
142
133
  'client' => false,
143
- 'control' => true,
144
134
  'cport' => Byebug::PORT + 1,
145
135
  'host' => nil,
136
+ 'control' => true,
146
137
  'quit' => true,
147
138
  'no_rewrite_program' => false,
148
139
  'stop' => true,
@@ -165,67 +156,37 @@ Usage: #{program} [options] <script.rb> -- <script.rb parameters>
165
156
  EOB
166
157
  opts.separator ""
167
158
  opts.separator "Options:"
168
- opts.on("-A", "--annotate LEVEL", Integer, "Set annotation level") do
169
- |annotate|
170
- Byebug.annotate = annotate
171
- end
172
- opts.on("-c", "--client", "Connect to remote byebug") do
173
- options.client = true
174
- end
175
- opts.on("--cport PORT", Integer, "Port used for control commands") do
176
- |cport|
177
- options.cport = cport
178
- end
179
- opts.on("-d", "--debug", "Set $DEBUG=true") {$DEBUG = true}
180
- opts.on("--emacs LEVEL", Integer,
181
- "Activates full Emacs support at annotation level LEVEL") do
182
- |level|
183
- Byebug.annotate = level.to_i
184
- ENV['EMACS'] = '1'
185
- ENV['COLUMNS'] = '120' if ENV['COLUMNS'].to_i < 120
186
- options.control = false
187
- options.quit = false
188
- end
189
- opts.on('--emacs-basic', 'Activates basic Emacs mode') do
190
- ENV['EMACS'] = '1'
191
- end
192
- opts.on('-h', '--host HOST', 'Host name used for remote debugging') do
193
- |host|
194
- options.host = host
195
- end
196
- opts.on('-I', '--include PATH', String, 'Add PATH to $LOAD_PATH') do |path|
197
- $LOAD_PATH.unshift(path)
198
- end
199
- opts.on('--no-control', 'Do not automatically start control thread') do
200
- options.control = false
201
- end
202
- opts.on('--no-quit', 'Do not quit when script finishes') do
203
- options.quit = false
204
- end
205
- opts.on('--no-rewrite-program',
206
- 'Do not set $0 to the program being debugged') do
207
- options.no_rewrite_program = true
208
- end
209
- opts.on('--no-stop', 'Do not stop when script is loaded') do
210
- options.stop = false
211
- end
212
- opts.on('-nx', 'Not run byebug initialization files (e.g. .byebugrc') do
213
- options.nx = true
214
- end
215
- opts.on('-p', '--port PORT', Integer, 'Port used for remote debugging') do
216
- |port|
217
- options.port = port
218
- end
219
- opts.on('-r', '--require SCRIPT', String,
220
- 'Require the library, before executing your script') do |name|
221
- if name == 'debug'
222
- puts "byebug is not compatible with Ruby's 'debug' library. This option is ignored."
159
+ opts.on("-A", "--annotate LEVEL", Integer, "Set annotation level") {
160
+ |annotate| Byebug.annotate = annotate }
161
+ opts.on("-c", "--client", "Connect to remote byebug") {
162
+ options.client = true }
163
+ opts.on("--cport PORT", Integer, "Port used for control commands") {
164
+ |cport| options.cport = cport }
165
+ opts.on("-d", "--debug", "Set $DEBUG=true") {
166
+ $DEBUG = true }
167
+ opts.on('-h', '--host HOST', 'Host name used for remote debugging') {
168
+ |host| options.host = host }
169
+ opts.on('-I', '--include PATH', String, 'Add PATH to $LOAD_PATH') {
170
+ |path| $LOAD_PATH.unshift(path) }
171
+ opts.on('--no-control', 'Do not automatically start control thread') {
172
+ options.control = false }
173
+ opts.on('--no-quit', 'Do not quit when script finishes') {
174
+ options.quit = false }
175
+ opts.on('--no-rewrite-program', 'Don\'t set $0 to the program debugged') {
176
+ options.no_rewrite_program = true }
177
+ opts.on('--no-stop', 'Do not stop when script is loaded') {
178
+ options.stop = false }
179
+ opts.on('-nx', 'Don\'t run any byebug initialization files') {
180
+ options.nx = true }
181
+ opts.on('-p', '--port PORT', Integer, 'Port used for remote debugging') {
182
+ |port| options.port = port }
183
+ opts.on('-r', '--require SCRIPT', String, 'Require library before script') {
184
+ |name| if name == 'debug'
185
+ puts 'byebug not compatible with Ruby\'s \'debug\' lib, option ignored'
223
186
  else
224
187
  require name
225
- end
226
- end
227
- opts.on('--restart-script FILE', String,
228
- 'Name of the script file to run. Erased after read') do
188
+ end }
189
+ opts.on('--restart-script FILE', String, 'Name of the script file to run. Erased after read') do
229
190
  |restart_script|
230
191
  options.restart_script = restart_script
231
192
  unless File.exists?(options.restart_script)
@@ -241,21 +202,19 @@ EOB
241
202
  exit
242
203
  end
243
204
  end
244
- opts.on('-s', '--server', 'Listen for remote connections') do
245
- options.server = true
246
- end
247
- opts.on('-w', '--wait', 'Wait for a client connection, implies -s option') do
248
- options.wait = true
249
- end
250
- opts.on('-x', '--trace', 'Turn on line tracing') {options.tracing = true}
205
+ opts.on('-s', '--server', 'Listen for remote connections') {
206
+ options.server = true }
207
+ opts.on('-w', '--wait', 'Wait for a client connection, implies -s option') {
208
+ options.wait = true }
209
+ opts.on('-x', '--trace', 'Turn on line tracing') {
210
+ options.tracing = true }
251
211
  opts.separator ''
252
212
  opts.separator 'Common options:'
253
213
  opts.on_tail('--help', 'Show this message') do
254
214
  puts opts
255
215
  exit
256
216
  end
257
- opts.on_tail('--version',
258
- 'Print the version') do
217
+ opts.on_tail('--version', 'Print program version') do
259
218
  puts "byebug #{Byebug::VERSION}"
260
219
  exit
261
220
  end
@@ -263,8 +222,7 @@ EOB
263
222
  $VERBOSE = true
264
223
  options.verbose_long = true
265
224
  end
266
- opts.on_tail('-v',
267
- 'Print version number, then turn on verbose mode') do
225
+ opts.on_tail('-v', 'Print version number, then turn on verbose mode') do
268
226
  puts "byebug #{Byebug::VERSION}"
269
227
  $VERBOSE = true
270
228
  end
@@ -274,16 +232,10 @@ end
274
232
 
275
233
  # What file is used for byebug startup commands.
276
234
  unless defined?(OPTS_INITFILE)
277
- if RUBY_PLATFORM =~ /mswin/
278
- # Of course MS Windows has to be different
279
- OPTS_INITFILE = 'rdbopt.ini'
280
- HOME_DIR = (ENV['HOME'] ||
281
- ENV['HOMEDRIVE'].to_s + ENV['HOMEPATH'].to_s).to_s
282
- else
283
- OPTS_INITFILE = '.rdboptrc'
284
- HOME_DIR = ENV['HOME'].to_s
285
- end
235
+ OPTS_INITFILE = '.byebugoptrc'
236
+ HOME_DIR = ENV['HOME'].to_s
286
237
  end
238
+
287
239
  begin
288
240
  initfile = File.join(HOME_DIR, OPTS_INITFILE)
289
241
  eval(File.read(initfile)) if File.exist?(initfile)
@@ -294,9 +246,6 @@ opts = process_options(options)
294
246
  begin
295
247
  Byebug::ARGV = ARGV.clone if not defined? Byebug::ARGV
296
248
  byebug_path = File.expand_path($0)
297
- if RUBY_PLATFORM =~ /mswin/
298
- byebug_path += '.cmd' unless byebug_path =~ /\.cmd$/i
299
- end
300
249
  Byebug::BYEBUG_SCRIPT = byebug_path
301
250
  Byebug::INITIAL_DIR = Dir.pwd
302
251
  opts.parse! ARGV
@@ -330,9 +279,7 @@ else
330
279
  Byebug.wait_connection = options.wait
331
280
 
332
281
  if options.server
333
- # start remote mode
334
282
  Byebug.start_remote(options.host, [options.port, options.cport]) do
335
- # load initrc script
336
283
  Byebug.run_init_script(StringIO.new) unless options.nx
337
284
  end
338
285
  debug_program(options)
@@ -4,9 +4,10 @@ static VALUE mByebug; /* Ruby Byebug Module object */
4
4
  static VALUE cContext;
5
5
  static VALUE cDebugThread;
6
6
 
7
- static VALUE tracing = Qfalse;
8
- static VALUE debug = Qfalse;
9
- static VALUE locker = Qnil;
7
+ static VALUE tracing = Qfalse;
8
+ static VALUE post_mortem = Qfalse;
9
+ static VALUE debug = Qfalse;
10
+ static VALUE locker = Qnil;
10
11
 
11
12
  static VALUE contexts;
12
13
  static VALUE catchpoints;
@@ -14,11 +15,11 @@ static VALUE breakpoints;
14
15
 
15
16
  static VALUE tpLine;
16
17
  static VALUE tpCall;
18
+ static VALUE tpCCall;
17
19
  static VALUE tpReturn;
20
+ static VALUE tpCReturn;
18
21
  static VALUE tpRaise;
19
22
 
20
- static VALUE idAlive;
21
-
22
23
  static VALUE
23
24
  tp_inspect(VALUE trace_point) {
24
25
  rb_trace_arg_t *trace_arg = rb_tracearg_from_tracepoint(trace_point);
@@ -59,7 +60,7 @@ Byebug_thread_context(VALUE self, VALUE thread)
59
60
 
60
61
  context = rb_hash_aref(contexts, thread);
61
62
  if (context == Qnil) {
62
- context = context_create(thread, cDebugThread);
63
+ context = Context_create(thread, cDebugThread);
63
64
  rb_hash_aset(contexts, thread, context);
64
65
  }
65
66
  return context;
@@ -71,11 +72,13 @@ Byebug_current_context(VALUE self)
71
72
  return Byebug_thread_context(self, rb_thread_current());
72
73
  }
73
74
 
75
+ /*
74
76
  static int
75
77
  remove_dead_threads(VALUE thread, VALUE context, VALUE ignored)
76
78
  {
77
79
  return (IS_THREAD_ALIVE(thread)) ? ST_CONTINUE : ST_DELETE;
78
80
  }
81
+ */
79
82
 
80
83
  static void
81
84
  cleanup(debug_context_t *context)
@@ -96,9 +99,7 @@ cleanup(debug_context_t *context)
96
99
  static int
97
100
  check_start_processing(debug_context_t *context, VALUE thread)
98
101
  {
99
- /* return if thread is marked as 'ignored'.
100
- byebug's threads are marked this way
101
- */
102
+ /* return if thread is marked as 'ignored' */
102
103
  if(CTX_FL_TEST(context, CTX_FL_IGNORE)) return 0;
103
104
 
104
105
  while(1)
@@ -161,26 +162,32 @@ call_at_line(debug_context_t *context, char *file, int line,
161
162
  rb_funcall(context_object, rb_intern("at_line"), 2, path, lineno);
162
163
  }
163
164
 
165
+ #define EVENT_SETUP \
166
+ VALUE path, lineno, method_id, defined_class, binding, self; \
167
+ VALUE context_object; \
168
+ debug_context_t *context; \
169
+ context_object = Byebug_current_context(mByebug); \
170
+ Data_Get_Struct(context_object, debug_context_t, context); \
171
+ if (!check_start_processing(context, rb_thread_current())) return; \
172
+ load_frame_info(trace_point, &path, &lineno, &method_id, &defined_class, \
173
+ &binding, &self); \
174
+ if (debug == Qtrue) \
175
+ printf("%s (stack_size: %d)\n", \
176
+ RSTRING_PTR(tp_inspect(trace_point)), context->stack_size); \
177
+
164
178
  static void
165
179
  process_line_event(VALUE trace_point, void *data)
166
180
  {
167
- VALUE path, lineno, method_id, defined_class, binding, self;
168
- VALUE context_object;
181
+ EVENT_SETUP;
169
182
  VALUE breakpoint;
170
- debug_context_t *context;
171
183
  int moved = 0;
172
184
 
173
- context_object = Byebug_current_context(mByebug);
174
- Data_Get_Struct(context_object, debug_context_t, context);
175
- if (!check_start_processing(context, rb_thread_current())) return;
176
-
177
- load_frame_info(
178
- trace_point, &path, &lineno, &method_id, &defined_class, &binding, &self);
179
- if (debug == Qtrue)
180
- printf("%s (stack_size: %d)\n", RSTRING_PTR(tp_inspect(trace_point)),
181
- context->stack_size);
182
- update_frame(context_object, RSTRING_PTR(path), FIX2INT(lineno), method_id,
183
- defined_class, binding, self);
185
+ if (context->stack_size == 0)
186
+ push_frame(context, RSTRING_PTR(path), FIX2INT(lineno), method_id,
187
+ defined_class, binding, self);
188
+ else
189
+ update_frame(context->stack, RSTRING_PTR(path), FIX2INT(lineno), method_id,
190
+ defined_class, binding, self);
184
191
 
185
192
  if (context->last_line != FIX2INT(lineno) || context->last_file == NULL ||
186
193
  strcmp(context->last_file, RSTRING_PTR(path)))
@@ -227,52 +234,48 @@ process_line_event(VALUE trace_point, void *data)
227
234
  }
228
235
 
229
236
  static void
230
- process_return_event(VALUE trace_point, void *data)
237
+ process_c_return_event(VALUE trace_point, void *data)
231
238
  {
232
- VALUE path, lineno, method_id, defined_class, binding, self;
233
- VALUE context_object;
234
- debug_context_t *context;
239
+ EVENT_SETUP;
235
240
 
236
- context_object = Byebug_current_context(mByebug);
237
- Data_Get_Struct(context_object, debug_context_t, context);
238
- if (!check_start_processing(context, rb_thread_current())) return;
241
+ pop_frame(context);
239
242
 
240
- load_frame_info(
241
- trace_point, &path, &lineno, &method_id, &defined_class, &binding, &self);
242
- if (debug == Qtrue)
243
- printf("%s (stack_size: %d)\n", RSTRING_PTR(tp_inspect(trace_point)),
244
- context->stack_size);
243
+ cleanup(context);
244
+ }
245
+
246
+ static void
247
+ process_return_event(VALUE trace_point, void *data)
248
+ {
249
+ EVENT_SETUP;
245
250
 
246
251
  if (context->stack_size == context->stop_frame)
247
252
  {
248
253
  context->stop_next = 1;
249
254
  context->stop_frame = 0;
250
255
  }
256
+ pop_frame(context);
257
+
258
+ cleanup(context);
259
+ }
251
260
 
252
- pop_frame(context_object);
261
+ static void
262
+ process_c_call_event(VALUE trace_point, void *data)
263
+ {
264
+ EVENT_SETUP;
253
265
 
266
+ push_frame(context, RSTRING_PTR(path), FIX2INT(lineno), method_id,
267
+ defined_class, binding, self);
254
268
  cleanup(context);
255
269
  }
256
270
 
257
271
  static void
258
272
  process_call_event(VALUE trace_point, void *data)
259
273
  {
260
- VALUE path, lineno, method_id, defined_class, binding, self;
261
- VALUE context_object;
274
+ EVENT_SETUP;
262
275
  VALUE breakpoint;
263
- debug_context_t *context;
264
276
 
265
- context_object = Byebug_current_context(mByebug);
266
- Data_Get_Struct(context_object, debug_context_t, context);
267
- if (!check_start_processing(context, rb_thread_current())) return;
268
-
269
- load_frame_info(
270
- trace_point, &path, &lineno, &method_id, &defined_class, &binding, &self);
271
- if (debug == Qtrue)
272
- printf("%s (stack_size: %d)\n", RSTRING_PTR(tp_inspect(trace_point)),
273
- context->stack_size);
274
- push_frame(context_object, RSTRING_PTR(path), FIX2INT(lineno), method_id,
275
- defined_class, binding, self);
277
+ push_frame(context, RSTRING_PTR(path), FIX2INT(lineno), method_id,
278
+ defined_class, binding, self);
276
279
 
277
280
  breakpoint = find_breakpoint_by_method(breakpoints, defined_class,
278
281
  SYM2ID(method_id),
@@ -290,30 +293,27 @@ process_call_event(VALUE trace_point, void *data)
290
293
  static void
291
294
  process_raise_event(VALUE trace_point, void *data)
292
295
  {
293
- VALUE path, lineno, method_id, defined_class, binding, self;
294
- VALUE context_object;
296
+ EVENT_SETUP;
295
297
  VALUE expn_class, aclass;
296
298
  VALUE err = rb_errinfo();
297
299
  VALUE ancestors;
298
- debug_context_t *context;
299
300
  int i;
300
301
 
301
- context_object = Byebug_current_context(mByebug);
302
- Data_Get_Struct(context_object, debug_context_t, context);
303
- if (!check_start_processing(context, rb_thread_current())) return;
304
-
305
- load_frame_info(
306
- trace_point, &path, &lineno, &method_id, &defined_class, &binding, &self);
307
- if (debug == Qtrue)
308
- printf("%s (stack_size: %d)\n", RSTRING_PTR(tp_inspect(trace_point)),
309
- context->stack_size);
310
- update_frame(context_object, RSTRING_PTR(path), FIX2INT(lineno), method_id,
302
+ update_frame(context->stack, RSTRING_PTR(path), FIX2INT(lineno), method_id,
311
303
  defined_class, binding, self);
312
304
 
305
+ if (post_mortem == Qtrue && self)
306
+ {
307
+ VALUE binding = rb_binding_new();
308
+ rb_ivar_set(rb_errinfo(), rb_intern("@__debug_file"), path);
309
+ rb_ivar_set(rb_errinfo(), rb_intern("@__debug_line"), lineno);
310
+ rb_ivar_set(rb_errinfo(), rb_intern("@__debug_binding"), binding);
311
+ rb_ivar_set(rb_errinfo(), rb_intern("@__debug_context"), Context_dup(context));
312
+ }
313
+
313
314
  expn_class = rb_obj_class(err);
314
315
 
315
- if (catchpoints == Qnil ||
316
- context->stack_size == 0 ||
316
+ if (catchpoints == Qnil || context->stack_size == 0 ||
317
317
  CTX_FL_TEST(context, CTX_FL_CATCHING) ||
318
318
  RHASH_TBL(catchpoints)->num_entries == 0) {
319
319
  cleanup(context);
@@ -353,22 +353,34 @@ Byebug_setup_tracepoints(VALUE self)
353
353
  catchpoints = rb_hash_new();
354
354
 
355
355
  tpLine = rb_tracepoint_new(Qnil,
356
- RUBY_EVENT_LINE,
357
- process_line_event, NULL);
358
- rb_tracepoint_enable(tpLine);
356
+ RUBY_EVENT_LINE,
357
+ process_line_event, NULL);
358
+
359
+ tpCall = rb_tracepoint_new(Qnil,
360
+ RUBY_EVENT_CALL | RUBY_EVENT_B_CALL | RUBY_EVENT_CLASS,
361
+ process_call_event, NULL);
362
+
363
+ tpCCall = rb_tracepoint_new(Qnil,
364
+ RUBY_EVENT_C_CALL,
365
+ process_c_call_event, NULL);
359
366
 
360
367
  tpReturn = rb_tracepoint_new(Qnil,
361
- RUBY_EVENT_RETURN | RUBY_EVENT_C_RETURN | RUBY_EVENT_B_RETURN | RUBY_EVENT_END,
362
- process_return_event, NULL);
363
- rb_tracepoint_enable(tpReturn);
368
+ RUBY_EVENT_RETURN | RUBY_EVENT_B_RETURN | RUBY_EVENT_END,
369
+ process_return_event, NULL);
364
370
 
365
- tpCall = rb_tracepoint_new(Qnil,
366
- RUBY_EVENT_CALL | RUBY_EVENT_C_CALL | RUBY_EVENT_B_CALL | RUBY_EVENT_CLASS,
367
- process_call_event, NULL);
368
- rb_tracepoint_enable(tpCall);
371
+ tpCReturn = rb_tracepoint_new(Qnil,
372
+ RUBY_EVENT_C_RETURN,
373
+ process_c_return_event, NULL);
369
374
 
370
375
  tpRaise = rb_tracepoint_new(Qnil,
371
- RUBY_EVENT_RAISE, process_raise_event, NULL);
376
+ RUBY_EVENT_RAISE,
377
+ process_raise_event, NULL);
378
+
379
+ rb_tracepoint_enable(tpLine);
380
+ rb_tracepoint_enable(tpCall);
381
+ rb_tracepoint_enable(tpCCall);
382
+ rb_tracepoint_enable(tpReturn);
383
+ rb_tracepoint_enable(tpCReturn);
372
384
  rb_tracepoint_enable(tpRaise);
373
385
 
374
386
  return Qnil;
@@ -381,14 +393,30 @@ Byebug_remove_tracepoints(VALUE self)
381
393
  breakpoints = Qnil;
382
394
  catchpoints = Qnil;
383
395
 
384
- if (tpLine != Qnil) rb_tracepoint_disable(tpLine);
385
- tpLine = Qnil;
386
- if (tpReturn != Qnil) rb_tracepoint_disable(tpReturn);
387
- tpReturn = Qnil;
388
- if (tpCall != Qnil) rb_tracepoint_disable(tpCall);
389
- tpCall = Qnil;
390
- if (tpRaise != Qnil) rb_tracepoint_disable(tpRaise);
391
- tpRaise = Qnil;
396
+ if (tpLine != Qnil) {
397
+ rb_tracepoint_disable(tpLine);
398
+ tpLine = Qnil;
399
+ }
400
+ if (tpCall != Qnil) {
401
+ rb_tracepoint_disable(tpCall);
402
+ tpCall = Qnil;
403
+ }
404
+ if (tpCCall != Qnil) {
405
+ rb_tracepoint_disable(tpCCall);
406
+ tpCCall = Qnil;
407
+ }
408
+ if (tpReturn != Qnil) {
409
+ rb_tracepoint_disable(tpReturn);
410
+ tpReturn = Qnil;
411
+ }
412
+ if (tpCReturn != Qnil) {
413
+ rb_tracepoint_disable(tpCReturn);
414
+ tpCReturn = Qnil;
415
+ }
416
+ if (tpRaise != Qnil) {
417
+ rb_tracepoint_disable(tpRaise);
418
+ tpRaise = Qnil;
419
+ }
392
420
  return Qnil;
393
421
  }
394
422
 
@@ -399,16 +427,17 @@ values_i(VALUE key, VALUE value, VALUE ary)
399
427
  return ST_CONTINUE;
400
428
  }
401
429
 
430
+ #define BYEBUG_STARTED (catchpoints != Qnil)
402
431
  static VALUE
403
432
  Byebug_started(VALUE self)
404
433
  {
405
- return catchpoints != Qnil ? Qtrue : Qfalse;
434
+ return BYEBUG_STARTED;
406
435
  }
407
436
 
408
437
  static VALUE
409
438
  Byebug_stop(VALUE self)
410
439
  {
411
- if (Byebug_started(self))
440
+ if (BYEBUG_STARTED)
412
441
  {
413
442
  Byebug_remove_tracepoints(self);
414
443
  return Qfalse;
@@ -421,7 +450,7 @@ Byebug_start(VALUE self)
421
450
  {
422
451
  VALUE result;
423
452
 
424
- if (Byebug_started(self))
453
+ if (BYEBUG_STARTED)
425
454
  result = Qfalse;
426
455
  else
427
456
  {
@@ -435,6 +464,21 @@ Byebug_start(VALUE self)
435
464
  return result;
436
465
  }
437
466
 
467
+ static VALUE
468
+ set_current_skipped_status(VALUE status)
469
+ {
470
+ VALUE context_object;
471
+ debug_context_t *context;
472
+
473
+ context_object = Byebug_current_context(mByebug);
474
+ Data_Get_Struct(context_object, debug_context_t, context);
475
+ if (status)
476
+ CTX_FL_SET(context, CTX_FL_SKIPPED);
477
+ else
478
+ CTX_FL_UNSET(context, CTX_FL_SKIPPED);
479
+ return Qnil;
480
+ }
481
+
438
482
  static VALUE
439
483
  Byebug_load(int argc, VALUE *argv, VALUE self)
440
484
  {
@@ -466,24 +510,65 @@ Byebug_load(int argc, VALUE *argv, VALUE self)
466
510
  return errinfo;
467
511
  }
468
512
 
469
- /* We should run all at_exit handler's in order to provide,
470
- * for instance, a chance to run all defined test cases */
513
+ /* We should run all at_exit handler's in order to provide, for instance, a
514
+ * chance to run all defined test cases */
471
515
  rb_exec_end_proc();
472
516
 
473
517
  return Qnil;
474
518
  }
475
519
 
520
+ static VALUE
521
+ debug_at_exit_c(VALUE proc)
522
+ {
523
+ return rb_funcall(proc, rb_intern("call"), 0);
524
+ }
525
+
526
+ static void
527
+ debug_at_exit_i(VALUE proc)
528
+ {
529
+ if (BYEBUG_STARTED)
530
+ {
531
+ set_current_skipped_status(Qtrue);
532
+ rb_ensure(debug_at_exit_c, proc, set_current_skipped_status, Qfalse);
533
+ }
534
+ else
535
+ debug_at_exit_c(proc);
536
+ }
537
+
538
+ static VALUE
539
+ Byebug_at_exit(VALUE self)
540
+ {
541
+ VALUE proc;
542
+ if (!rb_block_given_p()) rb_raise(rb_eArgError, "called without a block");
543
+ proc = rb_block_proc();
544
+ rb_set_end_proc(debug_at_exit_i, proc);
545
+ return proc;
546
+ }
547
+
476
548
  static VALUE
477
549
  Byebug_tracing(VALUE self)
478
550
  {
479
- return tracing;
551
+ return tracing;
480
552
  }
481
553
 
482
554
  static VALUE
483
555
  Byebug_set_tracing(VALUE self, VALUE value)
484
556
  {
485
- tracing = RTEST(value) ? Qtrue : Qfalse;
486
- return value;
557
+ tracing = RTEST(value) ? Qtrue : Qfalse;
558
+ return value;
559
+ }
560
+
561
+ static VALUE
562
+ Byebug_post_mortem(VALUE self)
563
+ {
564
+ return post_mortem;
565
+ }
566
+
567
+ static VALUE
568
+ Byebug_set_post_mortem(VALUE self, VALUE value)
569
+ {
570
+ post_mortem = RTEST(value) ? Qtrue : Qfalse;
571
+ return value;
487
572
  }
488
573
 
489
574
  static VALUE
@@ -494,7 +579,7 @@ Byebug_contexts(VALUE self)
494
579
  ary = rb_ary_new();
495
580
 
496
581
  /* check that all contexts point to alive threads */
497
- rb_hash_foreach(contexts, remove_dead_threads, 0);
582
+ /*rb_hash_foreach(contexts, remove_dead_threads, self);*/
498
583
 
499
584
  rb_hash_foreach(contexts, values_i, ary);
500
585
 
@@ -551,11 +636,12 @@ Init_byebug()
551
636
  rb_define_module_function(mByebug, "_start", Byebug_start, 0);
552
637
  rb_define_module_function(mByebug, "stop", Byebug_stop, 0);
553
638
  rb_define_module_function(mByebug, "started?", Byebug_started, 0);
554
- rb_define_module_function(mByebug, "tracing", Byebug_tracing, 0);
639
+ rb_define_module_function(mByebug, "tracing?", Byebug_tracing, 0);
555
640
  rb_define_module_function(mByebug, "tracing=", Byebug_set_tracing, 1);
556
641
  rb_define_module_function(mByebug, "debug_load", Byebug_load, -1);
557
-
558
- idAlive = rb_intern("alive?");
642
+ rb_define_module_function(mByebug, "debug_at_exit", Byebug_at_exit, 0);
643
+ rb_define_module_function(mByebug, "post_mortem?", Byebug_post_mortem, 0);
644
+ rb_define_module_function(mByebug, "post_mortem=", Byebug_set_post_mortem, 1);
559
645
 
560
646
  cContext = Init_context(mByebug);
561
647