rbx-trepanning 0.0.7-universal-rubinius-1.2 → 0.0.8-universal-rubinius-1.2
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog +236 -0
- data/NEWS +16 -0
- data/Rakefile +60 -11
- data/app/breakpoint.rb +5 -1
- data/app/brkptmgr.rb +5 -0
- data/app/cmd_parse.kpeg +225 -0
- data/app/cmd_parse.rb +209 -0
- data/app/cmd_parser.rb +1894 -0
- data/app/default.rb +0 -1
- data/app/method.rb +12 -8
- data/app/options.rb +2 -9
- data/app/validate.rb +2 -2
- data/bin/trepanx +3 -3
- data/lib/trepanning.rb +9 -6
- data/processor/breakpoint.rb +5 -19
- data/processor/command/alias.rb +4 -5
- data/processor/command/base/submgr.rb +2 -2
- data/processor/command/break.rb +44 -66
- data/processor/command/condition.rb +2 -0
- data/processor/command/continue.rb +11 -41
- data/processor/command/disassemble.rb +2 -0
- data/processor/command/eval.rb +20 -8
- data/processor/command/exit.rb +3 -2
- data/{doc → processor/command/help}/.gitignore +0 -0
- data/processor/command/help/command.txt +48 -0
- data/processor/command/help/filename.txt +40 -0
- data/processor/command/help/location.txt +37 -0
- data/processor/command/help.rb +52 -73
- data/processor/command/info_subcmd/breakpoints.rb +35 -13
- data/processor/command/info_subcmd/files.rb +34 -25
- data/processor/command/info_subcmd/frame.rb +67 -0
- data/processor/command/kill.rb +0 -1
- data/processor/command/restart.rb +8 -8
- data/processor/command/save.rb +58 -0
- data/processor/command/set_subcmd/trace_subcmd/buffer.rb +1 -1
- data/processor/command/set_subcmd/trace_subcmd/print.rb +1 -1
- data/processor/command/show.rb +7 -6
- data/processor/command/step.rb +16 -3
- data/processor/command/tbreak.rb +1 -1
- data/processor/disassemble.rb +1 -1
- data/processor/help.rb +20 -0
- data/processor/load_cmds.rb +53 -4
- data/processor/location.rb +47 -1
- data/processor/main.rb +4 -9
- data/processor/mock.rb +3 -3
- data/processor/running.rb +16 -17
- data/processor/validate.rb +171 -159
- data/rbx-trepanning.gemspec +1 -1
- data/test/example/debugger-stop.rb +16 -0
- data/test/functional/test-break-name.rb +1 -1
- data/test/functional/test-eval.rb +115 -0
- data/test/functional/test-tbreak.rb +1 -1
- data/test/integration/helper.rb +5 -2
- data/test/unit/cmd-helper.rb +1 -1
- data/test/unit/test-app-cmd_parse.rb +97 -0
- data/test/unit/test-app-cmd_parser.rb +22 -0
- data/test/unit/test-app-options.rb +1 -0
- data/test/unit/test-app-validate.rb +2 -2
- data/test/unit/test-cmd-break.rb +47 -5
- data/test/unit/test-completion.rb +2 -1
- data/test/unit/test-proc-location.rb +11 -0
- data/test/unit/test-proc-validate.rb +68 -30
- metadata +26 -11
- data/doc/debugger.html +0 -108
data/app/default.rb
CHANGED
@@ -22,7 +22,6 @@ class Trepan
|
|
22
22
|
|
23
23
|
:restart_argv => Rubinius::OS_ARGV,
|
24
24
|
# Command run when "restart" is given.
|
25
|
-
:restore_profile => nil, # Profile used to set/restore debugger state
|
26
25
|
:server => false, # Out-of-process debugging?
|
27
26
|
:skip_loader => false, # If run via -Xdebug or trepanx
|
28
27
|
# command-line we need this to skip
|
data/app/method.rb
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
module Trepanning
|
3
3
|
module Method
|
4
4
|
|
5
|
+
module_function
|
5
6
|
## FIXME: until the next two routines find their way back into
|
6
7
|
## Rubinius::CompiledMethod...
|
7
8
|
##
|
@@ -23,7 +24,6 @@ module Trepanning
|
|
23
24
|
end
|
24
25
|
return nil
|
25
26
|
end
|
26
|
-
module_function :locate_line_in_cm
|
27
27
|
|
28
28
|
## FIXME: Try using Routine in Rubinius now.
|
29
29
|
##
|
@@ -54,7 +54,6 @@ module Trepanning
|
|
54
54
|
# No child method is a match - fail
|
55
55
|
return nil
|
56
56
|
end
|
57
|
-
module_function :locate_line
|
58
57
|
|
59
58
|
def lines_of_method(cm)
|
60
59
|
lines = []
|
@@ -63,7 +62,6 @@ module Trepanning
|
|
63
62
|
end
|
64
63
|
return lines
|
65
64
|
end
|
66
|
-
module_function :lines_of_method
|
67
65
|
|
68
66
|
# Return true if ip is the start of some instruction in meth.
|
69
67
|
# FIXME: be more stringent.
|
@@ -71,7 +69,6 @@ module Trepanning
|
|
71
69
|
size = cm.lines.size
|
72
70
|
ip >= 0 && ip < cm.lines[size-1]
|
73
71
|
end
|
74
|
-
module_function :valid_ip?
|
75
72
|
|
76
73
|
# Returns a CompiledMethod for the specified line. We search the
|
77
74
|
# current method +meth+ and then up the parent scope. If we hit
|
@@ -84,13 +81,11 @@ module Trepanning
|
|
84
81
|
end
|
85
82
|
|
86
83
|
lines = lines_of_method(cm)
|
87
|
-
## p ['++++1', cm, lines]
|
88
84
|
return cm if lines.member?(line)
|
89
85
|
scope = cm.scope
|
90
86
|
return nil unless scope.current_script
|
91
87
|
cm = scope.current_script.compiled_method
|
92
88
|
lines = lines_of_method(cm)
|
93
|
-
## p ['++++2', cm, lines]
|
94
89
|
until lines.member?(line) do
|
95
90
|
child = scope
|
96
91
|
scope = scope.parent
|
@@ -103,11 +98,19 @@ module Trepanning
|
|
103
98
|
end
|
104
99
|
cm = scope.current_script.compiled_method
|
105
100
|
lines = lines_of_method(cm)
|
106
|
-
## p ['++++3', cm, lines]
|
107
101
|
end
|
108
102
|
return cm
|
109
103
|
end
|
110
|
-
|
104
|
+
|
105
|
+
def top_scope(cm)
|
106
|
+
scope = cm.scope
|
107
|
+
while true do
|
108
|
+
scope = scope.parent
|
109
|
+
break unless scope && scope.current_script
|
110
|
+
cm = scope.current_script.compiled_method
|
111
|
+
end
|
112
|
+
cm
|
113
|
+
end
|
111
114
|
end
|
112
115
|
|
113
116
|
end
|
@@ -165,6 +168,7 @@ if __FILE__ == $0
|
|
165
168
|
p lines_of_method(cm)
|
166
169
|
find_line(line)
|
167
170
|
p find_method_with_line(cm, line+2)
|
171
|
+
puts "top scope: #{top_scope(cm)}"
|
168
172
|
ip = locate_line( __LINE__, cm)[1]
|
169
173
|
puts "Line #{__LINE__} has ip #{ip}"
|
170
174
|
[-1, 0, 10, ip, 10000].each do |i|
|
data/app/options.rb
CHANGED
@@ -9,7 +9,7 @@ class Trepan
|
|
9
9
|
require 'rubygems'; require 'require_relative'
|
10
10
|
require_relative 'default'
|
11
11
|
|
12
|
-
Trepan::VERSION = '0.0.
|
12
|
+
Trepan::VERSION = '0.0.8'
|
13
13
|
Trepan::PROGRAM = 'trepanx'
|
14
14
|
|
15
15
|
def self.show_version
|
@@ -82,13 +82,6 @@ EOB
|
|
82
82
|
|num|
|
83
83
|
options[:port] = num
|
84
84
|
end
|
85
|
-
opts.on("--restore PROFILE", String,
|
86
|
-
"Restore debugger state using PROFILE") do |profile|
|
87
|
-
if File.readable?(profile)
|
88
|
-
options[:restore_profile] = profile
|
89
|
-
stderr.puts "Debugger command file #{profile} is not readable. --restore option ignored."
|
90
|
-
end
|
91
|
-
end
|
92
85
|
opts.on('--server',
|
93
86
|
"Set up for out-of-process debugging") do
|
94
87
|
if options[:client]
|
@@ -98,7 +91,7 @@ EOB
|
|
98
91
|
end
|
99
92
|
end
|
100
93
|
opts.on('--[no-]highlight',
|
101
|
-
"Use [no] syntax
|
94
|
+
"Use [no] syntax highlight output") do |v|
|
102
95
|
options[:highlight] = ((v) ? :term : nil)
|
103
96
|
end
|
104
97
|
opts.on('--[no-]readline',
|
data/app/validate.rb
CHANGED
@@ -5,7 +5,7 @@ class Trepan
|
|
5
5
|
def line_or_ip(arg_str)
|
6
6
|
arg=arg_str.dup
|
7
7
|
is_ip =
|
8
|
-
if '
|
8
|
+
if '@' == arg[0..0]
|
9
9
|
arg[0] = ''
|
10
10
|
true
|
11
11
|
else
|
@@ -24,7 +24,7 @@ end
|
|
24
24
|
|
25
25
|
if __FILE__ == $0
|
26
26
|
include Trepan::Validate
|
27
|
-
%w(
|
27
|
+
%w(@1 oink 1 12 -12).each do |arg|
|
28
28
|
puts "line_or_ip(#{arg})=#{line_or_ip(arg).inspect}"
|
29
29
|
end
|
30
30
|
end
|
data/bin/trepanx
CHANGED
@@ -50,9 +50,9 @@ if File.basename(__FILE__) == File.basename($0)
|
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
53
|
-
program_to_debug = ARGV.shift
|
54
|
-
program_to_debug = whence_file(
|
55
|
-
File.exist?(
|
53
|
+
program_to_debug = (Trepan::PROG_UNRESOLVED_SCRIPT = ARGV.shift).dup
|
54
|
+
program_to_debug = whence_file(Trepan::PROG_UNRESOLVED_SCRIPT) unless
|
55
|
+
File.exist?(Trepan::PROG_UNRESOLVED_SCRIPT)
|
56
56
|
Trepan::PROG_SCRIPT = program_to_debug
|
57
57
|
|
58
58
|
opts = {}
|
data/lib/trepanning.rb
CHANGED
@@ -124,8 +124,6 @@ class Trepan
|
|
124
124
|
|
125
125
|
# Run user debugger command startup files.
|
126
126
|
add_startup_files unless @settings[:nx]
|
127
|
-
add_command_file(@settings[:restore_profile]) if
|
128
|
-
@settings[:restore_profile] && File.readable?(@settings[:restore_profile])
|
129
127
|
end
|
130
128
|
|
131
129
|
# The method is called when we want to do debugger command completion
|
@@ -155,7 +153,7 @@ class Trepan
|
|
155
153
|
def skip_loader
|
156
154
|
cmds =
|
157
155
|
if @settings[:skip_loader] == :Xdebug
|
158
|
-
['continue Rubinius::CodeLoader
|
156
|
+
['continue Rubinius::CodeLoader.load_script',
|
159
157
|
'continue 67',
|
160
158
|
# 'set kernelstep off', # eventually would like 'on'
|
161
159
|
'step', 'set hidelevel -1'
|
@@ -197,7 +195,7 @@ class Trepan
|
|
197
195
|
# Startup the debugger, skipping back +offset+ frames. This lets you start
|
198
196
|
# the debugger straight into callers method.
|
199
197
|
#
|
200
|
-
def
|
198
|
+
def debugger(settings = {:immediate => false})
|
201
199
|
@settings = @settings.merge(settings)
|
202
200
|
skip_loader if @settings[:skip_loader]
|
203
201
|
spinup_thread
|
@@ -206,6 +204,12 @@ class Trepan
|
|
206
204
|
@processor.hidelevels[@thread] = @settings[:hide_level]
|
207
205
|
end
|
208
206
|
|
207
|
+
# unless defined?(PROG_UNRESOLVED_SCRIPT)
|
208
|
+
# # We may later do more sophisticated things...
|
209
|
+
# Trepan.const_set('PROG_UNRESOLVED_SCRIPT',
|
210
|
+
# Rubinius::OS_ARGV.index($0) ? $0 : nil)
|
211
|
+
# end
|
212
|
+
|
209
213
|
process_cmdfile_setting(settings)
|
210
214
|
|
211
215
|
# Feed info to the debugger thread!
|
@@ -225,8 +229,7 @@ class Trepan
|
|
225
229
|
Thread.current.set_debugger_thread @thread
|
226
230
|
self
|
227
231
|
end
|
228
|
-
|
229
|
-
alias debugger start
|
232
|
+
alias start debugger
|
230
233
|
|
231
234
|
def stop(settings = {})
|
232
235
|
@processor.finalize
|
data/processor/breakpoint.rb
CHANGED
@@ -45,8 +45,9 @@ class Trepan
|
|
45
45
|
bp
|
46
46
|
end
|
47
47
|
|
48
|
-
def set_breakpoint_method(
|
49
|
-
opts={:event => 'brkpt'
|
48
|
+
def set_breakpoint_method(meth, line=nil, ip=nil,
|
49
|
+
opts={:event => 'brkpt', :negate=>false,
|
50
|
+
:temp => false})
|
50
51
|
cm =
|
51
52
|
if meth.kind_of?(Method) || meth.kind_of?(UnboundMethod)
|
52
53
|
meth.executable
|
@@ -60,7 +61,7 @@ class Trepan
|
|
60
61
|
end
|
61
62
|
|
62
63
|
if line
|
63
|
-
ip = cm.first_ip_on_line(line)
|
64
|
+
ip = cm.first_ip_on_line(line, -2)
|
64
65
|
|
65
66
|
unless ip
|
66
67
|
errmsg "Unknown line '#{line}' in method '#{cm.name}'"
|
@@ -74,7 +75,7 @@ class Trepan
|
|
74
75
|
# def lines without code will have value -1.
|
75
76
|
ip = 0 if -1 == ip
|
76
77
|
|
77
|
-
bp = @brkpts.add(
|
78
|
+
bp = @brkpts.add(meth.name, cm, ip, line, @brkpts.max+1, opts)
|
78
79
|
bp.activate
|
79
80
|
msg("Set %sbreakpoint #{bp.id}: #{meth.name}() at #{bp.location}" %
|
80
81
|
(opts[:temp] ? 'temporary ' : ''))
|
@@ -144,21 +145,6 @@ class Trepan
|
|
144
145
|
return true
|
145
146
|
end
|
146
147
|
|
147
|
-
# MRI 1.9.2 code
|
148
|
-
# # Enable or disable a breakpoint given its breakpoint number.
|
149
|
-
# def en_disable_breakpoint_by_number(bpnum, do_enable=true)
|
150
|
-
# bp = breakpoint_find(bpnum)
|
151
|
-
# return false unless bp
|
152
|
-
|
153
|
-
# enable_disable = do_enable ? 'en' : 'dis'
|
154
|
-
# if bp.enabled? == do_enable
|
155
|
-
# errmsg('Breakpoint %d previously %sabled.' %
|
156
|
-
# [bpnum, enable_disable])
|
157
|
-
# return false
|
158
|
-
# end
|
159
|
-
# bp.enabled = do_enable
|
160
|
-
# return true
|
161
|
-
# end
|
162
148
|
end
|
163
149
|
end
|
164
150
|
|
data/processor/command/alias.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
|
1
|
+
# Copyright (C) 2010, 2011 Rocky Bernstein <rockyb@rubyforge.net>
|
2
2
|
require 'rubygems'; require 'require_relative'
|
3
3
|
require_relative 'base/cmd'
|
4
4
|
|
@@ -11,12 +11,11 @@ class Trepan::Command::AliasCommand < Trepan::Command
|
|
11
11
|
|
12
12
|
Add an alias for a COMMAND
|
13
13
|
|
14
|
-
See also 'unalias'.
|
14
|
+
See also 'unalias' and 'show #{NAME}'.
|
15
15
|
HELP
|
16
16
|
|
17
17
|
CATEGORY = 'support'
|
18
18
|
MAX_ARGS = 2 # Need at most this many
|
19
|
-
NAME = File.basename(__FILE__, '.rb')
|
20
19
|
NEED_STACK = true
|
21
20
|
SHORT_HELP = 'Add an alias for a debugger command'
|
22
21
|
end
|
@@ -24,9 +23,9 @@ See also 'unalias'.
|
|
24
23
|
# Run command.
|
25
24
|
def run(args)
|
26
25
|
if args.size == 1
|
27
|
-
@proc.commands['show'].run(%
|
26
|
+
@proc.commands['show'].run(%W(show #{NAME}))
|
28
27
|
elsif args.size == 2
|
29
|
-
@proc.commands['show'].run(%W(show
|
28
|
+
@proc.commands['show'].run(%W(show #{NAME} #{args[1]}))
|
30
29
|
else
|
31
30
|
junk, al, command = args
|
32
31
|
old_command = @proc.aliases[al]
|
@@ -70,8 +70,8 @@ class Trepan::SubcommandMgr < Trepan::Command
|
|
70
70
|
subcmd_class = Trepan::SubSubcommand.const_get(name)
|
71
71
|
begin
|
72
72
|
cmd = subcmd_class.send(:new, self, parent)
|
73
|
-
rescue
|
74
|
-
puts "Subcmd #{name} is bad"
|
73
|
+
rescue Exception => exc
|
74
|
+
puts "Subcmd #{name} in #{parent.name.inspect} is bad: #{exc}"
|
75
75
|
end
|
76
76
|
@subcmds.add(cmd)
|
77
77
|
end
|
data/processor/command/break.rb
CHANGED
@@ -1,82 +1,47 @@
|
|
1
|
-
# Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
|
1
|
+
# Copyright (C) 2010, 2011 Rocky Bernstein <rockyb@rubyforge.net>
|
2
2
|
require 'rubygems'; require 'require_relative'
|
3
3
|
require_relative './base/cmd'
|
4
4
|
|
5
|
-
class Trepan::Command::
|
5
|
+
class Trepan::Command::BreakCommand < Trepan::Command
|
6
6
|
|
7
7
|
ALIASES = %w(b brk)
|
8
8
|
CATEGORY = 'breakpoints'
|
9
9
|
NAME = File.basename(__FILE__, '.rb')
|
10
10
|
HELP = <<-HELP
|
11
|
-
#{NAME}
|
12
|
-
#{NAME} [line number|offset]
|
13
|
-
#{NAME} Class[.#]method[:line-or-offset]
|
11
|
+
#{NAME} LOCATION [ {if|unless} CONDITION ]
|
14
12
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
The current method name is used for the start of the search. If a line
|
21
|
-
number is given and the line number is not found in that method,
|
22
|
-
enclosing scopes are searched for the line.
|
23
|
-
|
24
|
-
The last form is the most explicit. Use '#' to specify an instance
|
25
|
-
method and '.' to specify a class method. If a line number or offset
|
26
|
-
is omitted, we use the first line of the method.
|
13
|
+
Set a breakpoint. In the second form where CONDITIOn is given, the
|
14
|
+
condition is evaluated in the context of the position. We stop only If
|
15
|
+
CONDITION evalutes to non-false/nil and the "if" form used, or it is
|
16
|
+
false and the "unless" form used.\
|
27
17
|
|
28
18
|
Examples:
|
19
|
+
#{NAME}
|
20
|
+
#{NAME} 10 # set breakpoint on line 10
|
21
|
+
#{NAME} 10 if 1 == a # like above but only if a is equal to 1
|
22
|
+
#{NAME} 10 unless 1 == a # like above but only if a is equal to 1
|
23
|
+
#{NAME} me.rb:10
|
24
|
+
#{NAME} @20 # set breakpoint VM Instruction Sequence offset 20
|
25
|
+
#{NAME} Kernel.pp # Set a breakpoint at the beginning of Kernel.pp
|
29
26
|
|
30
|
-
|
31
|
-
#{NAME} 5 # set breakpoint on line 5
|
32
|
-
#{NAME} O5 # set breakpoint at offset 5
|
33
|
-
#{NAME} o5 # same as above
|
34
|
-
#{NAME} Array#pop::3 # Set break at instance method 'pop' in Array, line 3
|
35
|
-
#{NAME} Trepan.start:3 # Set break in class method 'start' of Trepan, line 3
|
36
|
-
#{NAME} Trepan.start:o3 # Same as above but at offset 3, not line 3.
|
37
|
-
#{NAME} Trepan.start # Set break in class method 'start' of Trepan
|
38
|
-
|
39
|
-
See also 'tbreak', 'info breakpoint', and 'delete'.
|
27
|
+
See also condition, continue and "help location".
|
40
28
|
HELP
|
41
29
|
SHORT_HELP = 'Set a breakpoint at a point in a method'
|
42
30
|
|
31
|
+
# This method runs the command
|
43
32
|
def run(args, temp=false)
|
44
|
-
arg_str = args[1..-1].join(' ')
|
45
|
-
|
46
|
-
describe, klass_name, which, name, line, ip =
|
47
|
-
@proc.breakpoint_position(args[1..-1])
|
48
|
-
event = temp ? 'tbrkpt' : 'brkpt'
|
49
|
-
opts={:event => event, :temp => temp}
|
50
|
-
if name.kind_of?(Rubinius::CompiledMethod)
|
51
|
-
bp = @proc.set_breakpoint_method(describe, name, line, ip, opts)
|
52
|
-
else
|
53
|
-
return unless klass_name
|
54
|
-
|
55
|
-
begin
|
56
|
-
klass = @proc.debug_eval(klass_name, settings[:maxstring])
|
57
|
-
rescue NameError
|
58
|
-
errmsg "Unable to find class/module: #{klass_name}"
|
59
|
-
ask_deferred klass_name, which, name, line
|
60
|
-
return
|
61
|
-
end
|
62
|
-
|
63
|
-
begin
|
64
|
-
if which == "#"
|
65
|
-
method = klass.instance_method(name)
|
66
|
-
else
|
67
|
-
method = klass.method(name)
|
68
|
-
end
|
69
|
-
rescue NameError
|
70
|
-
errmsg "Unable to find method '#{name}' in #{klass}"
|
71
|
-
ask_deferred klass_name, which, name, line
|
72
|
-
return
|
73
|
-
end
|
74
33
|
|
75
|
-
|
34
|
+
arg_str = args.size == 1 ? @proc.frame.line.to_s : @proc.cmd_argstr
|
35
|
+
cm, line, ip, condition, negate =
|
36
|
+
@proc.breakpoint_position(arg_str, true)
|
37
|
+
if cm
|
38
|
+
event = temp ? 'tbrkpt' : 'brkpt'
|
39
|
+
opts={:event => event, :temp => temp, :condition => condition,
|
40
|
+
:negate => negate}
|
41
|
+
bp = @proc.set_breakpoint_method(cm, line, ip, opts)
|
42
|
+
bp.set_temp! if temp
|
43
|
+
return bp
|
76
44
|
end
|
77
|
-
|
78
|
-
bp.set_temp! if temp
|
79
|
-
return bp
|
80
45
|
end
|
81
46
|
|
82
47
|
def ask_deferred(klass_name, which, name, line)
|
@@ -92,9 +57,22 @@ end
|
|
92
57
|
if __FILE__ == $0
|
93
58
|
require_relative '../mock'
|
94
59
|
dbgr, cmd = MockDebugger::setup
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
60
|
+
# require_relative '../../lib/trepanning'
|
61
|
+
def run_cmd(cmd, args)
|
62
|
+
cmd.proc.instance_variable_set('@cmd_argstr', args[1..-1].join(' '))
|
63
|
+
cmd.run(args)
|
64
|
+
end
|
65
|
+
|
66
|
+
run_cmd(cmd, [cmd.name])
|
67
|
+
run_cmd(cmd, [cmd.name, __LINE__.to_s])
|
68
|
+
|
69
|
+
def foo
|
70
|
+
5
|
71
|
+
end
|
72
|
+
run_cmd(cmd, [cmd.name, 'foo', (__LINE__-2).to_s])
|
73
|
+
run_cmd(cmd, [cmd.name, 'foo'])
|
74
|
+
run_cmd(cmd, [cmd.name, "MockDebugger::setup"])
|
75
|
+
require 'irb'
|
76
|
+
run_cmd(cmd, [cmd.name, "IRB.start"])
|
77
|
+
run_cmd(cmd, [cmd.name, 'foo93'])
|
100
78
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (C) 2011 Rocky Bernstein <rockyb@rubyforge.net>
|
1
|
+
# Copyright (C) 2010, 2011 Rocky Bernstein <rockyb@rubyforge.net>
|
2
2
|
require 'rubygems'; require 'require_relative'
|
3
3
|
require_relative 'base/cmd'
|
4
4
|
require_relative '../stepping'
|
@@ -7,7 +7,7 @@ class Trepan::Command::ContinueCommand < Trepan::Command
|
|
7
7
|
unless defined?(HELP)
|
8
8
|
NAME = File.basename(__FILE__, '.rb')
|
9
9
|
HELP = <<-HELP
|
10
|
-
#{NAME} [
|
10
|
+
#{NAME} [LOCATION]
|
11
11
|
|
12
12
|
Leave the debugger loop and continue execution. Subsequent entry to
|
13
13
|
the debugger however may occur via breakpoints or explicit calls, or
|
@@ -24,7 +24,7 @@ Examples:
|
|
24
24
|
#{NAME} gcd # continue to first instruction of method gcd
|
25
25
|
#{NAME} IRB.start o7 # continue to IRB.start offset 7
|
26
26
|
|
27
|
-
See also 'step', 'next', 'finish',
|
27
|
+
See also 'step', 'next', 'finish', 'nexti' commands and "help location".
|
28
28
|
HELP
|
29
29
|
|
30
30
|
ALIASES = %w(c cont)
|
@@ -39,45 +39,15 @@ See also 'step', 'next', 'finish', and 'nexti' commands.
|
|
39
39
|
|
40
40
|
## FIXME: DRY this code, tbreak and break.
|
41
41
|
unless args.size == 1
|
42
|
-
|
43
|
-
@proc.breakpoint_position(
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
if name.kind_of?(Rubinius::CompiledMethod)
|
49
|
-
bp = @proc.set_breakpoint_method(describe, name, line, ip,
|
50
|
-
{:temp=>true, :event =>'tbrkpt'})
|
51
|
-
unless bp
|
52
|
-
errmsg "Trouble setting temporary breakpoint"
|
53
|
-
return
|
54
|
-
end
|
42
|
+
cm, line, ip, condition, negate =
|
43
|
+
@proc.breakpoint_position(@proc.cmd_argstr, false)
|
44
|
+
if cm
|
45
|
+
opts={:event => 'tbrkpt', :temp => true}
|
46
|
+
bp = @proc.set_breakpoint_method(cm, line, ip, opts)
|
47
|
+
bp.set_temp!
|
55
48
|
else
|
56
|
-
|
57
|
-
|
58
|
-
klass = @proc.debug_eval(klass_name, settings[:maxstring])
|
59
|
-
rescue NameError
|
60
|
-
errmsg "Unable to find class/module: #{klass_name}"
|
61
|
-
return
|
62
|
-
end
|
63
|
-
|
64
|
-
begin
|
65
|
-
if which == "#"
|
66
|
-
method = klass.instance_method(name)
|
67
|
-
else
|
68
|
-
method = klass.method(name)
|
69
|
-
end
|
70
|
-
rescue NameError
|
71
|
-
errmsg "Unable to find method '#{name}' in #{klass}"
|
72
|
-
return
|
73
|
-
end
|
74
|
-
arg_str = args[1..-1].join(' ')
|
75
|
-
bp = @proc.set_breakpoint_method(arg_str.strip, method, line, nil,
|
76
|
-
{:temp=>true, :event =>'tbrkpt'})
|
77
|
-
unless bp
|
78
|
-
errmsg "Trouble setting temporary breakpoint"
|
79
|
-
return
|
80
|
-
end
|
49
|
+
errmsg "Trouble setting temporary breakpoint"
|
50
|
+
return
|
81
51
|
end
|
82
52
|
end
|
83
53
|
@proc.continue('continue')
|
data/processor/command/eval.rb
CHANGED
@@ -18,17 +18,18 @@ may be used again easily. The name of the global variable is printed
|
|
18
18
|
next to the inspect output of the value.
|
19
19
|
|
20
20
|
If no string is given we run the string from the current source code
|
21
|
-
about to be run. If the command ends ? (via an alias) and no string
|
22
|
-
|
23
|
-
'until' in the string.
|
21
|
+
about to be run. If the command ends ? (via an alias) and no string is
|
22
|
+
given we will also strip off any leading 'if', 'while', 'elseif',
|
23
|
+
'return', 'case', 'unless', or 'until' in the string.
|
24
24
|
|
25
25
|
#{NAME} 1+2 # 3
|
26
26
|
#{NAME} @v
|
27
27
|
#{NAME} # Run current source-code line
|
28
|
-
#{NAME}? # but strips off leading 'if', 'while',
|
28
|
+
#{NAME}? # but strips off leading 'if', 'while', ..
|
29
29
|
# from command
|
30
30
|
|
31
|
-
See also 'set autoeval'
|
31
|
+
See also 'set autoeval'. The command helps one predict future execution.
|
32
|
+
See 'set buffer trace' for showing what may have already been run.
|
32
33
|
HELP
|
33
34
|
|
34
35
|
ALIASES = %w(eval? ev? ev)
|
@@ -40,9 +41,20 @@ See also 'set autoeval'
|
|
40
41
|
def run(args)
|
41
42
|
if args.size == 1
|
42
43
|
text = @proc.current_source_text
|
43
|
-
|
44
|
-
|
45
|
-
|
44
|
+
if '?' == args[0][-1..-1]
|
45
|
+
if text =~ /^\s*(?:if|elsif|unless)\s+/
|
46
|
+
text.gsub!(/^\s*(?:if|elsif|unless)\s+/,'')
|
47
|
+
text.gsub!(/\s+then\s*$/, '')
|
48
|
+
elsif text =~ /^\s*(?:until|while)\s+/
|
49
|
+
text.gsub!(/^\s*(?:until|while)\s+/,'')
|
50
|
+
text.gsub!(/\s+do\s*$/, '')
|
51
|
+
elsif text =~ /^\s*return\s+/
|
52
|
+
text.gsub!(/^\s*return\s+/,'')
|
53
|
+
elsif text =~ /^\s*case\s+/
|
54
|
+
text.gsub!(/^\s*case\s*/,'')
|
55
|
+
end
|
56
|
+
msg "eval: #{text}"
|
57
|
+
end
|
46
58
|
else
|
47
59
|
text = @proc.cmd_argstr
|
48
60
|
end
|
data/processor/command/exit.rb
CHANGED
@@ -46,8 +46,9 @@ See also "kill" and "set confirm".'
|
|
46
46
|
end
|
47
47
|
exitrc = (args.size > 1) ? exitrc = Integer(args[1]) rescue 0 : 0
|
48
48
|
|
49
|
-
# FIXME:
|
50
|
-
@proc.
|
49
|
+
# FIXME: Is this the best/most general way?
|
50
|
+
@proc.finalize
|
51
|
+
@proc.dbgr.intf[-1].finalize
|
51
52
|
|
52
53
|
# No graceful way to stop threads...
|
53
54
|
# A little harsh, but for now let's go with this.
|
File without changes
|
@@ -0,0 +1,48 @@
|
|
1
|
+
overall debugger command syntax
|
2
|
+
|
3
|
+
Command tokenization syntax is very simple-minded.
|
4
|
+
|
5
|
+
If a line starts with #, the command is ignored.
|
6
|
+
If a line starts with !, the line is eval'd.
|
7
|
+
|
8
|
+
If the command you want eval'd uses the Ruby ! initially, add that
|
9
|
+
after the first ! or start the line with a space.
|
10
|
+
|
11
|
+
Commands are split at whereever ;; appears. This process disregards
|
12
|
+
any quotes or other symbols that have meaning in Ruby. The strings
|
13
|
+
after the leading command string are put back on a command queue.
|
14
|
+
|
15
|
+
Within a single command, tokens are then white-space split. Again,
|
16
|
+
this process disregards quotes or symbols that have meaning in Ruby.
|
17
|
+
Some commands like 'eval', 'macro', and 'break' have access to the
|
18
|
+
untokenized string entered and make use of that rather than the
|
19
|
+
tokenized list.
|
20
|
+
|
21
|
+
The leading token is first looked up in the macro table. If it is in
|
22
|
+
the table, the expansion is replaces the current command and possibly
|
23
|
+
other commands pushed onto a command queue. Next, the leading token is
|
24
|
+
looked up in the debugger alias table and the name may be substituted
|
25
|
+
there. Finally, the leading token is looked up in the debugger alias
|
26
|
+
table. If a match is found, the command name and arguments are
|
27
|
+
dispatched to the command object that process the command.
|
28
|
+
|
29
|
+
If the command is not found and "auto eval" is set on, then the
|
30
|
+
command is eval'd in the context that the program is currently stopped
|
31
|
+
at. If "auto eval" is not set on, then we display an error message
|
32
|
+
that the entered string is "undefined".
|
33
|
+
|
34
|
+
If you want irb-like command-processing, it's possible to go into an
|
35
|
+
irb shell with the "irb" command. It is also possible to arrange going
|
36
|
+
into an irb shell every time you enter the debugger.
|
37
|
+
|
38
|
+
Examples:
|
39
|
+
|
40
|
+
# This line does nothing. It is a comment
|
41
|
+
s # by default, this is an alias for the "step" command
|
42
|
+
!s # shows the value of variable step.
|
43
|
+
!!s # Evaluates !s (or "not s"). The first ! is indicates evaluate.
|
44
|
+
info program;; list # Runs two commands "info program" and "list"
|
45
|
+
pr "hi ;;-)" # Syntax error since ;; splits the line and " is not closed.
|
46
|
+
!puts "hi ;;-)" # One way to do the above.
|
47
|
+
|
48
|
+
See also "alias", "irb", "set auto eval", and "set auto irb".
|