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,128 @@
|
|
1
|
+
# Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
|
2
|
+
require 'rubygems'
|
3
|
+
require 'linecache'
|
4
|
+
require_relative 'disassemble'
|
5
|
+
require_relative 'msg'
|
6
|
+
require_relative 'frame'
|
7
|
+
class Trepan
|
8
|
+
class CmdProcessor
|
9
|
+
attr_accessor :reload_on_change
|
10
|
+
|
11
|
+
def location_initialize
|
12
|
+
@reload_on_change = nil
|
13
|
+
end
|
14
|
+
|
15
|
+
def resolve_file_with_dir(path_suffix)
|
16
|
+
settings[:directory].split(/:/).each do |dir|
|
17
|
+
dir =
|
18
|
+
if '$cwd' == dir
|
19
|
+
Dir.pwd
|
20
|
+
elsif '$cdir' == dir
|
21
|
+
Rubinius::OS_STARTUP_DIR
|
22
|
+
else
|
23
|
+
dir
|
24
|
+
end
|
25
|
+
next unless dir && File.directory?(dir)
|
26
|
+
try_file = File.join(dir, path_suffix)
|
27
|
+
return try_file if File.readable?(try_file)
|
28
|
+
end
|
29
|
+
nil
|
30
|
+
end
|
31
|
+
|
32
|
+
# Get line +line_number+ from file named +filename+. Return "\n"
|
33
|
+
# there was a problem. Leading blanks are stripped off.
|
34
|
+
def line_at(filename, line_number)
|
35
|
+
# We use linecache first to give precidence to user-remapped
|
36
|
+
# file names
|
37
|
+
line = LineCache::getline(filename, line_number, @reload_on_change)
|
38
|
+
unless line
|
39
|
+
# Try using search directories (set with command "directory")
|
40
|
+
if filename[0..0] != File::SEPARATOR
|
41
|
+
try_filename = resolve_file_with_dir(filename)
|
42
|
+
if try_filename &&
|
43
|
+
line = LineCache::getline(try_filename, line_number,
|
44
|
+
@reload_on_change)
|
45
|
+
LineCache::remap_file(filename, try_filename)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
return nil unless line
|
50
|
+
return line.lstrip.chomp
|
51
|
+
end
|
52
|
+
|
53
|
+
def loc_and_text(loc)
|
54
|
+
vm_location = @frame.vm_location
|
55
|
+
filename = vm_location.method.active_path
|
56
|
+
line_no = vm_location.line
|
57
|
+
static = vm_location.static_scope
|
58
|
+
|
59
|
+
if @frame.eval?
|
60
|
+
file = LineCache::map_script(static.script)
|
61
|
+
text = LineCache::getline(static.script, line_no)
|
62
|
+
loc += " remapped #{canonic_file(file)}:#{line_no}"
|
63
|
+
else
|
64
|
+
text = line_at(filename, line_no)
|
65
|
+
map_file, map_line = LineCache::map_file_line(filename, line_no)
|
66
|
+
if [filename, line_no] != [map_file, map_line]
|
67
|
+
loc += " remapped #{canonic_file(map_file)}:#{map_line}"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
[loc, line_no, text]
|
72
|
+
end
|
73
|
+
|
74
|
+
def print_location
|
75
|
+
# if %w(c-call call).member?(@event)
|
76
|
+
# # FIXME: Fix Ruby so we don't need this workaround?
|
77
|
+
# # See also where.rb
|
78
|
+
# opts = {}
|
79
|
+
# opts[:class] = @core.hook_arg if
|
80
|
+
# 'CFUNC' == @frame.type && @core.hook_arg && 0 == @frame_index
|
81
|
+
# msg format_stack_call(@frame, opts)
|
82
|
+
# elsif 'raise' == @core.event
|
83
|
+
# msg @core.hook_arg.inspect if @core.hook_arg # Exception object
|
84
|
+
# end
|
85
|
+
|
86
|
+
text = nil
|
87
|
+
# source_container = frame_container(@frame, false)
|
88
|
+
ev = if @event.nil? || 0 != @frame_index
|
89
|
+
' '
|
90
|
+
else
|
91
|
+
(EVENT2ICON[@event] || @event)
|
92
|
+
end
|
93
|
+
|
94
|
+
@line_no = @frame.vm_location.line
|
95
|
+
|
96
|
+
loc = source_location_info
|
97
|
+
loc, @line_no, text = loc_and_text(loc)
|
98
|
+
ip_str = frame.method ? " @#{frame.next_ip}" : ''
|
99
|
+
|
100
|
+
msg "#{ev} (#{loc}#{ip_str})"
|
101
|
+
|
102
|
+
# if %w(return c-return).member?(@core.event)
|
103
|
+
# retval = Trepan::Frame.value_returned(@frame, @core.event)
|
104
|
+
# msg 'R=> %s' % retval.inspect
|
105
|
+
# end
|
106
|
+
|
107
|
+
if text && !text.strip.empty?
|
108
|
+
msg text
|
109
|
+
@line_no -= 1
|
110
|
+
else
|
111
|
+
show_bytecode
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def source_location_info
|
116
|
+
filename = @frame.vm_location.method.active_path
|
117
|
+
canonic_filename =
|
118
|
+
if @frame.eval?
|
119
|
+
'eval ' + safe_repr(@frame.eval_string.gsub("\n", ';').inspect, 20)
|
120
|
+
else
|
121
|
+
canonic_file(filename)
|
122
|
+
end
|
123
|
+
loc = "#{canonic_filename}:#{@frame.vm_location.line}"
|
124
|
+
return loc
|
125
|
+
end
|
126
|
+
|
127
|
+
end
|
128
|
+
end
|
data/processor/main.rb
ADDED
@@ -0,0 +1,394 @@
|
|
1
|
+
# Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
|
2
|
+
# The main "driver" class for a command processor. Other parts of the
|
3
|
+
# command class and debugger command objects are pulled in from here.
|
4
|
+
|
5
|
+
require 'set'
|
6
|
+
require 'pathname' # For cleanpath
|
7
|
+
|
8
|
+
require 'rubygems'; require 'require_relative'
|
9
|
+
## %w(default display eventbuf eval load_cmds location frame hook msg
|
10
|
+
## validate).each do
|
11
|
+
%w(default breakpoint disassemble eval load_cmds location frame hook msg
|
12
|
+
running stepping validate).each do
|
13
|
+
|mod_str|
|
14
|
+
require_relative mod_str
|
15
|
+
end
|
16
|
+
## require_relative '../app/brkptmgr'
|
17
|
+
|
18
|
+
class Trepan
|
19
|
+
class CmdProcessor
|
20
|
+
|
21
|
+
# SEE ALSO attr's in require_relative's of loop above.
|
22
|
+
|
23
|
+
attr_reader :cmd_name # command name before alias or macro resolution
|
24
|
+
attr_reader :cmd_argstr # Current command args, a String.
|
25
|
+
# This is current_command with the command
|
26
|
+
# name removed from the beginning.
|
27
|
+
## attr_reader :core # Trepan core object
|
28
|
+
attr_reader :current_command # Current command getting run, a String.
|
29
|
+
attr_accessor :dbgr # Trepan instance (via
|
30
|
+
# Trepan::Core instance)
|
31
|
+
## FIXME 1.9.2 has attr_reader !
|
32
|
+
attr_accessor :debug_nest # Number of nested debugs. Used in showing
|
33
|
+
# prompt.
|
34
|
+
attr_accessor :different_pos # Same type as settings[:different]
|
35
|
+
# this is the temporary value for the
|
36
|
+
# next stop while settings is the default
|
37
|
+
# value to use.
|
38
|
+
attr_accessor :event # Stop event
|
39
|
+
attr_accessor :leave_cmd_loop # Commands set this to signal to leave
|
40
|
+
# the command loop (which often continues to
|
41
|
+
# run the debugged program).
|
42
|
+
attr_accessor :line_no # Last line shown in "list" command
|
43
|
+
attr_accessor :next_thread # Thread. If non-nil then in
|
44
|
+
# stepping the thread has to be
|
45
|
+
# this thread.
|
46
|
+
attr_accessor :pass_exception # Pass an exception back
|
47
|
+
attr_accessor :prompt # String print before requesting input
|
48
|
+
attr_reader :settings # Hash[:symbol] of command
|
49
|
+
# processor settings
|
50
|
+
attr_reader :step_bp
|
51
|
+
|
52
|
+
# The following are used in to force stopping at a different line
|
53
|
+
# number. FIXME: could generalize to a position object.
|
54
|
+
attr_accessor :last_pos # Last position. 6-Tuple: of
|
55
|
+
# [location, container, stack_size,
|
56
|
+
# current_thread, pc_offset]
|
57
|
+
|
58
|
+
|
59
|
+
unless defined?(EVENT2ICON)
|
60
|
+
# Event icons used in printing locations.
|
61
|
+
EVENT2ICON = {
|
62
|
+
'brkpt' => 'xx',
|
63
|
+
'tbrkpt' => 'x1',
|
64
|
+
'c-call' => 'C>',
|
65
|
+
'c-return' => '<C',
|
66
|
+
'step-call' => '->',
|
67
|
+
'call' => '->',
|
68
|
+
'class' => '::',
|
69
|
+
'coverage' => '[]',
|
70
|
+
'debugger-call' => ':o',
|
71
|
+
'end' => '-|',
|
72
|
+
'line' => '--',
|
73
|
+
'raise' => '!!',
|
74
|
+
'return' => '<-',
|
75
|
+
'start' => '>>',
|
76
|
+
'start' => '>>',
|
77
|
+
'switch' => 'sw',
|
78
|
+
'trace-var' => '$V',
|
79
|
+
'unknown' => '?!',
|
80
|
+
'vm' => 'VM',
|
81
|
+
'vm-insn' => '..',
|
82
|
+
}
|
83
|
+
# These events are important enough event that we always want to
|
84
|
+
# stop on them.
|
85
|
+
UNMASKABLE_EVENTS = Set.new(['end', 'raise', 'unknown'])
|
86
|
+
end
|
87
|
+
|
88
|
+
def initialize(dbgr, settings={})
|
89
|
+
@dbgr = dbgr
|
90
|
+
@debug_nest = 1
|
91
|
+
@hidelevels = {}
|
92
|
+
@last_command = nil
|
93
|
+
@last_pos = [nil, nil, nil, nil, nil, nil]
|
94
|
+
@next_thread = nil
|
95
|
+
@user_variables = 0
|
96
|
+
|
97
|
+
|
98
|
+
start_cmds = settings.delete(:start_cmds)
|
99
|
+
start_file = settings.delete(:start_file)
|
100
|
+
|
101
|
+
@settings = settings.merge(DEFAULT_SETTINGS)
|
102
|
+
@different_pos = @settings[:different]
|
103
|
+
|
104
|
+
# FIXME: Rework using a general "set substitute file" command and
|
105
|
+
# a global default profile which gets read.
|
106
|
+
prelude_file = File.expand_path(File.join(File.dirname(__FILE__),
|
107
|
+
%w(.. data prelude.rb)))
|
108
|
+
|
109
|
+
## Start with empty thread and frame info.
|
110
|
+
frame_teardown
|
111
|
+
|
112
|
+
# Run initialization routines for each of the "submodule"s.
|
113
|
+
# load_cmds has to come first.
|
114
|
+
## %w(load_cmds breakpoint display eventbuf frame running validate
|
115
|
+
## ).each do |submod|
|
116
|
+
%w(load_cmds breakpoint frame running validate).each do |submod|
|
117
|
+
self.send("#{submod}_initialize")
|
118
|
+
end
|
119
|
+
hook_initialize(commands)
|
120
|
+
end
|
121
|
+
|
122
|
+
def canonic_container(container)
|
123
|
+
[container[0], canonic_file(container[1])]
|
124
|
+
end
|
125
|
+
|
126
|
+
def canonic_file(filename)
|
127
|
+
# For now we want resolved filenames
|
128
|
+
@settings[:basename] ? File.basename(filename) :
|
129
|
+
# Cache this?
|
130
|
+
Pathname.new(filename).cleanpath.to_s
|
131
|
+
end
|
132
|
+
|
133
|
+
def compute_prompt
|
134
|
+
th = @current_thread
|
135
|
+
thread_str =
|
136
|
+
if 2 == Thread.list.size
|
137
|
+
''
|
138
|
+
elsif th == Thread.main
|
139
|
+
'@main'
|
140
|
+
else
|
141
|
+
"@#{th.current.object_id}"
|
142
|
+
end
|
143
|
+
"%s#{settings[:prompt]}%s%s: " %
|
144
|
+
['(' * @debug_nest, thread_str, ')' * @debug_nest]
|
145
|
+
|
146
|
+
end
|
147
|
+
|
148
|
+
# Check that we meed the criteria that cmd specifies it needs
|
149
|
+
def ok_for_running(cmd, name, nargs)
|
150
|
+
# TODO check execution_set against execution status.
|
151
|
+
# Check we have frame is not null
|
152
|
+
min_args = cmd.class.const_get(:MIN_ARGS)
|
153
|
+
if nargs < min_args
|
154
|
+
errmsg(("Command '%s' needs at least %d argument(s); " +
|
155
|
+
"got %d.") % [name, min_args, nargs])
|
156
|
+
return false
|
157
|
+
end
|
158
|
+
max_args = cmd.class.const_get(:MAX_ARGS)
|
159
|
+
if max_args and nargs > max_args
|
160
|
+
errmsg(("Command '%s' needs at most %d argument(s); " +
|
161
|
+
"got %d.") % [name, max_args, nargs])
|
162
|
+
return false
|
163
|
+
end
|
164
|
+
# if cmd.class.const_get(:NEED_RUNNING) && !...
|
165
|
+
# errmsg "Command '%s' requires a running program." % name
|
166
|
+
# return false
|
167
|
+
# end
|
168
|
+
|
169
|
+
if cmd.class.const_get(:NEED_STACK) && !@frame
|
170
|
+
errmsg "Command '%s' requires a running stack frame." % name
|
171
|
+
return false
|
172
|
+
end
|
173
|
+
|
174
|
+
return true
|
175
|
+
end
|
176
|
+
|
177
|
+
# Run one debugger command. True is returned if we want to quit.
|
178
|
+
def process_command_and_quit?()
|
179
|
+
intf = @dbgr.intf
|
180
|
+
return true if intf[-1].input.eof? && intf.size == 1
|
181
|
+
while !intf[-1].input.eof? || intf.size > 1
|
182
|
+
begin
|
183
|
+
@current_command = read_command().strip
|
184
|
+
if @current_command.empty?
|
185
|
+
if @last_command && intf[-1].interactive?
|
186
|
+
@current_command = @last_command
|
187
|
+
else
|
188
|
+
next
|
189
|
+
end
|
190
|
+
end
|
191
|
+
next if @current_command[0..0] == '#' # Skip comment lines
|
192
|
+
break
|
193
|
+
rescue IOError, Errno::EPIPE
|
194
|
+
if @dbgr.intf.size > 1
|
195
|
+
@dbgr.intf.pop
|
196
|
+
@last_command = nil
|
197
|
+
print_location
|
198
|
+
else
|
199
|
+
msg "That's all folks..."
|
200
|
+
## FIXME: think of something better.
|
201
|
+
quit('exit!')
|
202
|
+
return true
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
206
|
+
leave_cmdloop = run_command(@current_command)
|
207
|
+
|
208
|
+
# Save it to the history.
|
209
|
+
@dbgr.history_io.puts @last_command
|
210
|
+
end
|
211
|
+
|
212
|
+
def after_cmdloop
|
213
|
+
@cmdloop_posthooks.run
|
214
|
+
end
|
215
|
+
|
216
|
+
def before_cmdloop
|
217
|
+
|
218
|
+
frame_setup
|
219
|
+
|
220
|
+
@unconditional_prehooks.run
|
221
|
+
if breakpoint?
|
222
|
+
delete_breakpoint(@brkpt) if @brkpt.temp?
|
223
|
+
@last_pos = [@frame.vm_location, @stack_size, @current_thread, @event]
|
224
|
+
else
|
225
|
+
if stepping_skip? # || @stack_size <= @hide_level
|
226
|
+
step(@return_to_program, @step_count)
|
227
|
+
return true
|
228
|
+
elsif @event == 'start'
|
229
|
+
step('step', 0)
|
230
|
+
return true
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
@prompt = "(#{@settings[:prompt]}): " # compute_prompt
|
235
|
+
|
236
|
+
@leave_cmd_loop = false
|
237
|
+
print_location unless @settings[:traceprint]
|
238
|
+
# if 'trace-var' == @event
|
239
|
+
# msg "Note: we are stopped *after* the above location."
|
240
|
+
# end
|
241
|
+
|
242
|
+
# @eventbuf.add_mark if @settings[:tracebuffer]
|
243
|
+
|
244
|
+
@return_to_program = false
|
245
|
+
@cmdloop_prehooks.run
|
246
|
+
return false
|
247
|
+
end
|
248
|
+
|
249
|
+
|
250
|
+
# This is the main entry point.
|
251
|
+
def process_commands
|
252
|
+
skip_command = before_cmdloop
|
253
|
+
while not @leave_cmd_loop do
|
254
|
+
begin
|
255
|
+
if !skip_command
|
256
|
+
break if process_command_and_quit?()
|
257
|
+
end
|
258
|
+
if @return_to_program
|
259
|
+
after_cmdloop
|
260
|
+
if @step_count >= 0
|
261
|
+
@step_bp = step_over_by(1)
|
262
|
+
run_command('disassemble') if settings[:debugstep]
|
263
|
+
dbgr.listen('step' == @return_to_program)
|
264
|
+
else
|
265
|
+
@step_bp = nil
|
266
|
+
dbgr.listen
|
267
|
+
end
|
268
|
+
skip_command = before_cmdloop
|
269
|
+
end
|
270
|
+
rescue SystemExit
|
271
|
+
## @dbgr.stop
|
272
|
+
raise
|
273
|
+
rescue Exception => exc
|
274
|
+
errmsg("Internal debugger error: #{exc.inspect}")
|
275
|
+
exception_dump(exc, @settings[:debugexcept], $!.backtrace)
|
276
|
+
end
|
277
|
+
end
|
278
|
+
after_cmdloop
|
279
|
+
end
|
280
|
+
|
281
|
+
# Run current_command, a String. @last_command is set after the
|
282
|
+
# command is run if it is a command.
|
283
|
+
def run_command(current_command)
|
284
|
+
eval_command =
|
285
|
+
if current_command[0..0] == '!'
|
286
|
+
current_command[0] = ''
|
287
|
+
else
|
288
|
+
false
|
289
|
+
end
|
290
|
+
|
291
|
+
unless eval_command
|
292
|
+
# Expand macros. FIXME: put in a procedure
|
293
|
+
args = current_command.split
|
294
|
+
while true do
|
295
|
+
macro_cmd_name = args[0]
|
296
|
+
return false if args.size == 0
|
297
|
+
break unless @macros.member?(macro_cmd_name)
|
298
|
+
current_command = @macros[macro_cmd_name].call(*args[1..-1])
|
299
|
+
msg current_command if settings[:debugmacro]
|
300
|
+
if current_command.is_a?(Array) &&
|
301
|
+
current_command.any {|val| !val.is_a?(String)}
|
302
|
+
args = current_command
|
303
|
+
elsif current_command.is_a?(String)
|
304
|
+
args = current_command.split
|
305
|
+
else
|
306
|
+
errmsg("macro #{macro_cmd_name} should return an Array " +
|
307
|
+
"of Strings or a String. Got #{current_command.inspect}")
|
308
|
+
return false
|
309
|
+
end
|
310
|
+
end
|
311
|
+
|
312
|
+
@cmd_name = args[0]
|
313
|
+
run_cmd_name =
|
314
|
+
if @aliases.member?(@cmd_name)
|
315
|
+
@aliases[@cmd_name]
|
316
|
+
else
|
317
|
+
@cmd_name
|
318
|
+
end
|
319
|
+
|
320
|
+
if @commands.member?(run_cmd_name)
|
321
|
+
cmd = @commands[run_cmd_name]
|
322
|
+
if ok_for_running(cmd, run_cmd_name, args.size-1)
|
323
|
+
@cmd_argstr = current_command[@cmd_name.size..-1].lstrip
|
324
|
+
cmd.run(args)
|
325
|
+
@last_command = current_command
|
326
|
+
end
|
327
|
+
return false
|
328
|
+
end
|
329
|
+
end
|
330
|
+
|
331
|
+
# Eval anything that's not a command or has been
|
332
|
+
# requested to be eval'd
|
333
|
+
if settings[:autoeval] || eval_command
|
334
|
+
eval_code(current_command, @settings[:maxstring])
|
335
|
+
else
|
336
|
+
undefined_command(cmd_name)
|
337
|
+
end
|
338
|
+
return false
|
339
|
+
end
|
340
|
+
|
341
|
+
# Error message when a command doesn't exist
|
342
|
+
def undefined_command(cmd_name)
|
343
|
+
errmsg('Undefined command: "%s". Try "help".' % cmd_name)
|
344
|
+
end
|
345
|
+
|
346
|
+
# FIXME: Allow access to both Trepan::CmdProcessor and Trepan
|
347
|
+
# for index [] and []=.
|
348
|
+
# If there is a Trepan::CmdProcessor setting that would take precidence.
|
349
|
+
# def settings
|
350
|
+
# @settings.merge(@dbgr.settings) # wrong because this doesn't allow []=
|
351
|
+
# end
|
352
|
+
end
|
353
|
+
end
|
354
|
+
|
355
|
+
if __FILE__ == $0
|
356
|
+
$0 = 'foo' # So we don't get here again
|
357
|
+
require_relative '../lib/trepanning'
|
358
|
+
dbg = Trepan.new(:nx => true)
|
359
|
+
cmdproc = dbg.instance_variable_get('@processor')
|
360
|
+
cmdproc.msg('I am main')
|
361
|
+
cmdproc.errmsg('Whoa!')
|
362
|
+
cmds = cmdproc.commands
|
363
|
+
p cmdproc.aliases
|
364
|
+
p cmdproc.commands.keys.sort
|
365
|
+
cmd_name, cmd_obj = cmds.first
|
366
|
+
puts cmd_obj.class.const_get(:HELP)
|
367
|
+
puts cmd_obj.class.const_get(:SHORT_HELP)
|
368
|
+
|
369
|
+
cmdproc.instance_variable_set('@current_thread', Thread.current)
|
370
|
+
puts cmdproc.compute_prompt
|
371
|
+
Thread.new{ puts cmdproc.compute_prompt }.join
|
372
|
+
|
373
|
+
x = Thread.new{ Thread.pass; x = 1 }
|
374
|
+
puts cmdproc.compute_prompt
|
375
|
+
x.join
|
376
|
+
cmdproc.debug_nest += 1
|
377
|
+
puts cmdproc.compute_prompt
|
378
|
+
|
379
|
+
# if ARGV.size > 0
|
380
|
+
# cmdproc.msg('Enter "q" to quit')
|
381
|
+
# cmdproc.process_commands
|
382
|
+
# else
|
383
|
+
# $input = []
|
384
|
+
# class << cmdproc
|
385
|
+
# def read_command
|
386
|
+
# $input.shift
|
387
|
+
# end
|
388
|
+
# end
|
389
|
+
# $input = ['1+2']
|
390
|
+
# cmdproc.process_command_and_quit?
|
391
|
+
# $input = ['!s = 5'] # ! means eval line
|
392
|
+
# cmdproc.process_command_and_quit?
|
393
|
+
# end
|
394
|
+
end
|
data/processor/mock.rb
ADDED
@@ -0,0 +1,137 @@
|
|
1
|
+
# Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
|
2
|
+
# Mock setup for commands.
|
3
|
+
require 'rubygems'; require 'require_relative'
|
4
|
+
|
5
|
+
require_relative 'main'
|
6
|
+
|
7
|
+
# require_relative '../app/core'
|
8
|
+
require_relative '../app/default'
|
9
|
+
require_relative '../app/frame'
|
10
|
+
require_relative '../interface/user' # user interface (includes I/O)
|
11
|
+
|
12
|
+
module MockDebugger
|
13
|
+
class MockDebugger
|
14
|
+
attr_accessor :trace_filter # Procs/Methods we ignore.
|
15
|
+
|
16
|
+
attr_accessor :frame # Actually a "Rubinius::Location object
|
17
|
+
attr_accessor :core # access to Debugger::Core instance
|
18
|
+
attr_accessor :intf # The way the outside world interfaces with us.
|
19
|
+
attr_reader :initial_dir # String. Current directory when program
|
20
|
+
# started. Used in restart program.
|
21
|
+
attr_accessor :restart_argv # How to restart us, empty or nil.
|
22
|
+
# Note restart[0] is typically $0.
|
23
|
+
attr_reader :settings # Hash[:symbol] of things you can configure
|
24
|
+
attr_accessor :processor
|
25
|
+
|
26
|
+
# FIXME: move more stuff of here and into Trepan::CmdProcessor
|
27
|
+
# These below should go into Trepan::CmdProcessor.
|
28
|
+
attr_reader :cmd_argstr, :cmd_name, :vm_locations, :current_frame,
|
29
|
+
:debugee_thread
|
30
|
+
|
31
|
+
def initialize(settings={})
|
32
|
+
@before_cmdloop_hooks = []
|
33
|
+
@settings = Trepanning::DEFAULT_SETTINGS.merge(settings)
|
34
|
+
@intf = [Trepan::UserInterface.new]
|
35
|
+
@vm_locations = Rubinius::VM.backtrace(1, true)
|
36
|
+
@current_frame = Trepan::Frame.new(self, 0, @vm_locations[0])
|
37
|
+
@debugee_thread = Thread.current
|
38
|
+
@frames = []
|
39
|
+
@restart_argv = Rubinius::OS_STARTUP_DIR
|
40
|
+
|
41
|
+
## @core = Trepan::Core.new(self)
|
42
|
+
@trace_filter = []
|
43
|
+
|
44
|
+
# Don't allow user commands in mocks.
|
45
|
+
## @core.processor.settings[:user_cmd_dir] = nil
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
def frame(num)
|
50
|
+
@frames[num] ||= Trepan::Frame.new(self, num, @vm_locations[num])
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# Common Mock debugger setup
|
55
|
+
def setup(name=nil, show_constants=true)
|
56
|
+
unless name
|
57
|
+
loc = Rubinius::VM.backtrace(1, true)[0]
|
58
|
+
name = File.basename(loc.file, '.rb')
|
59
|
+
end
|
60
|
+
|
61
|
+
if ARGV.size > 0 && ARGV[0] == 'debug'
|
62
|
+
require_relative '../lib/trepanning'
|
63
|
+
dbgr = Trepan.new
|
64
|
+
dbgr.debugger
|
65
|
+
else
|
66
|
+
dbgr = MockDebugger.new
|
67
|
+
end
|
68
|
+
|
69
|
+
cmdproc = Trepan::CmdProcessor.new(dbgr)
|
70
|
+
cmdproc.frame = dbgr.frame(0)
|
71
|
+
dbgr.processor = cmdproc
|
72
|
+
|
73
|
+
cmdproc.load_cmds_initialize
|
74
|
+
cmds = cmdproc.commands
|
75
|
+
cmd = cmds[name]
|
76
|
+
cmd.proc.frame_setup
|
77
|
+
show_special_class_constants(cmd) if show_constants
|
78
|
+
|
79
|
+
def cmd.msg(message)
|
80
|
+
puts message
|
81
|
+
end
|
82
|
+
def cmd.msg_nocr(message)
|
83
|
+
print message
|
84
|
+
end
|
85
|
+
def cmd.errmsg(message)
|
86
|
+
puts "Error: #{message}"
|
87
|
+
end
|
88
|
+
def cmd.confirm(prompt, default)
|
89
|
+
true
|
90
|
+
end
|
91
|
+
|
92
|
+
return dbgr, cmd
|
93
|
+
end
|
94
|
+
module_function :setup
|
95
|
+
|
96
|
+
def sub_setup(sub_class, run=true)
|
97
|
+
sub_name = sub_class.const_get('PREFIX')
|
98
|
+
dbgr, cmd = setup(sub_name[0], false)
|
99
|
+
sub_cmd = sub_class.new(cmd)
|
100
|
+
sub_cmd.summary_help(sub_cmd.name)
|
101
|
+
puts
|
102
|
+
sub_cmd.run([cmd.name]) if run
|
103
|
+
return sub_cmd
|
104
|
+
end
|
105
|
+
module_function :sub_setup
|
106
|
+
|
107
|
+
def subsub_setup(sub_class, subsub_class, run=true)
|
108
|
+
subsub_name = subsub_class.const_get('PREFIX')
|
109
|
+
dbgr, cmd = setup(subsub_name[0], false)
|
110
|
+
sub_cmd = sub_class.new(dbgr.processor, cmd)
|
111
|
+
subsub_cmd = subsub_class.new(cmd.proc, sub_cmd, subsub_name.join(''))
|
112
|
+
subsub_cmd.run([subsub_cmd.name]) if run
|
113
|
+
return subsub_cmd
|
114
|
+
end
|
115
|
+
module_function :subsub_setup
|
116
|
+
|
117
|
+
def show_special_class_constants(cmd)
|
118
|
+
puts 'ALIASES: %s' % [cmd.class.const_get('ALIASES').inspect] if
|
119
|
+
cmd.class.constants.member?(:ALIASES)
|
120
|
+
%w(CATEGORY MIN_ARGS MAX_ARGS
|
121
|
+
NAME NEED_STACK SHORT_HELP).each do |name|
|
122
|
+
puts '%s: %s' % [name, cmd.class.const_get(name).inspect]
|
123
|
+
end
|
124
|
+
puts '-' * 30
|
125
|
+
puts cmd.class.const_get('HELP')
|
126
|
+
puts '=' * 30
|
127
|
+
end
|
128
|
+
module_function :show_special_class_constants
|
129
|
+
|
130
|
+
end
|
131
|
+
|
132
|
+
if __FILE__ == $0
|
133
|
+
dbgr = MockDebugger::MockDebugger.new
|
134
|
+
p dbgr.settings
|
135
|
+
puts '=' * 10
|
136
|
+
# p dbgr.core.processor.settings
|
137
|
+
end
|
data/processor/msg.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
|
2
|
+
# I/O related command processor methods
|
3
|
+
require 'rubygems'; require 'require_relative'
|
4
|
+
require_relative '../app/util'
|
5
|
+
class Trepan
|
6
|
+
include Util
|
7
|
+
class CmdProcessor
|
8
|
+
def errmsg(message)
|
9
|
+
@dbgr.intf[-1].errmsg(safe_rep(message))
|
10
|
+
end
|
11
|
+
|
12
|
+
def msg(message)
|
13
|
+
@dbgr.intf[-1].msg(safe_rep(message))
|
14
|
+
end
|
15
|
+
|
16
|
+
def msg_nocr(message)
|
17
|
+
@dbgr.intf[-1].msg_nocr(safe_rep(message))
|
18
|
+
end
|
19
|
+
|
20
|
+
def read_command()
|
21
|
+
@dbgr.intf[-1].read_command(@prompt)
|
22
|
+
end
|
23
|
+
|
24
|
+
def safe_rep(str)
|
25
|
+
Trepan::Util::safe_repr(str, @settings[:maxstring])
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|