byebug 1.0.3 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
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