ruby-debug 0.9.3 → 0.10.0
Sign up to get free protection for your applications and to get access to all the features.
- 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:
|