trepanning 0.1.6 → 1.93.32
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/COPYING +57 -0
- data/ChangeLog +585 -736
- data/NEWS +26 -12
- data/README.md +62 -0
- data/Rakefile +15 -9
- data/app/breakpoint.rb +11 -12
- data/app/complete.rb +14 -14
- data/app/core.rb +34 -30
- data/app/default.rb +8 -7
- data/app/markdown.rb +191 -0
- data/app/options.rb +104 -99
- data/app/run.rb +9 -1
- data/app/util.rb +7 -7
- data/bin/trepan +7 -7
- data/interface.rb +0 -4
- data/interface/user.rb +11 -11
- data/io/input.rb +13 -13
- data/lib/trepanning.rb +30 -29
- data/processor.rb +40 -40
- data/processor/command.rb +13 -9
- data/processor/command/alias.rb +21 -15
- data/processor/command/backtrace.rb +27 -19
- data/processor/command/break.rb +24 -21
- data/processor/command/complete.rb +5 -2
- data/processor/command/condition.rb +14 -9
- data/processor/command/debug.rb +8 -8
- data/processor/command/down.rb +6 -6
- data/processor/command/edit.rb +4 -0
- data/processor/command/eval.rb +2 -2
- data/processor/command/exit.rb +12 -9
- data/processor/command/finish.rb +25 -23
- data/processor/command/frame.rb +30 -26
- data/processor/command/help.rb +203 -185
- data/processor/command/help/{command.txt → command.md} +21 -18
- data/processor/command/help/examples.md +20 -0
- data/processor/command/help/filename.md +46 -0
- data/processor/command/help/location.md +34 -0
- data/processor/command/help/suffixes.md +19 -0
- data/processor/command/info.rb +6 -4
- data/processor/command/info_subcmd/breakpoints.rb +13 -13
- data/processor/command/info_subcmd/files.rb +35 -31
- data/processor/command/info_subcmd/frame.rb +82 -33
- data/processor/command/info_subcmd/macro.rb +1 -1
- data/processor/command/info_subcmd/program.rb +8 -5
- data/processor/command/info_subcmd/registers.rb +15 -13
- data/processor/command/kill.rb +23 -17
- data/processor/command/list.rb +63 -56
- data/processor/command/macro.rb +45 -28
- data/processor/command/next.rb +29 -23
- data/processor/command/pp.rb +11 -9
- data/processor/command/pr.rb +10 -8
- data/processor/command/ps.rb +5 -5
- data/processor/command/quit.rb +24 -17
- data/processor/command/raise.rb +6 -6
- data/processor/command/reload.rb +9 -2
- data/processor/command/reload_subcmd/command.rb +4 -4
- data/processor/command/restart.rb +9 -4
- data/processor/command/save.rb +9 -9
- data/processor/command/server.rb +18 -17
- data/processor/command/set.rb +8 -6
- data/processor/command/set_subcmd/confirm.rb +15 -2
- data/processor/command/set_subcmd/different.rb +7 -5
- data/processor/command/set_subcmd/highlight.rb +14 -3
- data/processor/command/set_subcmd/pc.rb +62 -0
- data/processor/command/set_subcmd/sp.rb +8 -2
- data/processor/command/shell.rb +25 -23
- data/processor/command/show.rb +9 -7
- data/processor/command/show_subcmd/confirm.rb +12 -1
- data/processor/command/show_subcmd/highlight.rb +13 -3
- data/processor/command/source.rb +27 -26
- data/processor/command/step.rb +52 -43
- data/processor/command/tbreak.rb +9 -4
- data/processor/command/unalias.rb +9 -7
- data/processor/command/undisplay.rb +11 -7
- data/processor/command/up.rb +18 -13
- data/processor/command/watchg.rb +20 -17
- data/processor/complete.rb +120 -0
- data/processor/default.rb +47 -43
- data/processor/list.rb +23 -6
- data/processor/load_cmds.rb +25 -105
- data/processor/location.rb +104 -96
- data/processor/mock.rb +12 -12
- data/processor/msg.rb +61 -52
- data/processor/validate.rb +36 -27
- data/test/data/fname-with-blank.right +0 -1
- data/test/data/trace-mingw.right +28 -0
- data/test/data/trace.right +0 -2
- data/test/functional/test-raise.rb +3 -0
- data/test/integration/helper.rb +16 -16
- data/test/integration/test-debugger-stop.rb +8 -2
- data/test/integration/test-quit.rb +16 -15
- data/test/integration/test-trace.rb +19 -10
- data/test/unit/cmd-helper.rb +4 -1
- data/test/unit/test-app-complete.rb +3 -1
- data/test/unit/test-app-options.rb +7 -1
- data/test/unit/test-app-run.rb +9 -1
- data/test/unit/test-cmd-alias.rb +1 -1
- data/test/unit/test-cmd-edit.rb +2 -0
- data/test/unit/test-cmd-help.rb +10 -5
- data/test/unit/test-cmd-parse_list_cmd.rb +3 -3
- data/test/unit/test-completion.rb +2 -2
- data/test/unit/test-proc-default.rb +34 -0
- data/trepanning.gemspec +15 -14
- metadata +70 -44
- data/README.textile +0 -50
- data/processor/command/help/examples.txt +0 -16
- data/processor/command/help/filename.txt +0 -40
- data/processor/command/help/location.txt +0 -37
- data/processor/command/help/suffixes.txt +0 -17
- data/processor/command/info_subcmd/registers_subcmd/dfp.rb +0 -28
- data/processor/command/info_subcmd/registers_subcmd/lfp.rb +0 -47
- data/processor/command/nocache.rb +0 -32
- data/processor/command/parsetree.rb +0 -56
data/processor/default.rb
CHANGED
@@ -1,50 +1,54 @@
|
|
1
|
-
# Copyright (C) 2010,
|
1
|
+
# Copyright (C) 2010-2011, 2013 Rocky Bernstein <rockyb@rubyforge.net>
|
2
2
|
require_relative '../app/default'
|
3
3
|
require_relative 'virtual'
|
4
4
|
class Trepan::CmdProcessor < Trepan::VirtualCmdProcessor
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
6
|
+
computed_displaywidth = (ENV['COLUMNS'] || `tput cols &2>/dev/null`).to_i rescue 80
|
7
|
+
computed_displaywidth = 80 unless computed_displaywidth >= 10
|
8
|
+
|
9
|
+
|
10
|
+
DEFAULT_SETTINGS = {
|
11
|
+
:abbrev => true, # Allow abbreviations of debugger commands?
|
12
|
+
:autoeval => true, # Ruby eval non-debugger commands
|
13
|
+
:autoirb => false, # Go into IRB in debugger command loop
|
14
|
+
:autolist => false, # Run 'list'
|
15
|
+
|
16
|
+
:basename => false, # Show basename of filenames only
|
17
|
+
:confirm => true, # Confirm potentially dangerous operations?
|
18
|
+
:different => 'on', # stop *only* when different position?
|
19
|
+
|
20
|
+
:debugdbgr => false, # Debugging the debugger
|
21
|
+
:debugexcept => true, # Internal debugging of command exceptions
|
22
|
+
:debugmacro => false, # debugging macros
|
23
|
+
:debugskip => false, # Internal debugging of step/next skipping
|
24
|
+
:directory => # last-resort path-search for files
|
25
|
+
'$cdir:$cwd', # that are not fully qualified.
|
26
|
+
|
27
|
+
:hidestack => nil, # Fixnum. How many hidden outer
|
28
|
+
# debugger stack frames to hide?
|
29
|
+
# nil or -1 means compute value. 0
|
30
|
+
# means hide none. Less than 0 means show
|
31
|
+
# all stack entries.
|
32
|
+
:highlight => true, # Use terminal highlight?
|
33
|
+
|
34
|
+
:maxlist => 10, # Number of source lines to list
|
35
|
+
:maxstack => 10, # backtrace limit
|
36
|
+
:maxstring => 150, # Strings which are larger than this
|
37
|
+
# will be truncated to this length when
|
38
|
+
# printed
|
39
|
+
:maxwidth => computed_displaywidth,
|
40
|
+
:prompt => 'trepan', # core part of prompt. Additional info like
|
41
|
+
# debug nesting and
|
42
|
+
:reload => false, # Reread source file if we determine
|
43
|
+
# it has changed?
|
44
|
+
:save_cmdfile => nil, # If set, debugger command file to be
|
45
|
+
# used on restart
|
46
|
+
:timer => false, # show elapsed time between events
|
47
|
+
:traceprint => false, # event tracing printing
|
48
|
+
:tracebuffer => false, # save events to a trace buffer.
|
49
|
+
:user_cmd_dir => File.join(%W(#{Trepan::HOME_DIR} trepan command)),
|
50
|
+
# User command directory
|
51
|
+
} unless defined?(DEFAULT_SETTINGS)
|
48
52
|
end
|
49
53
|
|
50
54
|
if __FILE__ == $0
|
data/processor/list.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
|
-
# Copyright (C) 2011 Rocky Bernstein <rockyb@rubyforge.net>
|
1
|
+
# Copyright (C) 2011, 2013 Rocky Bernstein <rockyb@rubyforge.net>
|
2
2
|
|
3
3
|
# Trepan command list validation routines. A String type is
|
4
4
|
# usually passed in as the argument to validation routines.
|
5
5
|
|
6
6
|
require 'rubygems'
|
7
|
-
|
7
|
+
require 'rbconfig'
|
8
8
|
require_relative './validate'
|
9
9
|
|
10
10
|
class Trepan
|
@@ -24,9 +24,14 @@ class Trepan
|
|
24
24
|
# See also duplicate code in print_location
|
25
25
|
if container[0] != 'file'
|
26
26
|
try_container = container
|
27
|
-
|
28
|
-
|
29
|
-
|
27
|
+
begin
|
28
|
+
while try_container[0] != 'file' && frame.prev do
|
29
|
+
frame = frame.prev
|
30
|
+
last unless frame
|
31
|
+
try_container = frame_container(frame, false)
|
32
|
+
end
|
33
|
+
rescue
|
34
|
+
return nil
|
30
35
|
end
|
31
36
|
container = try_container if try_container[0] == 'file'
|
32
37
|
end
|
@@ -44,6 +49,14 @@ class Trepan
|
|
44
49
|
filename = frame_filename
|
45
50
|
first = [1, frame_line - center_correction].max
|
46
51
|
else
|
52
|
+
## FIXME: push into parse
|
53
|
+
if RbConfig::CONFIG['target_os'].start_with?('mingw') and
|
54
|
+
position_str =~ /^[A-Za-z]:/
|
55
|
+
drive_letter = position_str[0..1]
|
56
|
+
position_str = position_str[2..-1]
|
57
|
+
else
|
58
|
+
drive_leter = nil
|
59
|
+
end
|
47
60
|
list_cmd_parse = parse_list(position_str,
|
48
61
|
:file_exists_proc => file_exists_proc)
|
49
62
|
return [nil] * 4 unless list_cmd_parse
|
@@ -95,7 +108,11 @@ class Trepan
|
|
95
108
|
first = [1, first - center_correction].max
|
96
109
|
last = first + listsize - 1 unless last
|
97
110
|
end
|
98
|
-
|
111
|
+
if filename
|
112
|
+
LineCache::cache(filename) unless LineCache::cached?(filename)
|
113
|
+
else
|
114
|
+
errmsg("Don't have a filename here")
|
115
|
+
end
|
99
116
|
return [iseq, filename, first, last]
|
100
117
|
end
|
101
118
|
|
data/processor/load_cmds.rb
CHANGED
@@ -1,11 +1,10 @@
|
|
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
|
-
require_relative '../app/complete'
|
9
8
|
require_relative 'virtual'
|
10
9
|
class Trepan::CmdProcessor < Trepan::VirtualCmdProcessor
|
11
10
|
|
@@ -13,11 +12,8 @@ class Trepan::CmdProcessor < Trepan::VirtualCmdProcessor
|
|
13
12
|
# indexed by alias name
|
14
13
|
attr_reader :commands # Hash[String] of command objects
|
15
14
|
# indexed by name
|
16
|
-
attr_reader :macros # Hash[String] of Proc objects
|
15
|
+
attr_reader :macros # Hash[String] of Proc objects
|
17
16
|
# indexed by macro name.
|
18
|
-
attr_reader :leading_str # leading part of string. Used in
|
19
|
-
# command completion
|
20
|
-
|
21
17
|
# "initialize" for multi-file class. Called from main.rb's "initialize".
|
22
18
|
def load_cmds_initialize
|
23
19
|
@commands = {}
|
@@ -26,13 +22,13 @@ class Trepan::CmdProcessor < Trepan::VirtualCmdProcessor
|
|
26
22
|
|
27
23
|
cmd_dirs = [ File.join(File.dirname(__FILE__), 'command') ]
|
28
24
|
cmd_dirs << @settings[:user_cmd_dir] if @settings[:user_cmd_dir]
|
29
|
-
cmd_dirs.each do |cmd_dir|
|
25
|
+
cmd_dirs.each do |cmd_dir|
|
30
26
|
load_debugger_commands(cmd_dir) if File.directory?(cmd_dir)
|
31
27
|
end
|
32
28
|
end
|
33
29
|
|
34
30
|
# Loads in debugger commands by require'ing each ruby file in the
|
35
|
-
# 'command' directory. Then a new instance of each class of the
|
31
|
+
# 'command' directory. Then a new instance of each class of the
|
36
32
|
# form Trepan::xxCommand is added to @commands and that array
|
37
33
|
# is returned.
|
38
34
|
def load_debugger_commands(file_or_dir)
|
@@ -41,13 +37,13 @@ class Trepan::CmdProcessor < Trepan::VirtualCmdProcessor
|
|
41
37
|
# change $0 so it doesn't get in the way of __FILE__ = $0
|
42
38
|
old_dollar0 = $0
|
43
39
|
$0 = ''
|
44
|
-
Dir.glob(File.join(dir, '*.rb')).each do |rb|
|
40
|
+
Dir.glob(File.join(dir, '*.rb')).each do |rb|
|
45
41
|
# We use require so that multiple calls have no effect.
|
46
42
|
require rb
|
47
43
|
end
|
48
44
|
$0 = old_dollar0
|
49
45
|
elsif File.readable?(file_or_dir)
|
50
|
-
# We use load in case we are reloading.
|
46
|
+
# We use load in case we are reloading.
|
51
47
|
# 'require' would not be effective here
|
52
48
|
load file_or_dir
|
53
49
|
else
|
@@ -68,7 +64,7 @@ class Trepan::CmdProcessor < Trepan::VirtualCmdProcessor
|
|
68
64
|
end
|
69
65
|
end
|
70
66
|
|
71
|
-
# Looks up cmd_array[0] in @commands and runs that. We do lots of
|
67
|
+
# Looks up cmd_array[0] in @commands and runs that. We do lots of
|
72
68
|
# validity testing on cmd_array.
|
73
69
|
def run_cmd(cmd_array)
|
74
70
|
unless cmd_array.is_a?(Array)
|
@@ -76,12 +72,12 @@ class Trepan::CmdProcessor < Trepan::VirtualCmdProcessor
|
|
76
72
|
return
|
77
73
|
end
|
78
74
|
if cmd_array.detect{|item| !item.is_a?(String)}
|
79
|
-
errmsg "run_cmd argument Array should only contain strings. " +
|
75
|
+
errmsg "run_cmd argument Array should only contain strings. " +
|
80
76
|
"Got #{cmd_array.inspect}"
|
81
77
|
return
|
82
78
|
end
|
83
79
|
if cmd_array.empty?
|
84
|
-
errmsg "run_cmd Array should have at least one item. " +
|
80
|
+
errmsg "run_cmd Array should have at least one item. " +
|
85
81
|
"Got: #{cmd_array.inspect}"
|
86
82
|
return
|
87
83
|
end
|
@@ -92,7 +88,7 @@ class Trepan::CmdProcessor < Trepan::VirtualCmdProcessor
|
|
92
88
|
end
|
93
89
|
|
94
90
|
def save_commands(opts)
|
95
|
-
save_filename = opts[:filename] ||
|
91
|
+
save_filename = opts[:filename] ||
|
96
92
|
File.join(Dir.tmpdir, Dir::Tmpname.make_tmpname(['trepanning-save', '.txt'], nil))
|
97
93
|
begin
|
98
94
|
save_file = File.open(save_filename, 'w')
|
@@ -106,16 +102,16 @@ class Trepan::CmdProcessor < Trepan::VirtualCmdProcessor
|
|
106
102
|
cmd_obj.save_command if cmd_obj.respond_to?(:save_command)
|
107
103
|
next unless cmd_obj.is_a?(Trepan::SubcommandMgr)
|
108
104
|
cmd_obj.subcmds.subcmds.each do |subcmd_name, subcmd_obj|
|
109
|
-
save_file.puts subcmd_obj.save_command if
|
105
|
+
save_file.puts subcmd_obj.save_command if
|
110
106
|
subcmd_obj.respond_to?(:save_command)
|
111
107
|
next unless subcmd_obj.is_a?(Trepan::SubSubcommandMgr)
|
112
108
|
subcmd_obj.subcmds.subcmds.each do |subsubcmd_name, subsubcmd_obj|
|
113
|
-
save_file.puts subsubcmd_obj.save_command if
|
109
|
+
save_file.puts subsubcmd_obj.save_command if
|
114
110
|
subsubcmd_obj.respond_to?(:save_command)
|
115
111
|
end
|
116
112
|
end
|
117
113
|
end
|
118
|
-
save_file.puts "!FileUtils.rm #{save_filename.inspect}" if
|
114
|
+
save_file.puts "!FileUtils.rm #{save_filename.inspect}" if
|
119
115
|
opts[:erase]
|
120
116
|
save_file.close
|
121
117
|
|
@@ -129,90 +125,16 @@ class Trepan::CmdProcessor < Trepan::VirtualCmdProcessor
|
|
129
125
|
# command, but I don't know it. And eval works.
|
130
126
|
klass = self.instance_eval("Trepan::Command::#{command}")
|
131
127
|
cmd = klass.send(:new, self)
|
132
|
-
|
128
|
+
|
133
129
|
# Add to list of commands and aliases.
|
134
130
|
cmd_name = klass.const_get(:NAME)
|
135
131
|
if klass.constants.member?(:ALIASES)
|
136
|
-
aliases= klass.const_get(:ALIASES)
|
132
|
+
aliases= klass.const_get(:ALIASES)
|
137
133
|
aliases.each {|a| @aliases[a] = cmd_name}
|
138
134
|
end
|
139
135
|
@commands[cmd_name] = cmd
|
140
136
|
end
|
141
137
|
|
142
|
-
# Handle initial completion. We draw from the commands, aliases,
|
143
|
-
# and macros for completion. However we won't include aliases which
|
144
|
-
# are prefixes of other commands.
|
145
|
-
def complete(str, last_token)
|
146
|
-
@leading_str = str
|
147
|
-
next_blank_pos, token = Trepan::Complete.next_token(str, 0)
|
148
|
-
return [''] if token.empty? && !last_token.empty?
|
149
|
-
match_pairs = Trepan::Complete.complete_token_with_next(@commands,
|
150
|
-
token)
|
151
|
-
match_hash = {}
|
152
|
-
match_pairs.each do |pair|
|
153
|
-
match_hash[pair[0]] = pair[1]
|
154
|
-
end
|
155
|
-
alias_pairs = Trepan::Complete.
|
156
|
-
complete_token_filtered_with_next(@aliases, token, match_hash,
|
157
|
-
@commands)
|
158
|
-
match_pairs += alias_pairs
|
159
|
-
if str[next_blank_pos..-1].empty?
|
160
|
-
return match_pairs.map{|pair| pair[0]}.sort
|
161
|
-
else
|
162
|
-
alias_pairs.each do |pair|
|
163
|
-
match_hash[pair[0]] = pair[1]
|
164
|
-
end
|
165
|
-
end
|
166
|
-
if match_pairs.size > 1
|
167
|
-
# FIXME: figure out what to do here.
|
168
|
-
# Matched multiple items in the middle of the string
|
169
|
-
# We can't handle this so do nothing.
|
170
|
-
return []
|
171
|
-
# return match_pairs.map do |name, cmd|
|
172
|
-
# ["#{name} #{args[1..-1].join(' ')}"]
|
173
|
-
# end
|
174
|
-
end
|
175
|
-
# match_pairs.size == 1
|
176
|
-
next_complete(str, next_blank_pos, match_pairs[0][1], last_token)
|
177
|
-
end
|
178
|
-
|
179
|
-
def next_complete(str, next_blank_pos, cmd, last_token)
|
180
|
-
next_blank_pos, token = Trepan::Complete.next_token(str, next_blank_pos)
|
181
|
-
return [] if token.empty? && !last_token.empty?
|
182
|
-
|
183
|
-
if cmd.respond_to?(:complete_token_with_next)
|
184
|
-
match_pairs = cmd.complete_token_with_next(token)
|
185
|
-
return [] if match_pairs.empty?
|
186
|
-
if str[next_blank_pos..-1].rstrip.empty? &&
|
187
|
-
(token.empty? || token == last_token)
|
188
|
-
return match_pairs.map { |completion, junk| completion }
|
189
|
-
else
|
190
|
-
if match_pairs.size == 1
|
191
|
-
return next_complete(str, next_blank_pos, match_pairs[0][1],
|
192
|
-
last_token)
|
193
|
-
else
|
194
|
-
# FIXME: figure out what to do here.
|
195
|
-
# Matched multiple items in the middle of the string
|
196
|
-
# We can't handle this so do nothing.
|
197
|
-
return []
|
198
|
-
end
|
199
|
-
end
|
200
|
-
elsif cmd.respond_to?(:complete)
|
201
|
-
matches = cmd.complete(token)
|
202
|
-
return [] if matches.empty?
|
203
|
-
if str[next_blank_pos..-1].rstrip.empty? &&
|
204
|
-
(token.empty? || token == last_token)
|
205
|
-
return matches
|
206
|
-
else
|
207
|
-
# FIXME: figure out what to do here.
|
208
|
-
# Matched multiple items in the middle of the string
|
209
|
-
# We can't handle this so do nothing.
|
210
|
-
return []
|
211
|
-
end
|
212
|
-
else
|
213
|
-
return []
|
214
|
-
end
|
215
|
-
end
|
216
138
|
end
|
217
139
|
|
218
140
|
if __FILE__ == $0
|
@@ -222,14 +144,6 @@ if __FILE__ == $0
|
|
222
144
|
end
|
223
145
|
|
224
146
|
cmdproc = Trepan::CmdProcessor.new(nil)
|
225
|
-
cmddir = File.join(File.dirname(__FILE__), 'command')
|
226
|
-
cmdproc.instance_variable_set('@settings', {})
|
227
|
-
cmdproc.load_cmds_initialize
|
228
|
-
require 'columnize'
|
229
|
-
puts Columnize.columnize(cmdproc.commands.keys.sort)
|
230
|
-
puts '=' * 20
|
231
|
-
puts Columnize.columnize(cmdproc.aliases.keys.sort)
|
232
|
-
puts '=' * 20
|
233
147
|
|
234
148
|
def cmdproc.errmsg(mess)
|
235
149
|
puts "** #{mess}"
|
@@ -239,10 +153,16 @@ if __FILE__ == $0
|
|
239
153
|
puts mess
|
240
154
|
end
|
241
155
|
|
156
|
+
cmddir = File.join(File.dirname(__FILE__), 'command')
|
157
|
+
cmdproc.instance_variable_set('@settings', {})
|
158
|
+
cmdproc.load_cmds_initialize
|
159
|
+
require 'columnize'
|
160
|
+
puts Columnize.columnize(cmdproc.commands.keys.sort)
|
161
|
+
puts '=' * 20
|
162
|
+
puts Columnize.columnize(cmdproc.aliases.keys.sort)
|
163
|
+
puts '=' * 20
|
164
|
+
|
242
165
|
cmdproc.run_cmd('foo') # Invalid - not an Array
|
243
166
|
cmdproc.run_cmd([]) # Invalid - empty Array
|
244
167
|
cmdproc.run_cmd(['list', 5]) # Invalid - nonstring arg
|
245
|
-
p cmdproc.complete("d", 'd')
|
246
|
-
p cmdproc.complete("sho d", 'd')
|
247
|
-
p cmdproc.complete('', '')
|
248
168
|
end
|
data/processor/location.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (C) 2010,
|
1
|
+
# Copyright (C) 2010-2011, 2013, 2015 Rocky Bernstein <rockyb@rubyforge.net>
|
2
2
|
require 'rubygems'
|
3
3
|
require 'linecache'
|
4
4
|
require 'pathname' # For cleanpath
|
@@ -32,39 +32,39 @@ class Trepan::CmdProcessor < Trepan::VirtualCmdProcessor
|
|
32
32
|
'vm' => 'VM',
|
33
33
|
'vm-insn' => '..',
|
34
34
|
'yield' => '<>',
|
35
|
-
}
|
35
|
+
}
|
36
36
|
end
|
37
37
|
|
38
38
|
def canonic_container(container)
|
39
39
|
[container[0], canonic_file(container[1])]
|
40
40
|
end
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
41
|
+
|
42
|
+
def canonic_file(filename, resolve=true)
|
43
|
+
# For now we want resolved filenames
|
44
|
+
if @settings[:basename]
|
45
|
+
File.basename(filename)
|
46
|
+
elsif resolve
|
47
|
+
filename = LineCache::map_file(filename)
|
48
|
+
File.expand_path(Pathname.new(filename).cleanpath.to_s)
|
49
|
+
else
|
50
|
+
filename
|
51
|
+
end
|
51
52
|
end
|
52
|
-
end
|
53
53
|
|
54
54
|
# Return the text to the current source line.
|
55
55
|
# FIXME: loc_and_text should call this rather than the other
|
56
56
|
# way around.
|
57
57
|
def current_source_text
|
58
58
|
opts = {:reload_on_change => @reload}
|
59
|
-
junk1, junk2, text, found_line =
|
60
|
-
loc_and_text('', frame, frame.source_location[0],
|
59
|
+
junk1, junk2, text, found_line =
|
60
|
+
loc_and_text('', frame, frame.source_location[0],
|
61
61
|
frame.source_container, opts)
|
62
62
|
text
|
63
63
|
end
|
64
|
-
|
64
|
+
|
65
65
|
def resolve_file_with_dir(path_suffix)
|
66
66
|
@settings[:directory].split(/:/).each do |dir|
|
67
|
-
dir =
|
67
|
+
dir =
|
68
68
|
if '$cwd' == dir
|
69
69
|
Dir.pwd
|
70
70
|
elsif '$cdir' == dir
|
@@ -78,7 +78,7 @@ class Trepan::CmdProcessor < Trepan::VirtualCmdProcessor
|
|
78
78
|
end
|
79
79
|
nil
|
80
80
|
end
|
81
|
-
|
81
|
+
|
82
82
|
# Get line +line_number+ from file named +filename+. Return ''
|
83
83
|
# if there was a problem. Leading blanks are stripped off.
|
84
84
|
def line_at(filename, line_number,
|
@@ -87,12 +87,12 @@ class Trepan::CmdProcessor < Trepan::VirtualCmdProcessor
|
|
87
87
|
:output => @settings[:highlight]
|
88
88
|
})
|
89
89
|
line = LineCache::getline(filename, line_number, opts)
|
90
|
-
|
90
|
+
|
91
91
|
unless line
|
92
92
|
# Try using search directories (set with command "directory")
|
93
93
|
if filename[0..0] != File::SEPARATOR
|
94
|
-
try_filename = resolve_file_with_dir(filename)
|
95
|
-
if try_filename &&
|
94
|
+
try_filename = resolve_file_with_dir(filename)
|
95
|
+
if try_filename &&
|
96
96
|
line = LineCache::getline(try_filename, line_number, opts)
|
97
97
|
LineCache::remap_file(filename, try_filename)
|
98
98
|
end
|
@@ -103,89 +103,97 @@ class Trepan::CmdProcessor < Trepan::VirtualCmdProcessor
|
|
103
103
|
|
104
104
|
def loc_and_text(loc, frame, line_no, source_container,
|
105
105
|
opts = {
|
106
|
-
|
107
|
-
|
106
|
+
:reload_on_change => @settings[:reload],
|
107
|
+
:output => @settings[:highlight]
|
108
108
|
})
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
109
|
+
found_line = true
|
110
|
+
## FIXME: condition is too long.
|
111
|
+
if source_container[0] == 'string' && frame.iseq && frame.iseq.eval_source
|
112
|
+
file = LineCache::map_iseq(frame.iseq)
|
113
|
+
text = LineCache::getline(frame.iseq, line_no, opts)
|
114
|
+
loc += " remapped #{canonic_file(file)}:#{line_no}"
|
115
|
+
elsif source_container[0] != 'file'
|
116
|
+
via = loc
|
117
|
+
# while not (source_container[0] == 'file' and text_file?(source_container[1])) and
|
118
|
+
while not (source_container[0] == 'file') and
|
119
|
+
frame.prev do
|
120
|
+
frame = frame.prev
|
121
|
+
source_container = frame_container(frame, false)
|
122
|
+
end
|
123
|
+
if source_container[0] == 'file'
|
124
|
+
sloc = frame.source_location
|
125
|
+
line_no = sloc && sloc.size > 0 ? sloc[0] : '?'
|
126
|
+
filename = source_container[1]
|
127
|
+
loc += " via #{canonic_file(filename)}:#{line_no}"
|
128
|
+
text = line_at(filename, line_no, opts)
|
129
|
+
found_line = false
|
130
|
+
end
|
131
|
+
else
|
132
|
+
container = source_container[1]
|
133
|
+
map_file, map_line = LineCache::map_file_line(container, line_no)
|
134
|
+
if [container, line_no] != [map_file, map_line]
|
135
|
+
loc += " remapped #{canonic_file(map_file)}:#{map_line}"
|
136
|
+
end
|
137
|
+
|
138
|
+
text = line_at(container, line_no, opts)
|
133
139
|
end
|
134
|
-
|
135
|
-
text = line_at(container, line_no, opts)
|
136
|
-
end
|
137
|
-
[loc, line_no, text, found_line]
|
140
|
+
[loc, line_no, text, found_line]
|
138
141
|
end
|
139
|
-
|
142
|
+
|
140
143
|
def print_location
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
144
|
+
if %w(c-call call).member?(@event)
|
145
|
+
# FIXME: Fix Ruby so we don't need this workaround?
|
146
|
+
# See also where.rb
|
147
|
+
opts = {}
|
148
|
+
opts[:class] = @core.hook_arg if
|
149
|
+
'CFUNC' == @frame.type && @core.hook_arg && 0 == @frame_index
|
150
|
+
msg format_stack_call(@frame, opts)
|
151
|
+
elsif 'raise' == @event
|
152
|
+
msg @core.hook_arg.inspect if @core.hook_arg # Exception object
|
153
|
+
end
|
154
|
+
|
155
|
+
text = nil
|
156
|
+
source_container = frame_container(@frame, false)
|
157
|
+
ev = if @event.nil? || 0 != @frame_index
|
158
|
+
' '
|
159
|
+
else
|
160
|
+
(EVENT2ICON[@event] || @event)
|
161
|
+
end
|
162
|
+
@line_no = frame_line
|
163
|
+
|
164
|
+
loc = source_location_info(source_container, @line_no, @frame)
|
165
|
+
loc, @line_no, text, found_line =
|
166
|
+
loc_and_text(loc, @frame, @line_no, source_container)
|
167
|
+
|
168
|
+
ip_str = @frame.iseq ? " @#{frame.pc_offset}" : ''
|
169
|
+
msg "#{ev} (#{loc}#{ip_str})"
|
170
|
+
|
171
|
+
if %w(return c-return).member?(@event)
|
172
|
+
retval = Trepan::Frame.value_returned(@frame, @event)
|
173
|
+
msg 'R=> %s' % retval.inspect
|
174
|
+
elsif @event == 'raise'
|
175
|
+
# msg @proc.core.hook_arg.inspect if @proc.core.hook_arg
|
176
|
+
if @frame.iseq and @frame.iseq.catch_table_size == 0
|
177
|
+
msg "Warning: exception raised is non-local!"
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
if text && !text.strip.empty?
|
182
|
+
msg text
|
183
|
+
@line_no -= 1
|
184
|
+
end
|
185
|
+
unless found_line
|
186
|
+
# Can't find source line, so give assembly as consolation.
|
187
|
+
# This great idea comes from the Rubinius reference debugger.
|
188
|
+
run_command('disassemble')
|
189
|
+
end
|
182
190
|
end
|
183
|
-
|
191
|
+
|
184
192
|
def source_location_info(source_container, line_no, frame)
|
185
193
|
filename = source_container[1]
|
186
194
|
## FIXME: condition is too long.
|
187
|
-
canonic_filename =
|
188
|
-
if 'string' == source_container[0] && frame.iseq &&
|
195
|
+
canonic_filename =
|
196
|
+
if 'string' == source_container[0] && frame.iseq &&
|
189
197
|
frame.iseq.eval_source
|
190
198
|
eval_str = frame.iseq.eval_source
|
191
199
|
'eval "' + safe_repr(eval_str.gsub(/\n/,';'), 15) + '"'
|