rbx-trepanning 0.0.1-universal-rubinius
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/ChangeLog +376 -0
- data/LICENSE +25 -0
- data/NEWS +2 -0
- data/README.textile +28 -0
- data/Rakefile +165 -0
- data/THANKS +14 -0
- data/app/breakpoint.rb +218 -0
- data/app/breakpoint.rbc +3564 -0
- data/app/brkptmgr.rb +138 -0
- data/app/brkptmgr.rbc +2827 -0
- data/app/default.rb +61 -0
- data/app/default.rbc +1011 -0
- data/app/display.rb +35 -0
- data/app/display.rbc +968 -0
- data/app/frame.rb +98 -0
- data/app/frame.rbc +1808 -0
- data/app/irb.rb +112 -0
- data/app/irb.rbc +2111 -0
- data/app/iseq.rb +95 -0
- data/app/iseq.rbc +1801 -0
- data/app/method.rb +173 -0
- data/app/method.rbc +2492 -0
- data/app/mock.rb +13 -0
- data/app/mock.rbc +398 -0
- data/app/options.rb +123 -0
- data/app/options.rbc +2183 -0
- data/app/run.rb +86 -0
- data/app/run.rbc +1244 -0
- data/app/util.rb +49 -0
- data/app/util.rbc +1144 -0
- data/app/validate.rb +30 -0
- data/app/validate.rbc +676 -0
- data/bin/trepan.compiled.rbc +1043 -0
- data/bin/trepanx +63 -0
- data/bin/trepanx.compiled.rbc +985 -0
- data/interface/base_intf.rb +95 -0
- data/interface/base_intf.rbc +1742 -0
- data/interface/script.rb +104 -0
- data/interface/script.rbc +1642 -0
- data/interface/user.rb +91 -0
- data/interface/user.rbc +1418 -0
- data/io/base_io.rb +94 -0
- data/io/base_io.rbc +1404 -0
- data/io/input.rb +112 -0
- data/io/input.rbc +1979 -0
- data/io/null_output.rb +42 -0
- data/io/null_output.rbc +730 -0
- data/io/string_array.rb +156 -0
- data/io/string_array.rbc +2466 -0
- data/lib/trepanning.rb +398 -0
- data/lib/trepanning.rbc +6661 -0
- data/processor/breakpoint.rb +161 -0
- data/processor/command/alias.rb +55 -0
- data/processor/command/backtrace.rb +46 -0
- data/processor/command/base/cmd.rb +124 -0
- data/processor/command/base/subcmd.rb +213 -0
- data/processor/command/base/submgr.rb +179 -0
- data/processor/command/base/subsubcmd.rb +103 -0
- data/processor/command/base/subsubmgr.rb +184 -0
- data/processor/command/break.rb +100 -0
- data/processor/command/continue.rb +82 -0
- data/processor/command/delete.rb +30 -0
- data/processor/command/directory.rb +43 -0
- data/processor/command/disassemble.rb +103 -0
- data/processor/command/down.rb +54 -0
- data/processor/command/eval.rb +31 -0
- data/processor/command/exit.rb +58 -0
- data/processor/command/finish.rb +78 -0
- data/processor/command/frame.rb +89 -0
- data/processor/command/help.rb +146 -0
- data/processor/command/info.rb +28 -0
- data/processor/command/info_subcmd/breakpoints.rb +75 -0
- data/processor/command/info_subcmd/file.rb +153 -0
- data/processor/command/info_subcmd/method.rb +71 -0
- data/processor/command/info_subcmd/program.rb +59 -0
- data/processor/command/info_subcmd/variables.rb +40 -0
- data/processor/command/irb.rb +96 -0
- data/processor/command/kill.rb +70 -0
- data/processor/command/list.rb +296 -0
- data/processor/command/next.rb +66 -0
- data/processor/command/nexti.rb +59 -0
- data/processor/command/pr.rb +38 -0
- data/processor/command/ps.rb +40 -0
- data/processor/command/restart.rb +60 -0
- data/processor/command/set.rb +47 -0
- data/processor/command/set_subcmd/auto.rb +28 -0
- data/processor/command/set_subcmd/auto_subcmd/dis.rb +33 -0
- data/processor/command/set_subcmd/auto_subcmd/eval.rb +54 -0
- data/processor/command/set_subcmd/auto_subcmd/irb.rb +34 -0
- data/processor/command/set_subcmd/auto_subcmd/list.rb +34 -0
- data/processor/command/set_subcmd/basename.rb +26 -0
- data/processor/command/set_subcmd/debug.rb +27 -0
- data/processor/command/set_subcmd/debug_subcmd/dbgr.rb +36 -0
- data/processor/command/set_subcmd/debug_subcmd/skip.rb +23 -0
- data/processor/command/set_subcmd/debug_subcmd/step.rb +23 -0
- data/processor/command/set_subcmd/different.rb +60 -0
- data/processor/command/set_subcmd/hidelevel.rb +63 -0
- data/processor/command/set_subcmd/kernelstep.rb +61 -0
- data/processor/command/set_subcmd/max.rb +29 -0
- data/processor/command/set_subcmd/max_subcmd/list.rb +49 -0
- data/processor/command/set_subcmd/max_subcmd/stack.rb +50 -0
- data/processor/command/set_subcmd/max_subcmd/string.rb +54 -0
- data/processor/command/set_subcmd/max_subcmd/width.rb +49 -0
- data/processor/command/set_subcmd/substitute.rb +25 -0
- data/processor/command/set_subcmd/substitute_subcmd/path.rb +56 -0
- data/processor/command/set_subcmd/trace.rb +37 -0
- data/processor/command/set_subcmd/trace_subcmd/print.rb +57 -0
- data/processor/command/show.rb +27 -0
- data/processor/command/show_subcmd/alias.rb +43 -0
- data/processor/command/show_subcmd/args.rb +26 -0
- data/processor/command/show_subcmd/auto.rb +28 -0
- data/processor/command/show_subcmd/auto_subcmd/dis.rb +37 -0
- data/processor/command/show_subcmd/auto_subcmd/eval.rb +28 -0
- data/processor/command/show_subcmd/auto_subcmd/irb.rb +23 -0
- data/processor/command/show_subcmd/auto_subcmd/list.rb +22 -0
- data/processor/command/show_subcmd/basename.rb +22 -0
- data/processor/command/show_subcmd/debug.rb +27 -0
- data/processor/command/show_subcmd/debug_subcmd/dbgr.rb +21 -0
- data/processor/command/show_subcmd/debug_subcmd/skip.rb +22 -0
- data/processor/command/show_subcmd/debug_subcmd/step.rb +22 -0
- data/processor/command/show_subcmd/different.rb +27 -0
- data/processor/command/show_subcmd/hidelevel.rb +42 -0
- data/processor/command/show_subcmd/kernelstep.rb +37 -0
- data/processor/command/show_subcmd/max.rb +30 -0
- data/processor/command/show_subcmd/max_subcmd/list.rb +38 -0
- data/processor/command/show_subcmd/max_subcmd/stack.rb +36 -0
- data/processor/command/show_subcmd/max_subcmd/string.rb +42 -0
- data/processor/command/show_subcmd/max_subcmd/width.rb +37 -0
- data/processor/command/show_subcmd/trace.rb +29 -0
- data/processor/command/show_subcmd/trace_subcmd/print.rb +38 -0
- data/processor/command/source.rb +83 -0
- data/processor/command/step.rb +41 -0
- data/processor/command/tbreak.rb +19 -0
- data/processor/command/unalias.rb +44 -0
- data/processor/command/up.rb +87 -0
- data/processor/default.rb +56 -0
- data/processor/disassemble.rb +32 -0
- data/processor/eval.rb +96 -0
- data/processor/frame.rb +211 -0
- data/processor/help.rb +72 -0
- data/processor/hook.rb +133 -0
- data/processor/load_cmds.rb +101 -0
- data/processor/location.rb +128 -0
- data/processor/main.rb +394 -0
- data/processor/mock.rb +137 -0
- data/processor/msg.rb +28 -0
- data/processor/running.rb +230 -0
- data/processor/stepping.rb +115 -0
- data/processor/subcmd.rb +160 -0
- data/processor/validate.rb +355 -0
- data/test/data/enable.right +36 -0
- data/test/data/fname-with-blank.cmd +6 -0
- data/test/data/fname-with-blank.right +1 -0
- data/test/data/quit-Xdebug.right +3 -0
- data/test/data/quit.cmd +5 -0
- data/test/data/quit.right +0 -0
- data/test/example/fname with blank.rb +1 -0
- data/test/example/gcd-xx.rb +18 -0
- data/test/example/gcd.rb +19 -0
- data/test/example/gcd1.rb +24 -0
- data/test/example/null.rb +1 -0
- data/test/example/thread1.rb +3 -0
- data/test/functional/fn_helper.rb +112 -0
- data/test/functional/test-break-name.rb +52 -0
- data/test/functional/test-break.rb +51 -0
- data/test/functional/test-finish.rb +70 -0
- data/test/functional/test-fn_helper.rb +43 -0
- data/test/functional/test-list.rb +55 -0
- data/test/functional/test-next-bug.rb +49 -0
- data/test/functional/test-next.rb +101 -0
- data/test/functional/test-step.rb +272 -0
- data/test/functional/test-step2.rb +35 -0
- data/test/functional/test-tbreak.rb +41 -0
- data/test/integration/file-diff.rb +89 -0
- data/test/integration/helper.rb +78 -0
- data/test/integration/test-fname-with-blank.rb +12 -0
- data/test/integration/test-quit.rb +25 -0
- data/test/unit/cmd-helper.rb +46 -0
- data/test/unit/test-app-brkpt.rb +30 -0
- data/test/unit/test-app-brkptmgr.rb +51 -0
- data/test/unit/test-app-iseq.rb +49 -0
- data/test/unit/test-app-method.rb +54 -0
- data/test/unit/test-app-options.rb +61 -0
- data/test/unit/test-app-run.rb +16 -0
- data/test/unit/test-app-util.rb +28 -0
- data/test/unit/test-app-validate.rb +18 -0
- data/test/unit/test-base-subcmd.rb +61 -0
- data/test/unit/test-bin-trepanx.rb +48 -0
- data/test/unit/test-cmd-alias.rb +49 -0
- data/test/unit/test-cmd-break.rb +23 -0
- data/test/unit/test-cmd-exit.rb +27 -0
- data/test/unit/test-cmd-help.rb +101 -0
- data/test/unit/test-cmd-kill.rb +48 -0
- data/test/unit/test-intf-user.rb +46 -0
- data/test/unit/test-io-input.rb +27 -0
- data/test/unit/test-proc-eval.rb +37 -0
- data/test/unit/test-proc-frame.rb +79 -0
- data/test/unit/test-proc-help.rb +16 -0
- data/test/unit/test-proc-hook.rb +30 -0
- data/test/unit/test-proc-load_cmds.rb +41 -0
- data/test/unit/test-proc-location.rb +48 -0
- data/test/unit/test-proc-main.rb +96 -0
- data/test/unit/test-proc-validate.rb +91 -0
- data/test/unit/test-subcmd-help.rb +51 -0
- metadata +337 -0
@@ -0,0 +1,179 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
# Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
|
3
|
+
require 'rubygems'; require 'require_relative'
|
4
|
+
require_relative 'cmd'
|
5
|
+
require_relative '../../subcmd'
|
6
|
+
require_relative '../../help'
|
7
|
+
|
8
|
+
class Trepan::SubcommandMgr < Trepan::Command
|
9
|
+
|
10
|
+
include Trepan::Help
|
11
|
+
|
12
|
+
unless defined?(CATEGORY)
|
13
|
+
CATEGORY = 'status'
|
14
|
+
MIN_ARGS = 0
|
15
|
+
MAX_ARGS = nil
|
16
|
+
NAME = '?' # FIXME: Need to define this, but should
|
17
|
+
# pick this up from class/file name.
|
18
|
+
NEED_STACK = false
|
19
|
+
end
|
20
|
+
|
21
|
+
attr_accessor :subcmds # Array of instaniated Trepan::Subcommand objects
|
22
|
+
attr_reader :name # Name of command
|
23
|
+
attr_reader :last_args # Last arguments seen
|
24
|
+
|
25
|
+
# Initialize show subcommands. Note: instance variable name
|
26
|
+
# has to be setcmds ('set' + 'cmds') for subcommand completion
|
27
|
+
# to work.
|
28
|
+
def initialize(proc)
|
29
|
+
@name = obj_const(self, :NAME)
|
30
|
+
@subcmds = Trepan::Subcmd.new(self)
|
31
|
+
@proc = proc
|
32
|
+
load_debugger_subcommands(self)
|
33
|
+
end
|
34
|
+
|
35
|
+
# Create an instance of each of the debugger subcommands. Commands
|
36
|
+
# are found by importing files in the directory 'name' + '_sub'. Some
|
37
|
+
# files are excluded via an array set in initialize. For each of
|
38
|
+
# the remaining files, we import them and scan for class names
|
39
|
+
# inside those files and for each class name, we will create an
|
40
|
+
# instance of that class. The set of TrepanCommand class instances
|
41
|
+
# form set of possible debugger commands.
|
42
|
+
def load_debugger_subcommands(parent)
|
43
|
+
|
44
|
+
# Initialization
|
45
|
+
cmd_names = []
|
46
|
+
subcmd_names = []
|
47
|
+
cmd_dir = File.dirname(__FILE__)
|
48
|
+
subcmd_dir = File.join(cmd_dir, '..', name + '_subcmd')
|
49
|
+
files = Dir.glob(File.join(subcmd_dir, '*.rb'))
|
50
|
+
files.each do |rb|
|
51
|
+
basename = File.basename(rb, '.rb')
|
52
|
+
if File.directory?(File.join(File.dirname(rb), basename + '_subcmd'))
|
53
|
+
subcmd_names << name.capitalize + basename.capitalize
|
54
|
+
else
|
55
|
+
cmd_names << name.capitalize + basename.capitalize
|
56
|
+
end
|
57
|
+
require rb
|
58
|
+
end if File.directory?(subcmd_dir)
|
59
|
+
|
60
|
+
subcommands = {}
|
61
|
+
cmd_names.each do |name|
|
62
|
+
next unless Trepan::Subcommand.constants.member?(name)
|
63
|
+
subcmd_class = "Trepan::Subcommand::#{name}.new(self)"
|
64
|
+
cmd = self.instance_eval(subcmd_class)
|
65
|
+
cmd_name = cmd.name
|
66
|
+
@subcmds.add(cmd)
|
67
|
+
end
|
68
|
+
subcmd_names.each do |name|
|
69
|
+
next unless Trepan::SubSubcommand.constants.member?(name)
|
70
|
+
subcmd_class = "Trepan::SubSubcommand::#{name}.new(self, parent)"
|
71
|
+
begin
|
72
|
+
cmd = self.instance_eval(subcmd_class)
|
73
|
+
rescue
|
74
|
+
puts "Subcmd #{name} is bad"
|
75
|
+
end
|
76
|
+
cmd_name = cmd.name
|
77
|
+
@subcmds.add(cmd)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# Give help for a command which has subcommands. This can be
|
82
|
+
# called in several ways:
|
83
|
+
# help cmd
|
84
|
+
# help cmd subcmd
|
85
|
+
# help cmd commands
|
86
|
+
#
|
87
|
+
# Our shtick is to give help for the overall command only if
|
88
|
+
# subcommand or 'commands' is not given. If a subcommand is given and
|
89
|
+
# found, then specific help for that is given. If 'commands' is given
|
90
|
+
# we will list the all the subcommands.
|
91
|
+
def help(args)
|
92
|
+
if args.size <= 2
|
93
|
+
# "help cmd". Give the general help for the command part.
|
94
|
+
doc = my_const(:HELP)
|
95
|
+
if doc
|
96
|
+
return doc
|
97
|
+
else
|
98
|
+
errmsg('Sorry - author mess up. ' +
|
99
|
+
'No help registered for command' +
|
100
|
+
@name)
|
101
|
+
return nil
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
subcmd_name = args[2]
|
106
|
+
|
107
|
+
if '*' == subcmd_name
|
108
|
+
help_text = ["List of subcommands for command '%s':" % @name]
|
109
|
+
help_text << columnize_commands(@subcmds.list)
|
110
|
+
return help_text
|
111
|
+
end
|
112
|
+
|
113
|
+
# "help cmd subcmd". Give help specific for that subcommand.
|
114
|
+
cmd = @subcmds.lookup(subcmd_name, false)
|
115
|
+
if cmd
|
116
|
+
if cmd.respond_to?(:help)
|
117
|
+
return cmd.help(args)
|
118
|
+
else
|
119
|
+
doc = obj_const(cmd, :HELP)
|
120
|
+
if doc
|
121
|
+
return doc
|
122
|
+
else
|
123
|
+
errmsg('Sorry - author mess up. ' +
|
124
|
+
'No help registered for subcommand: ' +
|
125
|
+
subcmd_name + ', of command: ' +
|
126
|
+
@name)
|
127
|
+
return nil
|
128
|
+
end
|
129
|
+
end
|
130
|
+
else
|
131
|
+
matches = @subcmds.list.grep(/^#{subcmd_name}/).sort
|
132
|
+
if matches.empty?
|
133
|
+
errmsg("No #{name} subcommands found matching /^#{subcmd_name}/. Try \"help\" #{@name}.")
|
134
|
+
return nil
|
135
|
+
elsif 1 == matches.size
|
136
|
+
args[-1] = matches[0].to_s
|
137
|
+
help(args)
|
138
|
+
else
|
139
|
+
help_text = ["Subcommands of \"#{@name}\" matching /^#{subcmd_name}/:"]
|
140
|
+
help_text << columnize_commands(matches.sort)
|
141
|
+
return help_text
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def run(args)
|
147
|
+
@last_args = args
|
148
|
+
if args.size < 2 || args.size == 2 && args[-1] == '*'
|
149
|
+
summary_list(obj_const(self, :NAME), @subcmds)
|
150
|
+
return false
|
151
|
+
end
|
152
|
+
|
153
|
+
subcmd_prefix = args[1]
|
154
|
+
# We were given: cmd subcmd ...
|
155
|
+
# Run that.
|
156
|
+
subcmd = @subcmds.lookup(subcmd_prefix)
|
157
|
+
if subcmd
|
158
|
+
subcmd.run(args)
|
159
|
+
else
|
160
|
+
undefined_subcmd(@name, subcmd_prefix)
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
if __FILE__ == $0
|
166
|
+
# Demo it.
|
167
|
+
require_relative '../../mock'
|
168
|
+
dbgr = MockDebugger::MockDebugger.new
|
169
|
+
# cmds = dbgr.core.processor.commands
|
170
|
+
# cmd = cmds['set']
|
171
|
+
# Trepan::SubcommandMgr.new(dbgr.core.processor)
|
172
|
+
# puts cmd.help(%w(help set))
|
173
|
+
# puts '=' * 40
|
174
|
+
# # require_relative '../../../lib/trepanning)
|
175
|
+
# # Trepan.debug(:set_restart => true)
|
176
|
+
# puts cmd.help(%w(help set *))
|
177
|
+
# puts '=' * 40
|
178
|
+
# puts cmd.help(%w(help set d.*))
|
179
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
# Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
|
3
|
+
# A base class for debugger subcommands of subcommands.
|
4
|
+
#
|
5
|
+
# Note: don't end classname with Command (capital C as in SubCommand),
|
6
|
+
# since main will think this a command name like QuitCommand
|
7
|
+
# ^
|
8
|
+
|
9
|
+
# Base Class for Trepan subcommands. We pull in some helper
|
10
|
+
# functions for command from module cmdfns.
|
11
|
+
|
12
|
+
require 'rubygems'; require 'require_relative'
|
13
|
+
require_relative 'cmd'
|
14
|
+
require_relative 'subcmd'
|
15
|
+
|
16
|
+
class Trepan
|
17
|
+
|
18
|
+
class SubSubcommand < Subcommand
|
19
|
+
def initialize(cmd, parent, name)
|
20
|
+
@cmd = cmd
|
21
|
+
@name = name
|
22
|
+
@parent = parent
|
23
|
+
@proc = parent.proc
|
24
|
+
end
|
25
|
+
|
26
|
+
def settings
|
27
|
+
@parent.settings
|
28
|
+
end
|
29
|
+
|
30
|
+
def string_in_show
|
31
|
+
help_constant_sym = if self.class.constants.member?('SHORT_HELP')
|
32
|
+
:SHORT_HELP
|
33
|
+
else :HELP
|
34
|
+
end
|
35
|
+
str = my_const(help_constant_sym)
|
36
|
+
%w(Show Set).each do |word|
|
37
|
+
if 0 == str.index(word)
|
38
|
+
str = str[word.size+1 ..-1].capitalize
|
39
|
+
break
|
40
|
+
end
|
41
|
+
end
|
42
|
+
str
|
43
|
+
end
|
44
|
+
|
45
|
+
# Set a Boolean-valued debugger setting.
|
46
|
+
def run_set_bool(args, default=true)
|
47
|
+
set_val = args.size < 2 ? 'on' : args[1]
|
48
|
+
setting = @name.gsub(/^(set|show)/,'')
|
49
|
+
begin
|
50
|
+
settings[setting.to_sym] = @proc.get_onoff(set_val)
|
51
|
+
run_show_bool(string_in_show)
|
52
|
+
rescue NameError, TypeError
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def run_show_bool(what=nil)
|
57
|
+
setting = @name.gsub(/^(set|show)/,'')
|
58
|
+
val = show_onoff(settings[setting.to_sym])
|
59
|
+
what = setting unless what
|
60
|
+
msg('%s is %s.' % [what.chomp, val])
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
|
65
|
+
class SetBoolSubSubcommand < SubSubcommand
|
66
|
+
def run(args)
|
67
|
+
run_set_bool(args)
|
68
|
+
end
|
69
|
+
|
70
|
+
def save_command
|
71
|
+
val = settings[subcmd_setting_key] ? 'on' : 'off'
|
72
|
+
["#{subcmd_prefix_string} #{val}"]
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
class ShowBoolSubSubcommand < SubSubcommand
|
77
|
+
def run(args)
|
78
|
+
run_show_bool(string_in_show)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
class ShowIntSubSubcommand < SubSubcommand
|
83
|
+
def run(args)
|
84
|
+
run_show_int
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
if __FILE__ == $0
|
90
|
+
# Demo it.
|
91
|
+
require_relative '../../mock'
|
92
|
+
require_relative '../../subcmd'
|
93
|
+
name = File.basename(__FILE__, '.rb')
|
94
|
+
|
95
|
+
# FIXME: DRY the below code
|
96
|
+
dbgr, info_cmd = MockDebugger::setup('info')
|
97
|
+
testcmdMgr = Trepan::Subcmd.new(info_cmd)
|
98
|
+
cmd_name = 'testing'
|
99
|
+
infox_cmd = Trepan::SubSubcommand.new(info_cmd.proc,
|
100
|
+
info_cmd,
|
101
|
+
cmd_name)
|
102
|
+
infox_cmd.settings
|
103
|
+
end
|
@@ -0,0 +1,184 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
# Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
|
3
|
+
require 'rubygems'; require 'require_relative'
|
4
|
+
require_relative 'subcmd'
|
5
|
+
require_relative '../../subcmd'
|
6
|
+
require_relative '../../help'
|
7
|
+
|
8
|
+
require 'rubygems'; require 'require_relative'
|
9
|
+
class Trepan::SubSubcommandMgr < Trepan::Subcommand
|
10
|
+
|
11
|
+
include Trepan::Help
|
12
|
+
|
13
|
+
unless defined?(CATEGORY)
|
14
|
+
CATEGORY = 'status'
|
15
|
+
MIN_ARGS = 0
|
16
|
+
MAX_ARGS = nil
|
17
|
+
NAME = '?' # FIXME: Need to define this, but should
|
18
|
+
# pick this up from class/file name.
|
19
|
+
NEED_STACK = false
|
20
|
+
end
|
21
|
+
|
22
|
+
attr_accessor :pname
|
23
|
+
attr_accessor :subcmds # Array of instantiated Trepan::Subcommand objects
|
24
|
+
|
25
|
+
# Initialize show subcommands. Note: instance variable name
|
26
|
+
# has to be setcmds ('set' + 'cmds') for subcommand completion
|
27
|
+
# to work.
|
28
|
+
# FIXME: do we need proc still?
|
29
|
+
def initialize(proc, parent)
|
30
|
+
name = obj_const(self, :NAME)
|
31
|
+
@name = name.to_sym
|
32
|
+
@subcmds = Trepan::Subcmd.new(self)
|
33
|
+
@parent = parent
|
34
|
+
@pname = parent.name
|
35
|
+
@proc = parent.proc
|
36
|
+
|
37
|
+
# Set class constant SHORT_HELP to be the first line of HELP
|
38
|
+
# unless it has been defined in the class already.
|
39
|
+
# The below was the simplest way I could find to do this since
|
40
|
+
# we are the super class but want to set the subclass's constant.
|
41
|
+
# defined? didn't seem to work here.
|
42
|
+
c = self.class.constants
|
43
|
+
self.class.const_set('SHORT_HELP',
|
44
|
+
self.class.const_get('HELP')) if
|
45
|
+
c.member?('HELP') and !c.member?('SHORT_HELP')
|
46
|
+
|
47
|
+
load_debugger_subsubcommands(name, self)
|
48
|
+
end
|
49
|
+
|
50
|
+
# Create an instance of each of the debugger subcommands. Commands
|
51
|
+
# are found by importing files in the directory 'name' + 'sub'. Some
|
52
|
+
# files are excluded via an array set in initialize. For each of
|
53
|
+
# the remaining files, we import them and scan for class names
|
54
|
+
# inside those files and for each class name, we will create an
|
55
|
+
# instance of that class. The set of TrepanCommand class instances
|
56
|
+
# form set of possible debugger commands.
|
57
|
+
def load_debugger_subsubcommands(name, obj)
|
58
|
+
|
59
|
+
# Initialization
|
60
|
+
cmd_names = []
|
61
|
+
cmd_dir = File.dirname(__FILE__)
|
62
|
+
subcmd_dir = File.join(cmd_dir, '..', @pname + '_subcmd', name + '_subcmd')
|
63
|
+
files = Dir.glob(File.join(subcmd_dir, '*.rb'))
|
64
|
+
files.each do |rb|
|
65
|
+
cmd_names << name.capitalize + File.basename(rb, '.rb').capitalize
|
66
|
+
require rb
|
67
|
+
end if File.directory?(subcmd_dir)
|
68
|
+
|
69
|
+
subcommands = {}
|
70
|
+
cmd_names.each do |subname|
|
71
|
+
cmd_name = "#{pname}#{subname.downcase}"
|
72
|
+
subclass_name = "#{@pname.capitalize}#{subname}"
|
73
|
+
next unless
|
74
|
+
Trepan::SubSubcommand.constants.member?(subclass_name)
|
75
|
+
cmd = self.instance_eval("Trepan::SubSubcommand::" + subclass_name +
|
76
|
+
".new(self, @parent, '#{cmd_name}')")
|
77
|
+
@subcmds.add(cmd, cmd_name)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# Give help for a command which has subcommands. This can be
|
82
|
+
# called in several ways:
|
83
|
+
# help cmd
|
84
|
+
# help cmd subcmd
|
85
|
+
# help cmd commands
|
86
|
+
#
|
87
|
+
# Our shtick is to give help for the overall command only if
|
88
|
+
# subcommand or 'commands' is not given. If a subcommand is given and
|
89
|
+
# found, then specific help for that is given. If 'commands' is given
|
90
|
+
# we will list the all the subcommands.
|
91
|
+
def help(args)
|
92
|
+
if args.size <= 3
|
93
|
+
# "help cmd". Give the general help for the command part.
|
94
|
+
doc = self.class.const_get(:HELP)
|
95
|
+
if doc
|
96
|
+
return doc
|
97
|
+
else
|
98
|
+
errmsg('Sorry - author mess up. ' +
|
99
|
+
'No help registered for command' +
|
100
|
+
@name)
|
101
|
+
return nil
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
prefix = my_const(:PREFIX)
|
106
|
+
subcmd_name = args[prefix.size+1]
|
107
|
+
prefix_str = prefix.join(' ')
|
108
|
+
|
109
|
+
if '*' == subcmd_name
|
110
|
+
help_text = ["List of subcommands for '%s':" % prefix_str]
|
111
|
+
cmd_names = @subcmds.list.map{|c| c[prefix_str.size-1..-1]}
|
112
|
+
help_text << columnize_commands(cmd_names)
|
113
|
+
return help_text
|
114
|
+
end
|
115
|
+
|
116
|
+
# "help cmd subcmd". Give help specific for that subcommand if
|
117
|
+
# the command matches uniquely, or show a list of matching
|
118
|
+
# subcommands
|
119
|
+
keyprefix_str = prefix.join('')
|
120
|
+
key_str = keyprefix_str + subcmd_name
|
121
|
+
cmd = @subcmds.lookup(key_str, false)
|
122
|
+
if cmd
|
123
|
+
doc = obj_const(cmd, :HELP)
|
124
|
+
if doc
|
125
|
+
return doc
|
126
|
+
else
|
127
|
+
errmsg('Sorry - author mess up. ' +
|
128
|
+
'No help registered for subcommand: ' +
|
129
|
+
subcmd_name + ', of command: ' +
|
130
|
+
@name)
|
131
|
+
return nil
|
132
|
+
end
|
133
|
+
else
|
134
|
+
matches = @subcmds.list.grep(/^#{key_str}/).sort
|
135
|
+
if matches.empty?
|
136
|
+
errmsg("No #{name} subcommands found matching /^#{subcmd_name}/. Try \"help #{@name}\".")
|
137
|
+
return nil
|
138
|
+
elsif 1 == matches.size
|
139
|
+
args[-1] = matches[0].to_s[keyprefix_str.size..-1]
|
140
|
+
help(args)
|
141
|
+
else
|
142
|
+
help_text = ["Subcommands of \"#{@name}\" matching /^#{subcmd_name}/:"]
|
143
|
+
help_text << columnize_commands(matches.sort)
|
144
|
+
return help_text
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
def run(args)
|
150
|
+
args = @parent.last_args if args.size == 0
|
151
|
+
if args.size < 3 || args.size == 3 && args[-1] == '*'
|
152
|
+
summary_list(obj_const(self, :NAME), @subcmds)
|
153
|
+
return false
|
154
|
+
end
|
155
|
+
|
156
|
+
subcmd_prefix = args[0..2].join('')
|
157
|
+
# We were given: cmd subcmd ...
|
158
|
+
# Run that.
|
159
|
+
subcmd = @subcmds.lookup(subcmd_prefix)
|
160
|
+
if subcmd
|
161
|
+
subcmd.run(args[2..-1])
|
162
|
+
else
|
163
|
+
undefined_subcmd(obj_const(self, :PREFIX).join(' '), args[-1])
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
end
|
168
|
+
|
169
|
+
if __FILE__ == $0
|
170
|
+
# Demo it.
|
171
|
+
require_relative '../../mock'
|
172
|
+
dbgr = MockDebugger::MockDebugger.new
|
173
|
+
# cmds = dbgr.core.processor.commands
|
174
|
+
# cmd = cmds['info']
|
175
|
+
# Trepan::SubSubcommandMgr.new(dbgr.core.processor, cmd)
|
176
|
+
# puts cmd.help(%w(help info registers))
|
177
|
+
# puts '=' * 40
|
178
|
+
# puts cmd.help(%w(help info registers *))
|
179
|
+
# puts '=' * 40
|
180
|
+
# FIXME
|
181
|
+
# require_relative '../../lib/trepanning'
|
182
|
+
# Trepan.debug(:set_restart => true)
|
183
|
+
# puts cmd.help(%w(help info registers p.*))
|
184
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
# Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
|
2
|
+
require 'rubygems'; require 'require_relative'
|
3
|
+
require_relative './base/cmd'
|
4
|
+
|
5
|
+
class Trepan::Command::SetBreakpointCommand < Trepan::Command
|
6
|
+
|
7
|
+
ALIASES = %w(b brk)
|
8
|
+
CATEGORY = 'breakpoints'
|
9
|
+
NAME = File.basename(__FILE__, '.rb')
|
10
|
+
HELP = <<-HELP
|
11
|
+
#{NAME}
|
12
|
+
#{NAME} [line number|offset]
|
13
|
+
#{NAME} Class[.#]method[:line-or-offset]
|
14
|
+
|
15
|
+
Sets a breakpoint. In the first form, a breakpoint is set at the
|
16
|
+
current line you are stopped at. In the second form, you give a line
|
17
|
+
number or an offset. An offset is a number that is prefaced with 'O'
|
18
|
+
or 'o' and represents a Rubinius VM PC offset.
|
19
|
+
|
20
|
+
The current method name is used for the start of the search. If a line
|
21
|
+
number is given and the line number is not found in that method,
|
22
|
+
enclosing scopes are searched for the line.
|
23
|
+
|
24
|
+
The last form is the most explicit. Use '#' to specify an instance
|
25
|
+
method and '.' to specify a class method. If a line number or offset
|
26
|
+
is omitted, we use the first line of the method.
|
27
|
+
|
28
|
+
Examples:
|
29
|
+
|
30
|
+
#{NAME} # set breakpoint at the current line
|
31
|
+
#{NAME} 5 # set breakpoint on line 5
|
32
|
+
#{NAME} O5 # set breakpoint at offset 5
|
33
|
+
#{NAME} o5 # same as above
|
34
|
+
#{NAME} Array#pop::3 # Set break at instance method 'pop' in Array, line 3
|
35
|
+
#{NAME} Trepan.start:3 # Set break in class method 'start' of Trepan, line 3
|
36
|
+
#{NAME} Trepan.start:o3 # Same as above but at offset 3, not line 3.
|
37
|
+
#{NAME} Trepan.start # Set break in class method 'start' of Trepan
|
38
|
+
|
39
|
+
See also 'tbreak', 'info breakpoint', and 'delete'.
|
40
|
+
HELP
|
41
|
+
SHORT_HELP = 'Set a breakpoint at a point in a method'
|
42
|
+
|
43
|
+
def run(args, temp=false)
|
44
|
+
arg_str = args[1..-1].join(' ')
|
45
|
+
|
46
|
+
describe, klass_name, which, name, line, ip =
|
47
|
+
@proc.breakpoint_position(args[1..-1])
|
48
|
+
event = temp ? 'tbrkpt' : 'brkpt'
|
49
|
+
opts={:event => event, :temp => temp}
|
50
|
+
if name.kind_of?(Rubinius::CompiledMethod)
|
51
|
+
bp = @proc.set_breakpoint_method(describe, name, line, ip, opts)
|
52
|
+
else
|
53
|
+
return unless klass_name
|
54
|
+
|
55
|
+
begin
|
56
|
+
klass = @proc.debug_eval(klass_name, settings[:maxstring])
|
57
|
+
rescue NameError
|
58
|
+
errmsg "Unable to find class/module: #{klass_name}"
|
59
|
+
ask_deferred klass_name, which, name, line
|
60
|
+
return
|
61
|
+
end
|
62
|
+
|
63
|
+
begin
|
64
|
+
if which == "#"
|
65
|
+
method = klass.instance_method(name)
|
66
|
+
else
|
67
|
+
method = klass.method(name)
|
68
|
+
end
|
69
|
+
rescue NameError
|
70
|
+
errmsg "Unable to find method '#{name}' in #{klass}"
|
71
|
+
ask_deferred klass_name, which, name, line
|
72
|
+
return
|
73
|
+
end
|
74
|
+
|
75
|
+
bp = @proc.set_breakpoint_method(arg_str.strip, method, line, ip, opts)
|
76
|
+
end
|
77
|
+
|
78
|
+
bp.set_temp! if temp
|
79
|
+
return bp
|
80
|
+
end
|
81
|
+
|
82
|
+
def ask_deferred(klass_name, which, name, line)
|
83
|
+
if confirm('Would you like to defer this breakpoint to later?', false)
|
84
|
+
@proc.dbgr.add_deferred_breakpoint(klass_name, which, name, line)
|
85
|
+
msg 'Deferred breakpoint created.'
|
86
|
+
else
|
87
|
+
msg 'Not confirmed.'
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
if __FILE__ == $0
|
93
|
+
require_relative '../mock'
|
94
|
+
dbgr, cmd = MockDebugger::setup
|
95
|
+
cmd.run([cmd.name])
|
96
|
+
# require 'trepanning'
|
97
|
+
# Trepan.start(:set_restart => true)
|
98
|
+
cmd.run([cmd.name, __LINE__.to_s])
|
99
|
+
cmd.run([cmd.name, 'foo'])
|
100
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'rubygems'; require 'require_relative'
|
2
|
+
require_relative 'base/cmd'
|
3
|
+
require_relative '../stepping'
|
4
|
+
|
5
|
+
class Trepan::Command::ContinueCommand < Trepan::Command
|
6
|
+
NAME = File.basename(__FILE__, '.rb')
|
7
|
+
HELP = <<-HELP
|
8
|
+
#{NAME} [breakpoint position]
|
9
|
+
|
10
|
+
Leave the debugger loop and continue execution. Subsequent entry to
|
11
|
+
the debugger however may occur via breakpoints or explicit calls, or
|
12
|
+
exceptions.
|
13
|
+
|
14
|
+
If a parameter is given, a temporary breakpoint is set at that position
|
15
|
+
before continuing.
|
16
|
+
|
17
|
+
Examples:
|
18
|
+
#{NAME}
|
19
|
+
#{NAME} 10 # continue to line 10
|
20
|
+
|
21
|
+
See also 'step', 'next', and 'nexti' commands.
|
22
|
+
HELP
|
23
|
+
ALIASES = %w(c cont)
|
24
|
+
CATEGORY = 'running'
|
25
|
+
MAX_ARGS = 1
|
26
|
+
NEED_RUNNING = true
|
27
|
+
SHORT_HELP = 'Continue execution of the debugged program'
|
28
|
+
|
29
|
+
# This is the method that runs the command
|
30
|
+
def run(args)
|
31
|
+
|
32
|
+
## FIXME: DRY this code, tbreak and break.
|
33
|
+
unless args.size == 1
|
34
|
+
describe, klass_name, which, name, line, ip =
|
35
|
+
@proc.breakpoint_position(args[1..-1])
|
36
|
+
unless describe
|
37
|
+
errmsg "Can't parse temporary breakpoint location"
|
38
|
+
return
|
39
|
+
end
|
40
|
+
if name.kind_of?(Rubinius::CompiledMethod)
|
41
|
+
bp = @proc.set_breakpoint_method(describe, name, line, ip,
|
42
|
+
{:temp=>true, :event =>'tbrkpt'})
|
43
|
+
unless bp
|
44
|
+
errmsg "Trouble setting temporary breakpoint"
|
45
|
+
return
|
46
|
+
end
|
47
|
+
else
|
48
|
+
return unless klass_name
|
49
|
+
begin
|
50
|
+
klass = @proc.debug_eval(klass_name, settings[:maxstring])
|
51
|
+
rescue NameError
|
52
|
+
errmsg "Unable to find class/module: #{klass_name}"
|
53
|
+
return
|
54
|
+
end
|
55
|
+
|
56
|
+
begin
|
57
|
+
if which == "#"
|
58
|
+
method = klass.instance_method(name)
|
59
|
+
else
|
60
|
+
method = klass.method(name)
|
61
|
+
end
|
62
|
+
rescue NameError
|
63
|
+
errmsg "Unable to find method '#{name}' in #{klass}"
|
64
|
+
return
|
65
|
+
end
|
66
|
+
arg_str = args[1..-1].join(' ')
|
67
|
+
bp = @proc.set_breakpoint_method(arg_str.strip, method, line, nil,
|
68
|
+
{:temp=>true, :event =>'tbrkpt'})
|
69
|
+
unless bp
|
70
|
+
errmsg "Trouble setting temporary breakpoint"
|
71
|
+
return
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
@proc.continue('continue')
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
if __FILE__ == $0
|
80
|
+
require_relative '../mock'
|
81
|
+
dbgr, cmd = MockDebugger::setup
|
82
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'rubygems'; require 'require_relative'
|
2
|
+
require_relative './base/cmd'
|
3
|
+
|
4
|
+
class Trepan::Command::DeleteBreakpontCommand < Trepan::Command
|
5
|
+
CATEGORY = 'breakpoints'
|
6
|
+
NAME = File.basename(__FILE__, '.rb')
|
7
|
+
SHORT_HELP = 'Delete a breakpoint'
|
8
|
+
HELP = <<-HELP
|
9
|
+
Specify the breakpoint by number, use 'info break' to see the numbers
|
10
|
+
HELP
|
11
|
+
|
12
|
+
def run(args)
|
13
|
+
if args.size != 2
|
14
|
+
errmsg 'Please specify which breakpoint by number'
|
15
|
+
return
|
16
|
+
end
|
17
|
+
|
18
|
+
begin
|
19
|
+
i = Integer(args[1])
|
20
|
+
rescue ArgumentError
|
21
|
+
errmsg "'#{args}' is not a number"
|
22
|
+
return
|
23
|
+
end
|
24
|
+
|
25
|
+
if @proc.delete_breakpoint_by_number(i)
|
26
|
+
msg('Deleted breakpoint %d.' % i)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|