byebug 1.0.3 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -0
- data/README.md +13 -11
- data/Rakefile +0 -6
- data/bin/byebug +83 -136
- data/ext/byebug/byebug.c +182 -96
- data/ext/byebug/byebug.h +5 -7
- data/ext/byebug/context.c +52 -40
- data/lib/byebug.rb +81 -81
- data/lib/byebug/command.rb +18 -35
- data/lib/byebug/commands/control.rb +1 -1
- data/lib/byebug/commands/display.rb +0 -2
- data/lib/byebug/commands/enable.rb +4 -16
- data/lib/byebug/commands/eval.rb +5 -3
- data/lib/byebug/commands/frame.rb +68 -69
- data/lib/byebug/commands/help.rb +2 -1
- data/lib/byebug/commands/info.rb +43 -42
- data/lib/byebug/commands/method.rb +4 -3
- data/lib/byebug/commands/set.rb +10 -19
- data/lib/byebug/commands/show.rb +6 -13
- data/lib/byebug/interface.rb +1 -1
- data/lib/byebug/processor.rb +14 -17
- data/lib/byebug/version.rb +1 -2
- data/old_doc/byebug.texi +576 -847
- data/test/breakpoints_test.rb +0 -1
- data/test/conditions_test.rb +35 -33
- data/test/display_test.rb +14 -13
- data/test/edit_test.rb +28 -25
- data/test/eval_test.rb +0 -2
- data/test/finish_test.rb +4 -3
- data/test/frame_test.rb +20 -21
- data/test/help_test.rb +26 -23
- data/test/info_test.rb +105 -108
- data/test/irb_test.rb +26 -25
- data/test/kill_test.rb +19 -19
- data/test/list_test.rb +140 -156
- data/test/method_test.rb +21 -22
- data/test/post_mortem_test.rb +2 -5
- data/test/quit_test.rb +16 -17
- data/test/reload_test.rb +2 -2
- data/test/restart_test.rb +0 -1
- data/test/save_test.rb +31 -32
- data/test/set_test.rb +50 -47
- data/test/show_test.rb +67 -66
- data/test/source_test.rb +31 -34
- data/test/stepping_test.rb +32 -34
- data/test/support/test_dsl.rb +1 -1
- data/test/trace_test.rb +1 -2
- data/test/variables_test.rb +36 -34
- metadata +2 -4
- data/lib/byebug/commands/tmate.rb +0 -36
- data/test/tmate_test.rb +0 -44
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dc04cc8b68063ec31b6318a54bd88e1d4ee354be
|
4
|
+
data.tar.gz: 070611b0dbc7fcc7f6fa276b588b32297c5d5588
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1434e8a81a8f62b6af39ba73ba527c44b77c9219d06760ac36cc392d98de069f007d3a3b65f56c3f4db6b6ae3fcd3034fc660d8d9fa01781f677a53df2538bac
|
7
|
+
data.tar.gz: e679189a446359f9d98b18f086472129826218f57d1e1cc0c8d71fa186c146a917b0efafed1c4cc9a991d88f2390fff41c36d160a8f3a4ab2fb23f1ceacd1b90
|
data/CHANGELOG.md
CHANGED
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
|
-
|
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
|
-
|
20
|
+
## Configuration
|
22
21
|
|
23
|
-
|
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
|
-
#
|
18
|
-
#
|
19
|
-
#
|
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
|
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
|
-
#
|
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
|
-
#
|
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
|
-
#
|
45
|
+
# Activate post-mortem mode.
|
47
46
|
#
|
48
47
|
#<tt>--no-control</tt>::
|
49
|
-
#
|
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
|
-
#
|
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
|
-
#
|
61
|
+
# Use port <i>port</i> for remote debugging.
|
56
62
|
#
|
57
63
|
#<tt>-r | --require</tt><i>script</i>::
|
58
|
-
#
|
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
|
67
|
-
#
|
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>--
|
70
|
-
#
|
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
|
-
#
|
77
|
-
#
|
78
|
-
#
|
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>--
|
85
|
-
#
|
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
|
91
|
-
#
|
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
|
99
|
-
#
|
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")
|
169
|
-
|annotate|
|
170
|
-
|
171
|
-
|
172
|
-
opts.on("
|
173
|
-
options.
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
options.
|
178
|
-
|
179
|
-
|
180
|
-
opts.on(
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
options.
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
opts.on('-
|
193
|
-
|
|
194
|
-
|
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
|
-
|
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')
|
245
|
-
options.server = true
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
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
|
-
|
278
|
-
|
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)
|
data/ext/byebug/byebug.c
CHANGED
@@ -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
|
8
|
-
static VALUE
|
9
|
-
static VALUE
|
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 =
|
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
|
-
|
168
|
-
VALUE context_object;
|
181
|
+
EVENT_SETUP;
|
169
182
|
VALUE breakpoint;
|
170
|
-
debug_context_t *context;
|
171
183
|
int moved = 0;
|
172
184
|
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
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
|
-
|
237
|
+
process_c_return_event(VALUE trace_point, void *data)
|
231
238
|
{
|
232
|
-
|
233
|
-
VALUE context_object;
|
234
|
-
debug_context_t *context;
|
239
|
+
EVENT_SETUP;
|
235
240
|
|
236
|
-
|
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
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
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
|
-
|
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
|
-
|
261
|
-
VALUE context_object;
|
274
|
+
EVENT_SETUP;
|
262
275
|
VALUE breakpoint;
|
263
|
-
debug_context_t *context;
|
264
276
|
|
265
|
-
|
266
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
357
|
-
|
358
|
-
|
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
|
-
|
362
|
-
|
363
|
-
rb_tracepoint_enable(tpReturn);
|
368
|
+
RUBY_EVENT_RETURN | RUBY_EVENT_B_RETURN | RUBY_EVENT_END,
|
369
|
+
process_return_event, NULL);
|
364
370
|
|
365
|
-
|
366
|
-
|
367
|
-
|
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
|
-
|
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)
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
if (tpCall != Qnil)
|
389
|
-
|
390
|
-
|
391
|
-
|
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
|
434
|
+
return BYEBUG_STARTED;
|
406
435
|
}
|
407
436
|
|
408
437
|
static VALUE
|
409
438
|
Byebug_stop(VALUE self)
|
410
439
|
{
|
411
|
-
if (
|
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 (
|
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
|
-
*
|
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
|
-
|
551
|
+
return tracing;
|
480
552
|
}
|
481
553
|
|
482
554
|
static VALUE
|
483
555
|
Byebug_set_tracing(VALUE self, VALUE value)
|
484
556
|
{
|
485
|
-
|
486
|
-
|
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,
|
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
|
-
|
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
|
|