rb8-trepanning 0.1.5 → 0.1.6
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +18 -4
- data/ChangeLog +100 -87
- data/Makefile +23 -4
- data/README.textile +3 -3
- data/Rakefile +26 -20
- data/app/complete.rb +13 -13
- data/app/default.rb +8 -8
- data/app/display.rb +7 -7
- data/app/frame.rb +8 -8
- data/app/irb.rb +15 -15
- data/app/options.rb +25 -25
- data/app/run.rb +16 -8
- data/app/util.rb +7 -7
- data/bin/trepan8 +2 -2
- data/check-filter.rb +21 -0
- data/interface.rb +4 -4
- data/interface/user.rb +11 -11
- data/io.rb +18 -19
- data/io/input.rb +14 -12
- data/lib/debugger.rb +3 -1
- data/lib/trepanning.rb +30 -28
- data/processor.rb +41 -38
- data/processor/command.rb +9 -9
- data/processor/command/alias.rb +6 -6
- data/processor/command/down.rb +1 -2
- data/processor/command/edit.rb +12 -8
- data/processor/command/eval.rb +7 -7
- data/processor/command/info_subcmd/macro.rb +6 -6
- data/processor/command/info_subcmd/program.rb +5 -1
- data/processor/command/macro.rb +6 -6
- data/processor/command/show_subcmd/abbrev.rb +2 -2
- data/processor/command/up.rb +1 -2
- data/processor/complete.rb +120 -0
- data/processor/default.rb +13 -9
- data/processor/load_cmds.rb +18 -97
- data/processor/location.rb +34 -31
- data/processor/msg.rb +5 -5
- data/processor/validate.rb +44 -35
- data/test/data/break_loop_bug.right +2 -2
- data/test/data/edit.cmd +1 -1
- data/test/data/edit.right +7 -1
- data/test/data/printvar.right +2 -2
- data/test/data/raise.right +0 -1
- data/test/data/trace-mingw.right +28 -0
- data/test/integration/.gitignore +1 -0
- data/test/integration/test-raise.rb +10 -1
- data/test/integration/test-trace.rb +10 -6
- data/test/unit/test-app-options.rb +9 -3
- data/test/unit/test-app-run.rb +8 -1
- data/test/unit/test-cmd-alias.rb +2 -2
- data/test/unit/test-proc-default.rb +34 -0
- metadata +10 -6
data/processor/load_cmds.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
|
-
# Copyright (C) 2010, 2011 Rocky Bernstein <rockyb@rubyforge.net>
|
2
|
+
# Copyright (C) 2010, 2011 Rocky Bernstein <rockyb@rubyforge.net>
|
3
3
|
require 'tmpdir'
|
4
4
|
|
5
5
|
# Part of Trepan::CmdProcess that loads up debugger commands from
|
6
|
-
# builtin and user directories.
|
6
|
+
# builtin and user directories.
|
7
7
|
# Sets @commands, @aliases, @macros
|
8
8
|
require 'rubygems'; require 'require_relative'
|
9
9
|
require_relative '../app/complete'
|
@@ -14,9 +14,9 @@ class Trepan::CmdProcessor < Trepan::VirtualCmdProcessor
|
|
14
14
|
# indexed by alias name
|
15
15
|
attr_reader :commands # Hash[String] of command objects
|
16
16
|
# indexed by name
|
17
|
-
attr_reader :macros # Hash[String] of Proc objects
|
17
|
+
attr_reader :macros # Hash[String] of Proc objects
|
18
18
|
# indexed by macro name.
|
19
|
-
attr_reader :leading_str # leading part of string. Used in
|
19
|
+
attr_reader :leading_str # leading part of string. Used in
|
20
20
|
# command completion
|
21
21
|
|
22
22
|
# "initialize" for multi-file class. Called from main.rb's "initialize".
|
@@ -27,13 +27,13 @@ class Trepan::CmdProcessor < Trepan::VirtualCmdProcessor
|
|
27
27
|
|
28
28
|
cmd_dirs = [ File.join(File.dirname(__FILE__), 'command') ]
|
29
29
|
cmd_dirs << @settings[:user_cmd_dir] if @settings[:user_cmd_dir]
|
30
|
-
cmd_dirs.each do |cmd_dir|
|
30
|
+
cmd_dirs.each do |cmd_dir|
|
31
31
|
load_debugger_commands(cmd_dir) if File.directory?(cmd_dir)
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
35
35
|
# Loads in debugger commands by require'ing each ruby file in the
|
36
|
-
# 'command' directory. Then a new instance of each class of the
|
36
|
+
# 'command' directory. Then a new instance of each class of the
|
37
37
|
# form Trepan::xxCommand is added to @commands and that array
|
38
38
|
# is returned.
|
39
39
|
def load_debugger_commands(file_or_dir)
|
@@ -42,13 +42,13 @@ class Trepan::CmdProcessor < Trepan::VirtualCmdProcessor
|
|
42
42
|
# change $0 so it doesn't get in the way of __FILE__ = $0
|
43
43
|
old_dollar0 = $0
|
44
44
|
$0 = ''
|
45
|
-
Dir.glob(File.join(dir, '*.rb')).each do |rb|
|
45
|
+
Dir.glob(File.join(dir, '*.rb')).each do |rb|
|
46
46
|
# We use require so that multiple calls have no effect.
|
47
47
|
require rb
|
48
48
|
end
|
49
49
|
$0 = old_dollar0
|
50
50
|
elsif File.readable?(file_or_dir)
|
51
|
-
# We use load in case we are reloading.
|
51
|
+
# We use load in case we are reloading.
|
52
52
|
# 'require' would not be effective here
|
53
53
|
load file_or_dir
|
54
54
|
else
|
@@ -61,7 +61,7 @@ class Trepan::CmdProcessor < Trepan::VirtualCmdProcessor
|
|
61
61
|
|
62
62
|
# Add to list of commands and aliases.
|
63
63
|
cmd_name = klass.const_get(:NAME)
|
64
|
-
if klass.constants.member?('ALIASES') ||
|
64
|
+
if klass.constants.member?('ALIASES') ||
|
65
65
|
klass.constants.member?(:ALIASES)
|
66
66
|
aliases= klass.const_get('ALIASES') || klass.const_get(:ALIASES)
|
67
67
|
aliases.each {|a| @aliases[a] = cmd_name}
|
@@ -79,7 +79,7 @@ class Trepan::CmdProcessor < Trepan::VirtualCmdProcessor
|
|
79
79
|
end
|
80
80
|
end
|
81
81
|
|
82
|
-
# Looks up cmd_array[0] in @commands and runs that. We do lots of
|
82
|
+
# Looks up cmd_array[0] in @commands and runs that. We do lots of
|
83
83
|
# validity testing on cmd_array.
|
84
84
|
def run_cmd(cmd_array)
|
85
85
|
unless cmd_array.is_a?(Array)
|
@@ -87,12 +87,12 @@ class Trepan::CmdProcessor < Trepan::VirtualCmdProcessor
|
|
87
87
|
return
|
88
88
|
end
|
89
89
|
if cmd_array.detect{|item| !item.is_a?(String)}
|
90
|
-
errmsg "run_cmd argument Array should only contain strings. " +
|
90
|
+
errmsg "run_cmd argument Array should only contain strings. " +
|
91
91
|
"Got #{cmd_array.inspect}"
|
92
92
|
return
|
93
93
|
end
|
94
94
|
if cmd_array.empty?
|
95
|
-
errmsg "run_cmd Array should have at least one item. " +
|
95
|
+
errmsg "run_cmd Array should have at least one item. " +
|
96
96
|
"Got: #{cmd_array.inspect}"
|
97
97
|
return
|
98
98
|
end
|
@@ -103,7 +103,7 @@ class Trepan::CmdProcessor < Trepan::VirtualCmdProcessor
|
|
103
103
|
end
|
104
104
|
|
105
105
|
def save_commands(opts)
|
106
|
-
save_filename = opts[:filename] ||
|
106
|
+
save_filename = opts[:filename] ||
|
107
107
|
File.join(Dir.tmpdir, "trepanning-save-#{$$}.txt")
|
108
108
|
begin
|
109
109
|
save_file = File.open(save_filename, 'w')
|
@@ -117,16 +117,16 @@ class Trepan::CmdProcessor < Trepan::VirtualCmdProcessor
|
|
117
117
|
cmd_obj.save_command if cmd_obj.respond_to?(:save_command)
|
118
118
|
next unless cmd_obj.is_a?(Trepan::SubcommandMgr)
|
119
119
|
cmd_obj.subcmds.subcmds.each do |subcmd_name, subcmd_obj|
|
120
|
-
save_file.puts subcmd_obj.save_command if
|
120
|
+
save_file.puts subcmd_obj.save_command if
|
121
121
|
subcmd_obj.respond_to?(:save_command)
|
122
122
|
next unless subcmd_obj.is_a?(Trepan::SubSubcommandMgr)
|
123
123
|
subcmd_obj.subcmds.subcmds.each do |subsubcmd_name, subsubcmd_obj|
|
124
|
-
save_file.puts subsubcmd_obj.save_command if
|
124
|
+
save_file.puts subsubcmd_obj.save_command if
|
125
125
|
subsubcmd_obj.respond_to?(:save_command)
|
126
126
|
end
|
127
127
|
end
|
128
128
|
end
|
129
|
-
save_file.puts "!FileUtils.rm #{save_filename.inspect}" if
|
129
|
+
save_file.puts "!FileUtils.rm #{save_filename.inspect}" if
|
130
130
|
opts[:erase]
|
131
131
|
save_file.close
|
132
132
|
|
@@ -140,90 +140,15 @@ class Trepan::CmdProcessor < Trepan::VirtualCmdProcessor
|
|
140
140
|
# command, but I don't know it. And eval works.
|
141
141
|
klass = self.instance_eval("Trepan::Command::#{command}")
|
142
142
|
cmd = klass.send(:new, self)
|
143
|
-
|
143
|
+
|
144
144
|
# Add to list of commands and aliases.
|
145
145
|
cmd_name = klass.const_get(:NAME)
|
146
146
|
if klass.constants.member?(:ALIASES)
|
147
|
-
aliases= klass.const_get(:ALIASES)
|
147
|
+
aliases= klass.const_get(:ALIASES)
|
148
148
|
aliases.each {|a| @aliases[a] = cmd_name}
|
149
149
|
end
|
150
150
|
@commands[cmd_name] = cmd
|
151
151
|
end
|
152
|
-
|
153
|
-
# Handle initial completion. We draw from the commands, aliases,
|
154
|
-
# and macros for completion. However we won't include aliases which
|
155
|
-
# are prefixes of other commands.
|
156
|
-
def complete(str, last_token)
|
157
|
-
@leading_str = str
|
158
|
-
next_blank_pos, token = Trepan::Complete.next_token(str, 0)
|
159
|
-
return [''] if token.empty? && !last_token.empty?
|
160
|
-
match_pairs = Trepan::Complete.complete_token_with_next(@commands,
|
161
|
-
token)
|
162
|
-
match_hash = {}
|
163
|
-
match_pairs.each do |pair|
|
164
|
-
match_hash[pair[0]] = pair[1]
|
165
|
-
end
|
166
|
-
alias_pairs = Trepan::Complete.
|
167
|
-
complete_token_filtered_with_next(@aliases, token, match_hash,
|
168
|
-
@commands)
|
169
|
-
match_pairs += alias_pairs
|
170
|
-
if str[next_blank_pos..-1].empty?
|
171
|
-
return match_pairs.map{|pair| pair[0]}.sort
|
172
|
-
else
|
173
|
-
alias_pairs.each do |pair|
|
174
|
-
match_hash[pair[0]] = pair[1]
|
175
|
-
end
|
176
|
-
end
|
177
|
-
if match_pairs.size > 1
|
178
|
-
# FIXME: figure out what to do here.
|
179
|
-
# Matched multiple items in the middle of the string
|
180
|
-
# We can't handle this so do nothing.
|
181
|
-
return []
|
182
|
-
# return match_pairs.map do |name, cmd|
|
183
|
-
# ["#{name} #{args[1..-1].join(' ')}"]
|
184
|
-
# end
|
185
|
-
end
|
186
|
-
# match_pairs.size == 1
|
187
|
-
next_complete(str, next_blank_pos, match_pairs[0][1], last_token)
|
188
|
-
end
|
189
|
-
|
190
|
-
def next_complete(str, next_blank_pos, cmd, last_token)
|
191
|
-
next_blank_pos, token = Trepan::Complete.next_token(str, next_blank_pos)
|
192
|
-
return [] if token.empty? && !last_token.empty?
|
193
|
-
|
194
|
-
if cmd.respond_to?(:complete_token_with_next)
|
195
|
-
match_pairs = cmd.complete_token_with_next(token)
|
196
|
-
return [] if match_pairs.empty?
|
197
|
-
if str[next_blank_pos..-1].rstrip.empty? &&
|
198
|
-
(token.empty? || token == last_token)
|
199
|
-
return match_pairs.map { |completion, junk| completion }
|
200
|
-
else
|
201
|
-
if match_pairs.size == 1
|
202
|
-
return next_complete(str, next_blank_pos, match_pairs[0][1],
|
203
|
-
last_token)
|
204
|
-
else
|
205
|
-
# FIXME: figure out what to do here.
|
206
|
-
# Matched multiple items in the middle of the string
|
207
|
-
# We can't handle this so do nothing.
|
208
|
-
return []
|
209
|
-
end
|
210
|
-
end
|
211
|
-
elsif cmd.respond_to?(:complete)
|
212
|
-
matches = cmd.complete(token)
|
213
|
-
return [] if matches.empty?
|
214
|
-
if str[next_blank_pos..-1].rstrip.empty? &&
|
215
|
-
(token.empty? || token == last_token)
|
216
|
-
return matches
|
217
|
-
else
|
218
|
-
# FIXME: figure out what to do here.
|
219
|
-
# Matched multiple items in the middle of the string
|
220
|
-
# We can't handle this so do nothing.
|
221
|
-
return []
|
222
|
-
end
|
223
|
-
else
|
224
|
-
return []
|
225
|
-
end
|
226
|
-
end
|
227
152
|
end
|
228
153
|
|
229
154
|
if __FILE__ == $0
|
@@ -251,8 +176,4 @@ if __FILE__ == $0
|
|
251
176
|
cmdproc.run_cmd('foo') # Invalid - not an Array
|
252
177
|
cmdproc.run_cmd([]) # Invalid - empty Array
|
253
178
|
cmdproc.run_cmd(['list', 5]) # Invalid - nonstring arg
|
254
|
-
p cmdproc.complete("d", 'd')
|
255
|
-
require 'ruby-debug'; Debugger.start; debugger
|
256
|
-
p cmdproc.complete("sho d", 'd')
|
257
|
-
p cmdproc.complete('', '')
|
258
179
|
end
|
data/processor/location.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
# Copyright (C) 2010,
|
2
|
-
require 'rubygems';
|
1
|
+
# Copyright (C) 2010-2011, 2013 Rocky Bernstein <rockyb@rubyforge.net>
|
2
|
+
require 'rubygems';
|
3
3
|
begin
|
4
4
|
require 'linecache'
|
5
5
|
rescue LoadError
|
@@ -16,17 +16,20 @@ class Trepan::CmdProcessor < Trepan::VirtualCmdProcessor
|
|
16
16
|
unless defined?(EVENT2ICON)
|
17
17
|
# Event icons used in printing locations.
|
18
18
|
EVENT2ICON = {
|
19
|
-
'
|
19
|
+
'breakpoint' => 'xx',
|
20
20
|
'tbrkpt' => 'x1',
|
21
21
|
'c-call' => 'C>',
|
22
22
|
'c-return' => '<C',
|
23
23
|
'step-call' => '->',
|
24
24
|
'call' => '->',
|
25
|
+
'catchpoint' => '!!',
|
25
26
|
'class' => '::',
|
26
27
|
'coverage' => '[]',
|
27
28
|
'debugger-call' => ':o',
|
28
29
|
'end' => '-|',
|
29
30
|
'line' => '--',
|
31
|
+
'step' => '--',
|
32
|
+
'post-mortem' => ':/',
|
30
33
|
'raise' => '!!',
|
31
34
|
'return' => '<-',
|
32
35
|
'start' => '>>',
|
@@ -35,17 +38,17 @@ class Trepan::CmdProcessor < Trepan::VirtualCmdProcessor
|
|
35
38
|
'unknown' => '?!',
|
36
39
|
'vm' => 'VM',
|
37
40
|
'vm-insn' => '..',
|
38
|
-
}
|
41
|
+
}
|
39
42
|
end
|
40
43
|
|
41
44
|
def canonic_file(filename, resolve=true)
|
42
|
-
# For now we want resolved filenames
|
43
|
-
if @settings[:basename]
|
45
|
+
# For now we want resolved filenames
|
46
|
+
if @settings[:basename]
|
44
47
|
return File.basename(filename)
|
45
48
|
end
|
46
49
|
if resolve
|
47
50
|
filename = LineCache::unmap_file(filename)
|
48
|
-
if !File.exist?(filename)
|
51
|
+
if !File.exist?(filename)
|
49
52
|
if (try_filename = resolve_file_with_dir(filename))
|
50
53
|
filename = try_filename if File.exist?(filename)
|
51
54
|
end
|
@@ -58,10 +61,10 @@ class Trepan::CmdProcessor < Trepan::VirtualCmdProcessor
|
|
58
61
|
def current_source_text
|
59
62
|
LineCache::getline(@frame.file, @frame.line).chomp
|
60
63
|
end
|
61
|
-
|
64
|
+
|
62
65
|
def resolve_file_with_dir(path_suffix)
|
63
66
|
settings[:directory].split(/:/).each do |dir|
|
64
|
-
dir =
|
67
|
+
dir =
|
65
68
|
if '$cwd' == dir
|
66
69
|
Dir.pwd
|
67
70
|
else
|
@@ -73,10 +76,10 @@ class Trepan::CmdProcessor < Trepan::VirtualCmdProcessor
|
|
73
76
|
end
|
74
77
|
nil
|
75
78
|
end
|
76
|
-
|
79
|
+
|
77
80
|
# Get line +line_number+ from file named +filename+. Return "\n"
|
78
81
|
# there was a problem. Leading blanks are stripped off.
|
79
|
-
def line_at(filename, line_number,
|
82
|
+
def line_at(filename, line_number,
|
80
83
|
opts = {
|
81
84
|
:reload_on_change => @settings[:reload],
|
82
85
|
:output => @settings[:highlight]
|
@@ -87,9 +90,9 @@ class Trepan::CmdProcessor < Trepan::VirtualCmdProcessor
|
|
87
90
|
unless line
|
88
91
|
# Try using search directories (set with command "directory")
|
89
92
|
if filename[0..0] != File::SEPARATOR
|
90
|
-
try_filename = resolve_file_with_dir(filename)
|
91
|
-
if try_filename &&
|
92
|
-
line = LineCache::getline(try_filename, line_number, opts)
|
93
|
+
try_filename = resolve_file_with_dir(filename)
|
94
|
+
if try_filename &&
|
95
|
+
line = LineCache::getline(try_filename, line_number, opts)
|
93
96
|
LineCache::remap_file(filename, try_filename)
|
94
97
|
end
|
95
98
|
end
|
@@ -97,16 +100,16 @@ class Trepan::CmdProcessor < Trepan::VirtualCmdProcessor
|
|
97
100
|
return nil unless line
|
98
101
|
return line.lstrip.chomp
|
99
102
|
end
|
100
|
-
|
103
|
+
|
101
104
|
def loc_and_text(opts=
|
102
105
|
{:reload_on_change => @settings[:reload],
|
103
106
|
:output => @settings[:highlight]
|
104
107
|
})
|
105
|
-
|
108
|
+
|
106
109
|
loc = source_location_info
|
107
110
|
line_no = @frame.line
|
108
111
|
filename = @frame.file
|
109
|
-
|
112
|
+
|
110
113
|
# if @frame.eval?
|
111
114
|
# file = LineCache::map_script(static.script)
|
112
115
|
# text = LineCache::getline(static.script, line_no, opts)
|
@@ -120,40 +123,40 @@ class Trepan::CmdProcessor < Trepan::VirtualCmdProcessor
|
|
120
123
|
# end
|
121
124
|
[loc, line_no, text]
|
122
125
|
end
|
123
|
-
|
126
|
+
|
124
127
|
def format_location(event=@event, frame=@frame, frame_index=@frame.index)
|
125
128
|
text = nil
|
126
129
|
ev = if event.nil? || 0 != frame_index
|
127
|
-
' '
|
130
|
+
' '
|
128
131
|
else
|
129
132
|
(EVENT2ICON[event] || event)
|
130
133
|
end
|
131
|
-
|
134
|
+
|
132
135
|
@line_no = frame.line
|
133
136
|
loc, @line_no, text = loc_and_text
|
134
|
-
|
137
|
+
|
135
138
|
"#{ev} (#{loc}"
|
136
139
|
end
|
137
|
-
|
140
|
+
|
138
141
|
# FIXME: Use above format_location routine
|
139
142
|
def print_location
|
140
143
|
text = nil
|
141
144
|
ev = if @event.nil? || 0 != @frame.index
|
142
|
-
' '
|
145
|
+
' '
|
143
146
|
else
|
144
147
|
(EVENT2ICON[@event] || @event)
|
145
148
|
end
|
146
|
-
|
149
|
+
|
147
150
|
@line_no = @frame.line
|
148
151
|
loc, @line_no, text = loc_and_text
|
149
|
-
|
152
|
+
|
150
153
|
msg "#{ev} (#{loc})"
|
151
|
-
|
154
|
+
|
152
155
|
# if %w(return c-return).member?(@core.event)
|
153
156
|
# retval = Trepan::Frame.value_returned(@frame, @core.event)
|
154
|
-
# msg 'R=> %s' % retval.inspect
|
157
|
+
# msg 'R=> %s' % retval.inspect
|
155
158
|
# end
|
156
|
-
|
159
|
+
|
157
160
|
if text && !text.strip.empty?
|
158
161
|
old_maxstring = @settings[:maxstring]
|
159
162
|
@settings[:maxstring] = -1
|
@@ -162,10 +165,10 @@ class Trepan::CmdProcessor < Trepan::VirtualCmdProcessor
|
|
162
165
|
@line_no -= 1
|
163
166
|
end
|
164
167
|
end
|
165
|
-
|
168
|
+
|
166
169
|
def source_location_info
|
167
170
|
filename = @frame.file
|
168
|
-
canonic_filename =
|
171
|
+
canonic_filename =
|
169
172
|
## if @frame.eval?
|
170
173
|
## 'eval ' + safe_repr(@frame.eval_string.gsub("\n", ';').inspect, 20)
|
171
174
|
## else
|
@@ -173,7 +176,7 @@ class Trepan::CmdProcessor < Trepan::VirtualCmdProcessor
|
|
173
176
|
## end
|
174
177
|
loc = "#{canonic_filename}:#{@frame.line}"
|
175
178
|
return loc
|
176
|
-
end
|
179
|
+
end
|
177
180
|
end
|
178
181
|
|
179
182
|
if __FILE__ == $0 && caller.size == 0
|
data/processor/msg.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (C) 2010,
|
1
|
+
# Copyright (C) 2010-2011, 2013 Rocky Bernstein <rockyb@rubyforge.net>
|
2
2
|
# I/O related command processor methods
|
3
3
|
require 'rubygems'; require 'require_relative'
|
4
4
|
require_relative '../app/util'
|
@@ -23,8 +23,8 @@ class Trepan::CmdProcessor < Trepan::VirtualCmdProcessor
|
|
23
23
|
message = safe_rep(message) unless opts[:unlimited]
|
24
24
|
end
|
25
25
|
if @settings[:highlight] && defined?(Term::ANSIColor)
|
26
|
-
message =
|
27
|
-
Term::ANSIColor.italic + message + Term::ANSIColor.reset
|
26
|
+
message =
|
27
|
+
Term::ANSIColor.italic + message + Term::ANSIColor.reset
|
28
28
|
end
|
29
29
|
@intf.errmsg(message)
|
30
30
|
end
|
@@ -65,8 +65,8 @@ class Trepan::CmdProcessor < Trepan::VirtualCmdProcessor
|
|
65
65
|
def section(message, opts={})
|
66
66
|
message = safe_rep(message) unless opts[:unlimited]
|
67
67
|
if @settings[:highlight] && defined?(Term::ANSIColor)
|
68
|
-
message =
|
69
|
-
Term::ANSIColor.bold + message + Term::ANSIColor.reset
|
68
|
+
message =
|
69
|
+
Term::ANSIColor.bold + message + Term::ANSIColor.reset
|
70
70
|
end
|
71
71
|
@intf.msg(message)
|
72
72
|
end
|
data/processor/validate.rb
CHANGED
@@ -1,8 +1,9 @@
|
|
1
|
-
# Copyright (C) 2010,
|
1
|
+
# Copyright (C) 2010-2011, 2013 Rocky Bernstein <rockyb@rubyforge.net>
|
2
2
|
|
3
3
|
# Trepan command input validation routines. A String type is
|
4
4
|
# usually passed in as the argument to validation routines.
|
5
5
|
|
6
|
+
require 'rbconfig'
|
6
7
|
require 'rubygems'
|
7
8
|
require 'require_relative'
|
8
9
|
begin
|
@@ -23,7 +24,7 @@ require_relative 'msg' # for errmsg, msg
|
|
23
24
|
|
24
25
|
module Trepan
|
25
26
|
class CmdProcessor < VirtualCmdProcessor
|
26
|
-
|
27
|
+
|
27
28
|
attr_reader :file_exists_proc # Like File.exists? but checks using
|
28
29
|
# cached files
|
29
30
|
|
@@ -36,7 +37,7 @@ module Trepan
|
|
36
37
|
def confirm(msg, default)
|
37
38
|
@settings[:confirm] ? @intf.confirm(msg, default) : true
|
38
39
|
end
|
39
|
-
|
40
|
+
|
40
41
|
# Like cmdfns.get_an_int(), but if there's a stack frame use that
|
41
42
|
# in evaluation.
|
42
43
|
def get_an_int(arg, opts={})
|
@@ -60,19 +61,19 @@ module Trepan
|
|
60
61
|
end
|
61
62
|
return ret_value
|
62
63
|
end
|
63
|
-
|
64
|
+
|
64
65
|
unless defined?(DEFAULT_GET_INT_OPTS)
|
65
66
|
DEFAULT_GET_INT_OPTS = {
|
66
67
|
:min_value => 0, :default => 1, :cmdname => nil, :max_value => nil}
|
67
68
|
end
|
68
|
-
|
69
|
+
|
69
70
|
# If argument parameter 'arg' is not given, then use what is in
|
70
71
|
# opts[:default]. If String 'arg' evaluates to an integer between
|
71
72
|
# least min_value and at_most, use that. Otherwise report an
|
72
73
|
# error. If there's a stack frame use that for bindings in
|
73
74
|
# evaluation.
|
74
75
|
def get_int(arg, opts={})
|
75
|
-
|
76
|
+
|
76
77
|
return default unless arg
|
77
78
|
opts = DEFAULT_GET_INT_OPTS.merge(opts)
|
78
79
|
val = arg ? get_int_noerr(arg) : opts[:default]
|
@@ -85,7 +86,7 @@ module Trepan
|
|
85
86
|
end
|
86
87
|
return nil
|
87
88
|
end
|
88
|
-
|
89
|
+
|
89
90
|
if val < opts[:min_value]
|
90
91
|
if opts[:cmdname]
|
91
92
|
errmsg(("Command '%s' expects an integer at least" +
|
@@ -110,11 +111,11 @@ module Trepan
|
|
110
111
|
end
|
111
112
|
return val
|
112
113
|
end
|
113
|
-
|
114
|
+
|
114
115
|
def get_int_list(args, opts={})
|
115
116
|
args.map{|arg| get_an_int(arg, opts)}.compact
|
116
117
|
end
|
117
|
-
|
118
|
+
|
118
119
|
# Eval arg and it is an integer return the value. Otherwise
|
119
120
|
# return nil
|
120
121
|
def get_int_noerr(arg)
|
@@ -122,10 +123,10 @@ module Trepan
|
|
122
123
|
val = Integer(eval(arg, b))
|
123
124
|
rescue SyntaxError
|
124
125
|
nil
|
125
|
-
rescue
|
126
|
+
rescue
|
126
127
|
nil
|
127
128
|
end
|
128
|
-
|
129
|
+
|
129
130
|
def get_thread_from_string(id_or_num_str)
|
130
131
|
if id_or_num_str == '.'
|
131
132
|
Thread.current
|
@@ -140,7 +141,7 @@ module Trepan
|
|
140
141
|
end
|
141
142
|
end
|
142
143
|
end
|
143
|
-
|
144
|
+
|
144
145
|
# Parse a breakpoint position. On success return:
|
145
146
|
# - the Method the position is in
|
146
147
|
# - the file name - a Fixnum
|
@@ -155,7 +156,7 @@ module Trepan
|
|
155
156
|
end
|
156
157
|
return [nil] * 5 unless break_cmd_parse
|
157
158
|
tail = [break_cmd_parse.condition, break_cmd_parse.negate]
|
158
|
-
cm, file, line, position_type =
|
159
|
+
cm, file, line, position_type =
|
159
160
|
parse_position(break_cmd_parse.position)
|
160
161
|
if cm or file or line
|
161
162
|
return [cm, file, line, position_type] + tail
|
@@ -163,7 +164,7 @@ module Trepan
|
|
163
164
|
errmsg("Unable to get breakpoint position for #{position_str}")
|
164
165
|
return [nil] * 5
|
165
166
|
end
|
166
|
-
|
167
|
+
|
167
168
|
# Return true if arg is 'on' or 1 and false arg is 'off' or 0.
|
168
169
|
# Any other value is raises TypeError.
|
169
170
|
def get_onoff(arg, default=nil, print_error=true)
|
@@ -179,16 +180,16 @@ module Trepan
|
|
179
180
|
darg = arg.downcase
|
180
181
|
return true if arg == '1' || darg == 'on'
|
181
182
|
return false if arg == '0' || darg =='off'
|
182
|
-
|
183
|
+
|
183
184
|
errmsg("Expecting 'on', 1, 'off', or 0. Got: %s." % arg.to_s) if
|
184
185
|
print_error
|
185
186
|
raise TypeError
|
186
187
|
end
|
187
|
-
|
188
|
+
|
188
189
|
include Trepan::CmdParser
|
189
|
-
|
190
|
+
|
190
191
|
def get_method(meth)
|
191
|
-
start_binding =
|
192
|
+
start_binding =
|
192
193
|
begin
|
193
194
|
@frame.binding
|
194
195
|
rescue
|
@@ -205,13 +206,13 @@ module Trepan
|
|
205
206
|
end
|
206
207
|
end
|
207
208
|
end
|
208
|
-
|
209
|
-
# FIXME: this is a ? method but we return
|
210
|
-
# the method value.
|
209
|
+
|
210
|
+
# FIXME: this is a ? method but we return
|
211
|
+
# the method value.
|
211
212
|
def method?(meth)
|
212
213
|
get_method(meth)
|
213
214
|
end
|
214
|
-
|
215
|
+
|
215
216
|
# parse_position(self)->(meth, filename, offset, offset_type)
|
216
217
|
# See app/cmd_parser.kpeg for the syntax of a position which
|
217
218
|
# should include things like:
|
@@ -219,6 +220,14 @@ module Trepan
|
|
219
220
|
# Make sure it works for C:\foo\bar.py:12
|
220
221
|
def parse_position(info)
|
221
222
|
info = parse_location(info) if info.kind_of?(String)
|
223
|
+
## FIXME: push into parse
|
224
|
+
if RbConfig::CONFIG['target_os'].start_with?('mingw') and
|
225
|
+
info =~ /^[A-Za-z]:/
|
226
|
+
drive_letter = info[0..1]
|
227
|
+
info = info[2..-1]
|
228
|
+
else
|
229
|
+
drive_leter = nil
|
230
|
+
end
|
222
231
|
case info.container_type
|
223
232
|
when :fn
|
224
233
|
unless info.container
|
@@ -227,7 +236,7 @@ module Trepan
|
|
227
236
|
end
|
228
237
|
if cm = method?(info.container)
|
229
238
|
## Add bogus - canonic_file: active-path
|
230
|
-
return [cm, 'bogus', info.position,
|
239
|
+
return [cm, 'bogus', info.position,
|
231
240
|
info.position_type]
|
232
241
|
else
|
233
242
|
return [nil] * 4
|
@@ -235,13 +244,13 @@ module Trepan
|
|
235
244
|
when :file
|
236
245
|
## filename = canonic_file(info.container)
|
237
246
|
filename = info.container
|
238
|
-
# cm =
|
239
|
-
# if canonic_file(@frame.file) == filename
|
247
|
+
# cm =
|
248
|
+
# if canonic_file(@frame.file) == filename
|
240
249
|
# cm = @frame.method
|
241
250
|
# if :line == info.position_type
|
242
251
|
# find_method_with_line(cm, info.position)
|
243
252
|
# end
|
244
|
-
# else
|
253
|
+
# else
|
245
254
|
# LineCache.compiled_method(filename)
|
246
255
|
# end
|
247
256
|
return nil, filename, info.position, info.position_type
|
@@ -265,9 +274,9 @@ module Trepan
|
|
265
274
|
return [nil] * 4
|
266
275
|
end
|
267
276
|
end
|
268
|
-
|
277
|
+
|
269
278
|
def parse_method(meth_str)
|
270
|
-
begin
|
279
|
+
begin
|
271
280
|
meth_for_string(meth_str, @frame.binding)
|
272
281
|
rescue NameError
|
273
282
|
nil
|
@@ -275,7 +284,7 @@ module Trepan
|
|
275
284
|
nil
|
276
285
|
end
|
277
286
|
end
|
278
|
-
|
287
|
+
|
279
288
|
def validate_initialize
|
280
289
|
## top_srcdir = File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
281
290
|
## @dbgr_script_iseqs, @dbgr_iseqs = filter_scripts(top_srcdir)
|
@@ -296,15 +305,15 @@ if __FILE__ == $0
|
|
296
305
|
# FIXME have to pull in main for its initalize routine
|
297
306
|
DIRNAME = File.dirname(__FILE__)
|
298
307
|
load File.join(DIRNAME, 'main.rb')
|
299
|
-
|
308
|
+
|
300
309
|
require_relative 'mock'
|
301
310
|
dbgr, cmd = MockDebugger::setup('exit', false)
|
302
311
|
cmdproc = cmd.proc
|
303
312
|
onoff = %w(1 0 on off)
|
304
313
|
onoff.each { |val| puts "onoff(#{val}) = #{cmdproc.get_onoff(val)}" }
|
305
314
|
cmdproc.frame.instance_variable_set('@binding', binding)
|
306
|
-
%w(1 1E bad 1+1 -5).each do |val|
|
307
|
-
puts "get_int_noerr(#{val}) = #{cmdproc.get_int_noerr(val).inspect}"
|
315
|
+
%w(1 1E bad 1+1 -5).each do |val|
|
316
|
+
puts "get_int_noerr(#{val}) = #{cmdproc.get_int_noerr(val).inspect}"
|
308
317
|
end
|
309
318
|
def foo; 5 end
|
310
319
|
def cmdproc.errmsg(msg)
|
@@ -322,7 +331,7 @@ if __FILE__ == $0
|
|
322
331
|
|
323
332
|
puts "To be continued...."
|
324
333
|
exit
|
325
|
-
|
334
|
+
|
326
335
|
cmdproc.method?('cmdproc.errmsg')
|
327
336
|
puts '=' * 40
|
328
337
|
['Array.map', 'Trepan::CmdProcessor.new',
|
@@ -330,11 +339,11 @@ if __FILE__ == $0
|
|
330
339
|
puts "#{str} should be true: #{cmdproc.method?(str).inspect}"
|
331
340
|
end
|
332
341
|
puts '=' * 40
|
333
|
-
|
342
|
+
|
334
343
|
# FIXME:
|
335
344
|
# Array#foo should be false: true
|
336
345
|
# Trepan::CmdProcessor.allocate should be false: true
|
337
|
-
|
346
|
+
|
338
347
|
['food', '.errmsg'].each do |str|
|
339
348
|
puts "#{str} should be false: #{cmdproc.method?(str).inspect}"
|
340
349
|
end
|