ruby-debug 0.9.3 → 0.10.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.
- data/AUTHORS +1 -0
- data/CHANGES +41 -0
- data/ChangeLog +0 -0
- data/README +27 -13
- data/Rakefile +220 -0
- data/bin/rdebug +116 -42
- data/cli/ruby-debug.rb +33 -3
- data/cli/ruby-debug/command.rb +49 -12
- data/cli/ruby-debug/commands/breakpoints.rb +47 -64
- data/cli/ruby-debug/commands/control.rb +41 -13
- data/cli/ruby-debug/commands/display.rb +35 -18
- data/cli/ruby-debug/commands/enable.rb +159 -0
- data/cli/ruby-debug/commands/eval.rb +78 -4
- data/cli/ruby-debug/commands/frame.rb +67 -42
- data/cli/ruby-debug/commands/help.rb +21 -17
- data/cli/ruby-debug/commands/info.rb +210 -0
- data/cli/ruby-debug/commands/irb.rb +9 -1
- data/cli/ruby-debug/commands/list.rb +11 -8
- data/cli/ruby-debug/commands/method.rb +12 -23
- data/cli/ruby-debug/commands/script.rb +14 -9
- data/cli/ruby-debug/commands/settings.rb +174 -39
- data/cli/ruby-debug/commands/show.rb +193 -0
- data/cli/ruby-debug/commands/stepping.rb +15 -10
- data/cli/ruby-debug/commands/threads.rb +55 -56
- data/cli/ruby-debug/commands/variables.rb +27 -27
- data/cli/ruby-debug/helper.rb +134 -0
- data/cli/ruby-debug/interface.rb +46 -15
- data/cli/ruby-debug/processor.rb +156 -25
- data/doc/rdebug.1 +236 -0
- data/runner.sh +7 -0
- data/test/breakpoints.cmd +43 -0
- data/test/breakpoints.right +94 -0
- data/test/display.cmd +18 -0
- data/test/display.right +37 -0
- data/test/frame.cmd +21 -0
- data/test/frame.right +45 -0
- data/test/gcd.rb +18 -0
- data/test/help.cmd +12 -0
- data/test/help.right +4 -0
- data/test/helper.rb +87 -0
- data/test/info-var-bug.rb +45 -0
- data/test/info-var.cmd +23 -0
- data/test/info-var.right +47 -0
- data/test/info.cmd +12 -0
- data/test/info.right +35 -0
- data/test/quit.cmd +9 -0
- data/test/quit.right +22 -0
- data/test/setshow.cmd +44 -0
- data/test/setshow.right +73 -0
- data/test/stepping.cmd +17 -0
- data/test/stepping.right +40 -0
- data/test/tdebug.rb +196 -0
- data/test/test-breakpoints.rb +28 -0
- data/test/test-columnize.rb +46 -0
- data/test/test-display.rb +26 -0
- data/test/test-frame.rb +27 -0
- data/test/test-help.rb +44 -0
- data/test/test-info-var.rb +33 -0
- data/test/test-info.rb +28 -0
- data/test/test-quit.rb +28 -0
- data/test/test-ruby-debug-base.rb +76 -0
- data/test/test-setshow.rb +24 -0
- data/test/test-stepping.rb +26 -0
- metadata +63 -22
@@ -3,28 +3,24 @@ module Debugger
|
|
3
3
|
def var_list(ary, b = get_binding)
|
4
4
|
ary.sort!
|
5
5
|
for v in ary
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
for c in constants
|
20
|
-
print " %s => %s\n", c, mod.const_get(c)
|
6
|
+
begin
|
7
|
+
s = debug_eval(v, b).inspect
|
8
|
+
rescue
|
9
|
+
begin
|
10
|
+
s = debug_eval(v, b).to_s
|
11
|
+
rescue
|
12
|
+
s = "*Error in evaluation*"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
if s.size > self.class.settings[:width]
|
16
|
+
s[self.class.settings[:width]-3 .. -1] = "..."
|
17
|
+
end
|
18
|
+
print "%s = %s\n", v, s
|
21
19
|
end
|
22
20
|
end
|
23
21
|
end
|
24
22
|
|
25
23
|
class VarConstantCommand < Command # :nodoc:
|
26
|
-
include VarFunctions
|
27
|
-
|
28
24
|
def regexp
|
29
25
|
/^\s*v(?:ar)?\s+c(?:onst(?:ant)?)?\s+/
|
30
26
|
end
|
@@ -34,7 +30,13 @@ module Debugger
|
|
34
30
|
unless obj.kind_of? Module
|
35
31
|
print "Should be Class/Module: %s\n", @match.post_match
|
36
32
|
else
|
37
|
-
|
33
|
+
constants = debug_eval("#{@match.post_match}.constants")
|
34
|
+
constants.sort!
|
35
|
+
for c in constants
|
36
|
+
next if c =~ /SCRIPT/
|
37
|
+
value = obj.const_get(c) rescue "ERROR: #{$!}"
|
38
|
+
print " %s => %p\n", c, value
|
39
|
+
end
|
38
40
|
end
|
39
41
|
end
|
40
42
|
|
@@ -52,8 +54,6 @@ module Debugger
|
|
52
54
|
end
|
53
55
|
|
54
56
|
class VarGlobalCommand < Command # :nodoc:
|
55
|
-
include VarFunctions
|
56
|
-
|
57
57
|
def regexp
|
58
58
|
/^\s*v(?:ar)?\s+g(?:lobal)?\s*$/
|
59
59
|
end
|
@@ -76,14 +76,12 @@ module Debugger
|
|
76
76
|
end
|
77
77
|
|
78
78
|
class VarInstanceCommand < Command # :nodoc:
|
79
|
-
include VarFunctions
|
80
|
-
|
81
79
|
def regexp
|
82
|
-
/^\s*v(?:ar)?\s+i(?:nstance)?\s
|
80
|
+
/^\s*v(?:ar)?\s+i(?:nstance)?\s*/
|
83
81
|
end
|
84
82
|
|
85
83
|
def execute
|
86
|
-
obj = debug_eval(@match.post_match)
|
84
|
+
obj = debug_eval(@match.post_match.empty? ? 'self' : @match.post_match)
|
87
85
|
var_list(obj.instance_variables, obj.instance_eval{binding()})
|
88
86
|
end
|
89
87
|
|
@@ -101,14 +99,16 @@ module Debugger
|
|
101
99
|
end
|
102
100
|
|
103
101
|
class VarLocalCommand < Command # :nodoc:
|
104
|
-
include VarFunctions
|
105
|
-
|
106
102
|
def regexp
|
107
103
|
/^\s*v(?:ar)?\s+l(?:ocal)?\s*$/
|
108
104
|
end
|
109
105
|
|
110
106
|
def execute
|
111
|
-
|
107
|
+
locals = @state.context.frame_locals(@state.frame_pos)
|
108
|
+
_self = @state.context.frame_self(@state.frame_pos)
|
109
|
+
locals.keys.sort.each do |name|
|
110
|
+
print " %s => %p\n", name, locals[name]
|
111
|
+
end
|
112
112
|
end
|
113
113
|
|
114
114
|
class << self
|
@@ -0,0 +1,134 @@
|
|
1
|
+
module Debugger
|
2
|
+
|
3
|
+
module ColumnizeFunctions
|
4
|
+
# Display a list of strings as a compact set of columns.
|
5
|
+
#
|
6
|
+
# Each column is only as wide as necessary.
|
7
|
+
# Columns are separated by two spaces (one was not legible enough).
|
8
|
+
# Adapted from the routine of the same name in cmd.py
|
9
|
+
def columnize(list, displaywidth=80)
|
10
|
+
if not list.is_a?(Array)
|
11
|
+
return "Expecting an Array, got #{list.class}\n"
|
12
|
+
end
|
13
|
+
if list.size == 0
|
14
|
+
return "<empty>\n"
|
15
|
+
end
|
16
|
+
nonstrings = []
|
17
|
+
for str in list do
|
18
|
+
nonstrings << str unless str.is_a?(String)
|
19
|
+
end
|
20
|
+
if nonstrings.size > 0
|
21
|
+
return "Nonstrings: %s\n" % nonstrings.map {|non| non.to_s}.join(', ')
|
22
|
+
end
|
23
|
+
if 1 == list.size
|
24
|
+
return "#{list[0]}\n"
|
25
|
+
end
|
26
|
+
# Try every row count from 1 upwards
|
27
|
+
nrows = ncols = 0
|
28
|
+
colwidths = []
|
29
|
+
1.upto(list.size) do
|
30
|
+
colwidths = []
|
31
|
+
nrows += 1
|
32
|
+
ncols = (list.size + nrows-1) / nrows
|
33
|
+
totwidth = -2
|
34
|
+
# Debugger.debugger if nrows > 1
|
35
|
+
0.upto(ncols-1) do |col|
|
36
|
+
colwidth = 0
|
37
|
+
0.upto(nrows-1) do |row|
|
38
|
+
i = row + nrows*col
|
39
|
+
if i >= list.size
|
40
|
+
break
|
41
|
+
end
|
42
|
+
colwidth = [colwidth, list[i].size].max
|
43
|
+
end
|
44
|
+
colwidths << colwidth
|
45
|
+
totwidth += colwidth + 2
|
46
|
+
if totwidth > displaywidth
|
47
|
+
break
|
48
|
+
end
|
49
|
+
end
|
50
|
+
if totwidth <= displaywidth
|
51
|
+
break
|
52
|
+
end
|
53
|
+
end
|
54
|
+
s = ''
|
55
|
+
0.upto(nrows-1) do |row|
|
56
|
+
texts = []
|
57
|
+
0.upto(ncols-1) do |col|
|
58
|
+
i = row + nrows*col
|
59
|
+
if i >= list.size
|
60
|
+
x = ""
|
61
|
+
else
|
62
|
+
x = list[i]
|
63
|
+
end
|
64
|
+
texts << x
|
65
|
+
end
|
66
|
+
while texts and texts[-1] == ''
|
67
|
+
texts = texts[0..-2]
|
68
|
+
end
|
69
|
+
0.upto(texts.size-1) do |col|
|
70
|
+
texts[col] = texts[col].ljust(colwidths[col])
|
71
|
+
end
|
72
|
+
s += "%s\n" % texts.join(" ")
|
73
|
+
end
|
74
|
+
return s
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
module ParseFunctions
|
79
|
+
# Parse 'str' of command 'cmd' as an integer between
|
80
|
+
# min and max. If either min or max is nil, that
|
81
|
+
# value has no bound.
|
82
|
+
def get_int(str, cmd, min=nil, max=nil, default=1)
|
83
|
+
return default unless str
|
84
|
+
begin
|
85
|
+
int = Integer(str)
|
86
|
+
if min and int < min
|
87
|
+
print "%s argument '%s' needs to at least %s.\n" % [cmd, str, min]
|
88
|
+
return nil
|
89
|
+
elsif max and int > max
|
90
|
+
print "%s argument '%s' needs to at most %s.\n" % [cmd, str, max]
|
91
|
+
return nil
|
92
|
+
end
|
93
|
+
return int
|
94
|
+
rescue
|
95
|
+
print "%s argument '%s' needs to be a number.\n" % [cmd, str]
|
96
|
+
return nil
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
# Return true if arg is 'on' or 1 and false arg is 'off' or 0.
|
101
|
+
# Any other value raises RuntimeError.
|
102
|
+
def get_onoff(arg, default=nil, print_error=true)
|
103
|
+
if arg.nil? or arg == ''
|
104
|
+
if default.nil?
|
105
|
+
if print_error
|
106
|
+
print "Expecting 'on', 1, 'off', or 0. Got nothing.\n"
|
107
|
+
raise RuntimeError
|
108
|
+
end
|
109
|
+
return default
|
110
|
+
end
|
111
|
+
end
|
112
|
+
case arg.downcase
|
113
|
+
when '1', 'on'
|
114
|
+
return true
|
115
|
+
when '0', 'off'
|
116
|
+
return false
|
117
|
+
else
|
118
|
+
if print_error
|
119
|
+
print "Expecting 'on', 1, 'off', or 0. Got: %s.\n" % arg.to_s
|
120
|
+
raise RuntimeError
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
# Return 'on' or 'off' for supplied parameter. The parmeter should
|
126
|
+
# be true, false or nil.
|
127
|
+
def show_onoff(bool)
|
128
|
+
if not [TrueClass, FalseClass, NilClass].member?(bool.class)
|
129
|
+
return "??"
|
130
|
+
end
|
131
|
+
return bool ? 'on' : 'off'
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
data/cli/ruby-debug/interface.rb
CHANGED
@@ -1,5 +1,26 @@
|
|
1
1
|
module Debugger
|
2
2
|
class LocalInterface # :nodoc:
|
3
|
+
attr_accessor :histfile
|
4
|
+
attr_accessor :history_save
|
5
|
+
attr_accessor :history_length
|
6
|
+
|
7
|
+
unless defined?(FILE_HISTORY)
|
8
|
+
FILE_HISTORY = ".rdebug_hist"
|
9
|
+
end
|
10
|
+
def initialize()
|
11
|
+
@history_save = true
|
12
|
+
# take gdb's default
|
13
|
+
@history_length = ENV["HISTSIZE"] ? ENV["HISTSIZE"].to_i : 256
|
14
|
+
@histfile = File.join(ENV["HOME"]||ENV["HOMEPATH"]||".",
|
15
|
+
FILE_HISTORY)
|
16
|
+
open(@histfile, 'r') do |file|
|
17
|
+
file.each do |line|
|
18
|
+
line.chomp!
|
19
|
+
Readline::HISTORY << line
|
20
|
+
end
|
21
|
+
end if File.exists?(@histfile)
|
22
|
+
end
|
23
|
+
|
3
24
|
def read_command(prompt)
|
4
25
|
readline(prompt, true)
|
5
26
|
end
|
@@ -20,20 +41,13 @@ module Debugger
|
|
20
41
|
begin
|
21
42
|
require 'readline'
|
22
43
|
class << Debugger
|
23
|
-
FILE_HISTORY = ".rdebug_hist"
|
24
|
-
save_file = File.join(ENV["HOME"]||ENV["HOMEPATH"], FILE_HISTORY)
|
25
|
-
open(save_file, 'r') do |file|
|
26
|
-
file.each do |line|
|
27
|
-
line.chomp!
|
28
|
-
Readline::HISTORY << line
|
29
|
-
end
|
30
|
-
end if File.exists?(save_file)
|
31
|
-
|
32
44
|
define_method(:save_history) do
|
33
|
-
|
34
|
-
|
45
|
+
@histfile ||= File.join(ENV["HOME"]||ENV["HOMEPATH"]||".",
|
46
|
+
FILE_HISTORY)
|
47
|
+
open(@histfile, 'w') do |file|
|
48
|
+
Readline::HISTORY.to_a.last(@history_length).each do |line|
|
35
49
|
file.puts line unless line.strip.empty?
|
36
|
-
end
|
50
|
+
end if @history_save
|
37
51
|
end rescue nil
|
38
52
|
end
|
39
53
|
public :save_history
|
@@ -45,6 +59,8 @@ module Debugger
|
|
45
59
|
end
|
46
60
|
rescue LoadError
|
47
61
|
def readline(prompt, hist)
|
62
|
+
@histfile = ''
|
63
|
+
@hist_save = false
|
48
64
|
STDOUT.print prompt
|
49
65
|
STDOUT.flush
|
50
66
|
line = STDIN.gets
|
@@ -56,8 +72,15 @@ module Debugger
|
|
56
72
|
end
|
57
73
|
|
58
74
|
class RemoteInterface # :nodoc:
|
75
|
+
attr_accessor :histfile
|
76
|
+
attr_accessor :history_save
|
77
|
+
attr_accessor :history_length
|
78
|
+
|
59
79
|
def initialize(socket)
|
60
80
|
@socket = socket
|
81
|
+
@history_save = false
|
82
|
+
@history_length = 256
|
83
|
+
@histfile = ''
|
61
84
|
end
|
62
85
|
|
63
86
|
def read_command(prompt)
|
@@ -88,19 +111,27 @@ module Debugger
|
|
88
111
|
end
|
89
112
|
|
90
113
|
class ScriptInterface # :nodoc:
|
91
|
-
|
114
|
+
attr_accessor :histfile
|
115
|
+
attr_accessor :history_save
|
116
|
+
attr_accessor :history_length
|
117
|
+
def initialize(file, out, verbose=false)
|
92
118
|
@file = file.respond_to?(:gets) ? file : open(file)
|
93
119
|
@out = out
|
120
|
+
@verbose = verbose
|
121
|
+
@history_save = false
|
122
|
+
@history_length = 256 # take gdb default
|
123
|
+
@histfile = ''
|
94
124
|
end
|
95
125
|
|
96
126
|
def read_command(prompt)
|
97
127
|
while result = @file.gets
|
128
|
+
puts "# #{result}" if @verbose
|
98
129
|
next if result =~ /^\s*#/
|
99
130
|
next if result.strip.empty?
|
100
131
|
break
|
101
132
|
end
|
102
133
|
raise IOError unless result
|
103
|
-
result
|
134
|
+
result.chomp!
|
104
135
|
end
|
105
136
|
|
106
137
|
def confirm(prompt)
|
@@ -108,7 +139,7 @@ module Debugger
|
|
108
139
|
end
|
109
140
|
|
110
141
|
def print(*args)
|
111
|
-
@out.
|
142
|
+
@out.printf(*args)
|
112
143
|
end
|
113
144
|
|
114
145
|
def close
|
data/cli/ruby-debug/processor.rb
CHANGED
@@ -2,16 +2,28 @@ require 'ruby-debug/interface'
|
|
2
2
|
require 'ruby-debug/command'
|
3
3
|
|
4
4
|
module Debugger
|
5
|
+
|
6
|
+
annotate = 0
|
7
|
+
|
5
8
|
class CommandProcessor # :nodoc:
|
6
9
|
attr_accessor :interface
|
7
10
|
attr_reader :display
|
8
11
|
|
12
|
+
@@Show_breakpoints_postcmd = ["break", "tbreak", "disable", "enable",
|
13
|
+
"condition", "clear", "delete"]
|
14
|
+
@@Show_annotations_preloop = ["step", "continue", "next", "finish"]
|
15
|
+
@@Show_annotations_postcmd = ["down", "frame", "up"]
|
16
|
+
|
9
17
|
def initialize(interface = LocalInterface.new)
|
10
18
|
@interface = interface
|
11
19
|
@display = []
|
20
|
+
|
12
21
|
@mutex = Mutex.new
|
13
22
|
@last_cmd = nil
|
14
23
|
@actions = []
|
24
|
+
@last_file = nil # Filename the last time we stopped
|
25
|
+
@last_line = nil # line number the last time we stopped
|
26
|
+
@output_annotation_in_progress = false
|
15
27
|
end
|
16
28
|
|
17
29
|
def interface=(interface)
|
@@ -21,6 +33,27 @@ module Debugger
|
|
21
33
|
end
|
22
34
|
end
|
23
35
|
|
36
|
+
require 'pathname' # For cleanpath
|
37
|
+
|
38
|
+
# Regularize file name.
|
39
|
+
# This is also used as a common funnel place if basename is
|
40
|
+
# desired or if we are working remotely and want to change the
|
41
|
+
# basename. Or we are eliding filenames.
|
42
|
+
def self.canonic_file(filename)
|
43
|
+
# For now we want resolved filenames
|
44
|
+
if Command.settings[:basename]
|
45
|
+
File.basename(filename)
|
46
|
+
else
|
47
|
+
# Cache this?
|
48
|
+
Pathname.new(filename).cleanpath.to_s
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.print_location_and_text(file, line)
|
53
|
+
print "#{"\032\032" if ENV['EMACS']}#{canonic_file(file)}:#{line}\n" +
|
54
|
+
"#{Debugger.line_at(file, line)}"
|
55
|
+
end
|
56
|
+
|
24
57
|
def self.protect(mname)
|
25
58
|
alias_method "__#{mname}", mname
|
26
59
|
module_eval %{
|
@@ -39,13 +72,31 @@ module Debugger
|
|
39
72
|
end
|
40
73
|
|
41
74
|
def at_breakpoint(context, breakpoint)
|
75
|
+
if @output_annotation_in_progress
|
76
|
+
print "\032\032\n"
|
77
|
+
@output_annotation_in_progress = false
|
78
|
+
end
|
79
|
+
|
42
80
|
n = Debugger.breakpoints.index(breakpoint) + 1
|
81
|
+
print("\032\032%s:%s\n",
|
82
|
+
CommandProcessor.canonic_file(breakpoint.source),
|
83
|
+
breakpoint.pos) if ENV['EMACS']
|
43
84
|
print "Breakpoint %d at %s:%s\n", n, breakpoint.source, breakpoint.pos
|
44
85
|
end
|
45
86
|
protect :at_breakpoint
|
46
87
|
|
47
88
|
def at_catchpoint(context, excpt)
|
48
|
-
|
89
|
+
if @output_annotation_in_progress
|
90
|
+
print "\032\032\n"
|
91
|
+
@output_annotation_in_progress = false
|
92
|
+
end
|
93
|
+
|
94
|
+
print "\032\032%s:%d\n",
|
95
|
+
CommandProcessor.canonic_file(context.frame_file(1)),
|
96
|
+
context.frame_line(1) if ENV['EMACS']
|
97
|
+
print "Catchpoint at %s:%d: `%s' (%s)\n",
|
98
|
+
CommandProcessor.canonic_file(context.frame_file(1)),
|
99
|
+
context.frame_line(1), excpt, excpt.class
|
49
100
|
fs = context.stack_size
|
50
101
|
tb = caller(0)[-fs..-1]
|
51
102
|
if tb
|
@@ -57,18 +108,37 @@ module Debugger
|
|
57
108
|
protect :at_catchpoint
|
58
109
|
|
59
110
|
def at_tracing(context, file, line)
|
60
|
-
|
111
|
+
if @output_annotation_in_progress
|
112
|
+
print "\032\032\n"
|
113
|
+
@output_annotation_in_progress = false
|
114
|
+
end
|
115
|
+
|
116
|
+
@last_file = CommandProcessor.canonic_file(file)
|
117
|
+
file = CommandProcessor.canonic_file(file)
|
118
|
+
unless file == @last_file and @last_line == line and
|
119
|
+
Command.settings[:tracing_plus]
|
120
|
+
print "Tracing(%d):%s:%s %s",
|
121
|
+
context.thnum, file, line, Debugger.line_at(file, line)
|
122
|
+
@last_file = file
|
123
|
+
@last_line = line
|
124
|
+
end
|
125
|
+
always_run(context, file, line, 2)
|
61
126
|
end
|
62
127
|
protect :at_tracing
|
63
128
|
|
64
129
|
def at_line(context, file, line)
|
65
|
-
print "#{"\032\032" if ENV['EMACS']}%s:%d %s", file, line, Debugger.line_at(file, line)
|
66
130
|
process_commands(context, file, line)
|
67
131
|
end
|
68
132
|
protect :at_line
|
69
133
|
|
70
134
|
private
|
71
|
-
|
135
|
+
|
136
|
+
# Callers of this routine should make sure to use comma to
|
137
|
+
# separate format argments rather than %. Otherwise it seems that
|
138
|
+
# if the string you want to print has format specifier, which
|
139
|
+
# could happen if you are trying to show say a source-code line
|
140
|
+
# with "puts" or "print" in it, this print routine will give an
|
141
|
+
# error saying it is looking for more arguments.
|
72
142
|
def print(*args)
|
73
143
|
@interface.print(*args)
|
74
144
|
end
|
@@ -80,8 +150,10 @@ module Debugger
|
|
80
150
|
"(rdb:%d) " % context.thnum
|
81
151
|
end
|
82
152
|
end
|
83
|
-
|
84
|
-
|
153
|
+
|
154
|
+
# Run these commands, for example display commands or possibly
|
155
|
+
# the list or irb in an "autolist" or "autoirb".
|
156
|
+
def always_run(context, file, line, run_level)
|
85
157
|
event_cmds = Command.commands.select{|cmd| cmd.event }
|
86
158
|
state = State.new do |s|
|
87
159
|
s.context = context
|
@@ -95,7 +167,18 @@ module Debugger
|
|
95
167
|
@interface.state = state if @interface.respond_to?('state=')
|
96
168
|
|
97
169
|
commands = event_cmds.map{|cmd| cmd.new(state) }
|
98
|
-
commands.select{|cmd| cmd.class.always_run }.each{|cmd| cmd.execute }
|
170
|
+
commands.select{|cmd| cmd.class.always_run >= run_level}.each{|cmd| cmd.execute }
|
171
|
+
return state, commands
|
172
|
+
end
|
173
|
+
|
174
|
+
# Handle debugger commands
|
175
|
+
def process_commands(context, file, line)
|
176
|
+
if @output_annotation_in_progress
|
177
|
+
print "\032\032\n"
|
178
|
+
@output_annotation_in_progress = false
|
179
|
+
end
|
180
|
+
|
181
|
+
state, commands = always_run(context, file, line, 1)
|
99
182
|
|
100
183
|
splitter = lambda do |str|
|
101
184
|
str.split(/;/).inject([]) do |m, v|
|
@@ -112,35 +195,83 @@ module Debugger
|
|
112
195
|
m
|
113
196
|
end
|
114
197
|
end
|
115
|
-
|
198
|
+
|
199
|
+
preloop(commands, context)
|
200
|
+
CommandProcessor.print_location_and_text(file, line)
|
116
201
|
while !state.proceed? and input = @interface.read_command(prompt(context))
|
117
202
|
catch(:debug_error) do
|
118
|
-
|
119
203
|
if input == ""
|
120
204
|
next unless @last_cmd
|
121
205
|
input = @last_cmd
|
122
206
|
else
|
123
207
|
@last_cmd = input
|
124
208
|
end
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
if context.dead? && cmd.class.need_context
|
129
|
-
print "Command is unavailable\n"
|
130
|
-
else
|
131
|
-
cmd.execute
|
132
|
-
end
|
133
|
-
else
|
134
|
-
unknown_cmd = commands.find{|cmd| cmd.class.unknown }
|
135
|
-
if unknown_cmd
|
136
|
-
unknown_cmd.execute
|
137
|
-
else
|
138
|
-
print "Unknown command\n"
|
139
|
-
end
|
140
|
-
end
|
209
|
+
splitter[input].each do |cmd|
|
210
|
+
one_cmd(commands, context, cmd)
|
211
|
+
postcmd(commands, context, cmd)
|
141
212
|
end
|
142
213
|
end
|
143
214
|
end
|
215
|
+
|
216
|
+
if Debugger.annotate and Debugger.annotate > 2
|
217
|
+
print "\032\032starting\n"
|
218
|
+
@output_annotation_in_progress = true
|
219
|
+
end
|
220
|
+
end # process_commands
|
221
|
+
|
222
|
+
def one_cmd(commands, context, input)
|
223
|
+
if cmd = commands.find{ |c| c.match(input) }
|
224
|
+
if context.dead? && cmd.class.need_context
|
225
|
+
print "Command is unavailable\n"
|
226
|
+
else
|
227
|
+
cmd.execute
|
228
|
+
end
|
229
|
+
else
|
230
|
+
unknown_cmd = commands.find{|cmd| cmd.class.unknown }
|
231
|
+
if unknown_cmd
|
232
|
+
unknown_cmd.execute
|
233
|
+
else
|
234
|
+
print "Unknown command\n"
|
235
|
+
end
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
def postcmd(commands, context, cmd)
|
240
|
+
if Debugger.annotate and Debugger.annotate > 0
|
241
|
+
# FIXME: need to cannonicalize command names
|
242
|
+
# e.g. b vs. break
|
243
|
+
# and break out the command name "break 10"
|
244
|
+
# until then we'll refresh always
|
245
|
+
# cmd = @last_cmd unless cmd
|
246
|
+
#if @@Show_breakpoints_postcmd.member?(cmd)
|
247
|
+
annotation('breakpoints', commands, context, "info breakpoints") unless
|
248
|
+
Debugger.breakpoints.empty?
|
249
|
+
annotation('display', commands, context, "display")
|
250
|
+
# end
|
251
|
+
# if @@Show_annotations_postcmd.member?(cmd)
|
252
|
+
annotation('stack', commands, context, "where") if
|
253
|
+
context.stack_size > 0
|
254
|
+
annotation('variables', commands, context, "info variables")
|
255
|
+
# end
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
def preloop(commands, context)
|
260
|
+
if Debugger.annotate and Debugger.annotate > 0
|
261
|
+
# if we are here, the stack frames have changed outside the
|
262
|
+
# command loop (e.g. after a "continue" command), so we show
|
263
|
+
# the annotations again
|
264
|
+
annotation('breakpoints', commands, context, "info breakpoints")
|
265
|
+
annotation('stack', commands, context, "where")
|
266
|
+
annotation('variables', commands, context, "info variables")
|
267
|
+
annotation('display', commands, context, "display")
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
def annotation(label, commands, context, cmd)
|
272
|
+
print "\032\032#{label}\n"
|
273
|
+
one_cmd(commands, context, cmd)
|
274
|
+
print "\032\032\n"
|
144
275
|
end
|
145
276
|
|
146
277
|
class State # :nodoc:
|