rbx-trepanning 0.2.0-universal-rubinius-2.0
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/.gitignore +7 -0
- data/ChangeLog +2967 -0
- data/LICENSE +25 -0
- data/Makefile +13 -0
- data/NEWS +105 -0
- data/README.textile +34 -0
- data/Rakefile +244 -0
- data/THANKS +14 -0
- data/app/.gitignore +2 -0
- data/app/breakpoint.rb +242 -0
- data/app/brkptmgr.rb +153 -0
- data/app/client.rb +71 -0
- data/app/cmd_parse.kpeg +242 -0
- data/app/cmd_parse.rb +209 -0
- data/app/cmd_parser.rb +2083 -0
- data/app/complete.rb +79 -0
- data/app/condition.rb +22 -0
- data/app/default.rb +71 -0
- data/app/display.rb +186 -0
- data/app/eventbuffer.rb +147 -0
- data/app/file.rb +24 -0
- data/app/frame.rb +120 -0
- data/app/irb.rb +113 -0
- data/app/iseq.rb +188 -0
- data/app/method.rb +178 -0
- data/app/mock.rb +13 -0
- data/app/options.rb +154 -0
- data/app/rbx-llvm.rb +163 -0
- data/app/run.rb +92 -0
- data/app/util.rb +99 -0
- data/app/validate.rb +30 -0
- data/bin/.gitignore +2 -0
- data/bin/trepanx +69 -0
- data/data/.gitignore +2 -0
- data/data/irbrc +41 -0
- data/interface/.gitignore +2 -0
- data/interface/client.rb +84 -0
- data/interface/comcodes.rb +20 -0
- data/interface/script.rb +112 -0
- data/interface/server.rb +147 -0
- data/interface/user.rb +158 -0
- data/interface.rb +109 -0
- data/io/.gitignore +3 -0
- data/io/input.rb +151 -0
- data/io/null_output.rb +46 -0
- data/io/string_array.rb +155 -0
- data/io/tcpclient.rb +129 -0
- data/io/tcpfns.rb +33 -0
- data/io/tcpserver.rb +141 -0
- data/io.rb +148 -0
- data/lib/.gitignore +2 -0
- data/lib/trepanning.rb +467 -0
- data/processor/.gitignore +3 -0
- data/processor/Makefile +7 -0
- data/processor/breakpoint.rb +167 -0
- data/processor/command/.gitignore +2 -0
- data/processor/command/alias.rb +65 -0
- data/processor/command/backtrace.rb +68 -0
- data/processor/command/base/.gitignore +2 -0
- data/processor/command/base/subcmd.rb +226 -0
- data/processor/command/base/submgr.rb +185 -0
- data/processor/command/base/subsubcmd.rb +125 -0
- data/processor/command/base/subsubmgr.rb +196 -0
- data/processor/command/break.rb +78 -0
- data/processor/command/complete.rb +39 -0
- data/processor/command/condition.rb +64 -0
- data/processor/command/continue.rb +61 -0
- data/processor/command/delete.rb +44 -0
- data/processor/command/directory.rb +51 -0
- data/processor/command/disable.rb +71 -0
- data/processor/command/disassemble.rb +180 -0
- data/processor/command/display.rb +84 -0
- data/processor/command/down.rb +54 -0
- data/processor/command/edit.rb +74 -0
- data/processor/command/enable.rb +43 -0
- data/processor/command/eval.rb +93 -0
- data/processor/command/exit.rb +83 -0
- data/processor/command/finish.rb +80 -0
- data/processor/command/frame.rb +93 -0
- data/processor/command/help/.gitignore +1 -0
- data/processor/command/help/README +10 -0
- data/processor/command/help/command.txt +58 -0
- data/processor/command/help/examples.txt +16 -0
- data/processor/command/help/filename.txt +40 -0
- data/processor/command/help/location.txt +37 -0
- data/processor/command/help/suffixes.txt +17 -0
- data/processor/command/help.rb +228 -0
- data/processor/command/info.rb +30 -0
- data/processor/command/info_subcmd/.gitignore +3 -0
- data/processor/command/info_subcmd/breakpoints.rb +103 -0
- data/processor/command/info_subcmd/files.rb +219 -0
- data/processor/command/info_subcmd/frame.rb +68 -0
- data/processor/command/info_subcmd/line.rb +75 -0
- data/processor/command/info_subcmd/locals.rb +22 -0
- data/processor/command/info_subcmd/macro.rb +62 -0
- data/processor/command/info_subcmd/method.rb +71 -0
- data/processor/command/info_subcmd/program.rb +51 -0
- data/processor/command/info_subcmd/ruby.rb +64 -0
- data/processor/command/info_subcmd/source.rb +75 -0
- data/processor/command/info_subcmd/stack.rb +25 -0
- data/processor/command/info_subcmd/variables.rb +35 -0
- data/processor/command/info_subcmd/variables_subcmd/.gitignore +2 -0
- data/processor/command/info_subcmd/variables_subcmd/class.rb +42 -0
- data/processor/command/info_subcmd/variables_subcmd/constant.rb +42 -0
- data/processor/command/info_subcmd/variables_subcmd/globals.rb +69 -0
- data/processor/command/info_subcmd/variables_subcmd/instance.rb +42 -0
- data/processor/command/info_subcmd/variables_subcmd/locals.rb +80 -0
- data/processor/command/kill.rb +79 -0
- data/processor/command/list.rb +234 -0
- data/processor/command/macro.rb +86 -0
- data/processor/command/next.rb +67 -0
- data/processor/command/nexti.rb +59 -0
- data/processor/command/parsetree.rb +51 -0
- data/processor/command/pr.rb +37 -0
- data/processor/command/ps.rb +40 -0
- data/processor/command/restart.rb +60 -0
- data/processor/command/save.rb +58 -0
- data/processor/command/server.rb +72 -0
- data/processor/command/set.rb +47 -0
- data/processor/command/set_subcmd/.gitignore +2 -0
- data/processor/command/set_subcmd/abbrev.rb +25 -0
- data/processor/command/set_subcmd/auto.rb +33 -0
- data/processor/command/set_subcmd/auto_subcmd/.gitignore +2 -0
- data/processor/command/set_subcmd/auto_subcmd/dis.rb +33 -0
- data/processor/command/set_subcmd/auto_subcmd/eval.rb +53 -0
- data/processor/command/set_subcmd/auto_subcmd/irb.rb +33 -0
- data/processor/command/set_subcmd/auto_subcmd/list.rb +33 -0
- data/processor/command/set_subcmd/basename.rb +25 -0
- data/processor/command/set_subcmd/confirm.rb +24 -0
- data/processor/command/set_subcmd/debug.rb +26 -0
- data/processor/command/set_subcmd/debug_subcmd/.gitignore +2 -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 +61 -0
- data/processor/command/set_subcmd/hidelevel.rb +62 -0
- data/processor/command/set_subcmd/highlight.rb +39 -0
- data/processor/command/set_subcmd/kernelstep.rb +60 -0
- data/processor/command/set_subcmd/max.rb +26 -0
- data/processor/command/set_subcmd/max_subcmd/.gitignore +2 -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 +76 -0
- data/processor/command/set_subcmd/max_subcmd/width.rb +49 -0
- data/processor/command/set_subcmd/reload.rb +42 -0
- data/processor/command/set_subcmd/substitute.rb +24 -0
- data/processor/command/set_subcmd/substitute_subcmd/.gitignore +3 -0
- data/processor/command/set_subcmd/substitute_subcmd/path.rb +56 -0
- data/processor/command/set_subcmd/timer.rb +58 -0
- data/processor/command/set_subcmd/trace.rb +37 -0
- data/processor/command/set_subcmd/trace_subcmd/.gitignore +2 -0
- data/processor/command/set_subcmd/trace_subcmd/buffer.rb +42 -0
- data/processor/command/set_subcmd/trace_subcmd/print.rb +41 -0
- data/processor/command/shell.rb +131 -0
- data/processor/command/show.rb +39 -0
- data/processor/command/show_subcmd/.gitignore +3 -0
- data/processor/command/show_subcmd/abbrev.rb +20 -0
- data/processor/command/show_subcmd/aliases.rb +46 -0
- data/processor/command/show_subcmd/args.rb +25 -0
- data/processor/command/show_subcmd/auto.rb +28 -0
- data/processor/command/show_subcmd/auto_subcmd/.gitignore +3 -0
- data/processor/command/show_subcmd/auto_subcmd/dis.rb +37 -0
- data/processor/command/show_subcmd/auto_subcmd/eval.rb +24 -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 +20 -0
- data/processor/command/show_subcmd/confirm.rb +18 -0
- data/processor/command/show_subcmd/debug.rb +26 -0
- data/processor/command/show_subcmd/debug_subcmd/.gitignore +3 -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 +26 -0
- data/processor/command/show_subcmd/directories.rb +22 -0
- data/processor/command/show_subcmd/hidelevel.rb +41 -0
- data/processor/command/show_subcmd/highlight.rb +25 -0
- data/processor/command/show_subcmd/kernelstep.rb +34 -0
- data/processor/command/show_subcmd/max.rb +27 -0
- data/processor/command/show_subcmd/max_subcmd/.gitignore +2 -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/reload.rb +18 -0
- data/processor/command/show_subcmd/timer.rb +18 -0
- data/processor/command/show_subcmd/trace.rb +27 -0
- data/processor/command/show_subcmd/trace_subcmd/.gitignore +2 -0
- data/processor/command/show_subcmd/trace_subcmd/buffer.rb +64 -0
- data/processor/command/show_subcmd/trace_subcmd/print.rb +23 -0
- data/processor/command/show_subcmd/version.rb +23 -0
- data/processor/command/source.rb +133 -0
- data/processor/command/step.rb +97 -0
- data/processor/command/tbreak.rb +20 -0
- data/processor/command/unalias.rb +49 -0
- data/processor/command/undisplay.rb +63 -0
- data/processor/command/up.rb +89 -0
- data/processor/command.rb +173 -0
- data/processor/default.rb +64 -0
- data/processor/disassemble.rb +59 -0
- data/processor/display.rb +53 -0
- data/processor/eval.rb +97 -0
- data/processor/eventbuf.rb +101 -0
- data/processor/frame.rb +265 -0
- data/processor/help.rb +94 -0
- data/processor/hook.rb +134 -0
- data/processor/list.rb +123 -0
- data/processor/load_cmds.rb +253 -0
- data/processor/location.rb +228 -0
- data/processor/mock.rb +138 -0
- data/processor/msg.rb +74 -0
- data/processor/running.rb +244 -0
- data/processor/stepping.rb +135 -0
- data/processor/subcmd.rb +136 -0
- data/processor/validate.rb +379 -0
- data/processor/virtual.rb +33 -0
- data/processor.rb +404 -0
- data/rbx-trepanning.gemspec +39 -0
- data/sample/.gitignore +2 -0
- data/sample/list-terminal-colors.rb +139 -0
- data/sample/rocky-dot-trepanxrc +14 -0
- data/sample/rocky-trepanx-colors.rb +46 -0
- data/test/data/.gitignore +1 -0
- data/test/data/enable.right +36 -0
- data/test/data/fname-with-blank.cmd +6 -0
- data/test/data/fname-with-blank.right +6 -0
- data/test/data/inline-call.cmd +6 -0
- data/test/data/inline-call.right +14 -0
- data/test/data/quit-Xdebug.right +3 -0
- data/test/data/quit.cmd +5 -0
- data/test/data/quit.right +3 -0
- data/test/data/quit2.cmd +6 -0
- data/test/data/quit2.right +3 -0
- data/test/example/.gitignore +2 -0
- data/test/example/debugger-stop.rb +16 -0
- data/test/example/factorial.rb +10 -0
- data/test/example/fname with blank.rb +1 -0
- data/test/example/gcd-server.rb +22 -0
- data/test/example/gcd.rb +19 -0
- data/test/example/goto2goto.rb +11 -0
- data/test/example/inline-call.rb +23 -0
- data/test/example/null.rb +1 -0
- data/test/example/thread1.rb +3 -0
- data/test/functional/.gitignore +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 +85 -0
- data/test/functional/test-eval.rb +115 -0
- data/test/functional/test-finish.rb +70 -0
- data/test/functional/test-fn_helper.rb +43 -0
- data/test/functional/test-list.rb +56 -0
- data/test/functional/test-next-bug.rb +49 -0
- data/test/functional/test-next.rb +101 -0
- data/test/functional/test-recursive-bt.rb +94 -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/.gitignore +3 -0
- data/test/integration/file-diff.rb +89 -0
- data/test/integration/helper.rb +81 -0
- data/test/integration/test-fname-with-blank.rb +16 -0
- data/test/integration/test-inline-call.rb +20 -0
- data/test/integration/test-quit.rb +47 -0
- data/test/unit/.gitignore +3 -0
- data/test/unit/cmd-helper.rb +50 -0
- data/test/unit/mock-helper.rb +10 -0
- data/test/unit/test-app-brkpt.rb +31 -0
- data/test/unit/test-app-brkptmgr.rb +51 -0
- data/test/unit/test-app-cmd_parse.rb +97 -0
- data/test/unit/test-app-cmd_parser.rb +23 -0
- data/test/unit/test-app-complete.rb +39 -0
- data/test/unit/test-app-condition.rb +18 -0
- data/test/unit/test-app-display.rb +22 -0
- data/test/unit/test-app-iseq.rb +64 -0
- data/test/unit/test-app-method.rb +54 -0
- data/test/unit/test-app-options.rb +94 -0
- data/test/unit/test-app-run.rb +14 -0
- data/test/unit/test-app-util.rb +44 -0
- data/test/unit/test-app-validate.rb +18 -0
- data/test/unit/test-base-cmd.rb +45 -0
- data/test/unit/test-base-subcmd.rb +57 -0
- data/test/unit/test-base-submgr.rb +24 -0
- data/test/unit/test-base-subsubcmd.rb +17 -0
- data/test/unit/test-bin-trepanx.rb +48 -0
- data/test/unit/test-cmd-alias.rb +48 -0
- data/test/unit/test-cmd-break.rb +66 -0
- data/test/unit/test-cmd-edit.rb +34 -0
- data/test/unit/test-cmd-exit.rb +27 -0
- data/test/unit/test-cmd-finish.rb +31 -0
- data/test/unit/test-cmd-help.rb +104 -0
- data/test/unit/test-cmd-kill.rb +54 -0
- data/test/unit/test-cmd-parse_list_cmd.rb +36 -0
- data/test/unit/test-cmd-source.rb +34 -0
- data/test/unit/test-cmd-step.rb +29 -0
- data/test/unit/test-command.rb +45 -0
- data/test/unit/test-completion.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-io-tcp.rb +33 -0
- data/test/unit/test-io-tcpclient.rb +54 -0
- data/test/unit/test-io-tcpfns.rb +17 -0
- data/test/unit/test-io-tcpserver.rb +50 -0
- data/test/unit/test-proc-eval.rb +35 -0
- data/test/unit/test-proc-frame.rb +81 -0
- data/test/unit/test-proc-help.rb +16 -0
- data/test/unit/test-proc-hook.rb +30 -0
- data/test/unit/test-proc-list.rb +55 -0
- data/test/unit/test-proc-load_cmds.rb +51 -0
- data/test/unit/test-proc-location.rb +67 -0
- data/test/unit/test-proc-main.rb +95 -0
- data/test/unit/test-proc-validate.rb +139 -0
- data/test/unit/test-subcmd-help.rb +43 -0
- metadata +545 -0
data/processor/list.rb
ADDED
@@ -0,0 +1,123 @@
|
|
1
|
+
# Copyright (C) 2011 Rocky Bernstein <rockyb@rubyforge.net>
|
2
|
+
|
3
|
+
# Trepan command list validation routines. A String type is
|
4
|
+
# usually passed in as the argument to validation routines.
|
5
|
+
|
6
|
+
require 'rubygems'
|
7
|
+
require 'require_relative'
|
8
|
+
|
9
|
+
require_relative './validate'
|
10
|
+
|
11
|
+
class Trepan
|
12
|
+
class CmdProcessor < VirtualCmdProcessor
|
13
|
+
|
14
|
+
# If last is less than first, assume last is a count rather than an
|
15
|
+
# end line number. If last is negative, range is [first+last..first].
|
16
|
+
def adjust_last(first, last)
|
17
|
+
last < first ? first + last - 1 : last
|
18
|
+
end
|
19
|
+
|
20
|
+
# Parse a list command. On success return:
|
21
|
+
# - compiled method
|
22
|
+
# - the line number - a Fixnum
|
23
|
+
# - file name
|
24
|
+
# - last line
|
25
|
+
def parse_list_cmd(position_str, listsize, center_correction=0)
|
26
|
+
cm = nil
|
27
|
+
if position_str.empty?
|
28
|
+
filename = frame.file
|
29
|
+
first = [1, frame.line - center_correction].max
|
30
|
+
else
|
31
|
+
list_cmd_parse = parse_list(position_str,
|
32
|
+
:file_exists_proc => file_exists_proc)
|
33
|
+
return [nil] * 4 unless list_cmd_parse
|
34
|
+
last = list_cmd_parse.num
|
35
|
+
position = list_cmd_parse.position
|
36
|
+
|
37
|
+
if position.is_a?(String)
|
38
|
+
if position == '-'
|
39
|
+
return no_frame_msg_for_list unless frame.line
|
40
|
+
first = [1, frame.line - 2*listsize - 1].max
|
41
|
+
elsif position == '.'
|
42
|
+
return no_frame_msg_for_list unless frame.line
|
43
|
+
if (second = list_cmd_parse.num)
|
44
|
+
first = frame.line
|
45
|
+
last = adjust_last(first, second)
|
46
|
+
else
|
47
|
+
first = [1, frame.line - center_correction].max
|
48
|
+
last = first + listsize - 1
|
49
|
+
end
|
50
|
+
end
|
51
|
+
filename = frame.file
|
52
|
+
cm = frame.method
|
53
|
+
else
|
54
|
+
cm, filename, offset, offset_type =
|
55
|
+
parse_position(position)
|
56
|
+
|
57
|
+
return [nil] * 4 unless filename
|
58
|
+
if offset_type == :line
|
59
|
+
first = offset
|
60
|
+
elsif cm
|
61
|
+
first, vm_offset =
|
62
|
+
position_to_line_and_offset(cm, filename, position,
|
63
|
+
offset_type)
|
64
|
+
unless first
|
65
|
+
errmsg("Unable to get location in #{meth_or_frame}")
|
66
|
+
return [nil] * 4
|
67
|
+
end
|
68
|
+
elsif !offset
|
69
|
+
first = 1
|
70
|
+
else
|
71
|
+
errmsg("Unable to parse list position #{position_str}")
|
72
|
+
return [nil] * 4
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
if last
|
77
|
+
first, last = [first + last, first] if last < 0
|
78
|
+
last = adjust_last(first, last)
|
79
|
+
else
|
80
|
+
first = [1, first - center_correction].max
|
81
|
+
last = first + listsize - 1 unless last
|
82
|
+
end
|
83
|
+
LineCache::cache(filename) unless LineCache::cached?(filename)
|
84
|
+
return [cm, filename, first, last]
|
85
|
+
end
|
86
|
+
|
87
|
+
def no_frame_msg_for_list
|
88
|
+
errmsg("No Ruby program loaded.")
|
89
|
+
return [nil] * 4
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
if __FILE__ == $0
|
96
|
+
# Demo it.
|
97
|
+
require_relative 'mock'
|
98
|
+
require_relative 'frame'
|
99
|
+
dbgr, cmd = MockDebugger::setup('exit', false)
|
100
|
+
cmdproc = cmd.proc
|
101
|
+
cmdproc.frame_initialize
|
102
|
+
cmdproc.instance_variable_set('@settings',
|
103
|
+
Trepan::CmdProcessor::DEFAULT_SETTINGS)
|
104
|
+
def foo; 5 end
|
105
|
+
def cmdproc.errmsg(msg)
|
106
|
+
puts msg
|
107
|
+
end
|
108
|
+
puts '-' * 20
|
109
|
+
p cmdproc.parse_list_cmd('.', 10)
|
110
|
+
p cmdproc.parse_list_cmd('-', 10)
|
111
|
+
p cmdproc.parse_list_cmd('foo', 10)
|
112
|
+
p cmdproc.parse_list_cmd('@0', 10)
|
113
|
+
p cmdproc.parse_list_cmd("#{__LINE__}", 10)
|
114
|
+
p cmdproc.parse_list_cmd("#{__FILE__} @0", 10)
|
115
|
+
p '-' * 40
|
116
|
+
# require_relative '../lib/trepanning'; debugger
|
117
|
+
p cmdproc.parse_list_cmd("#{__FILE__}:#{__LINE__}", 10)
|
118
|
+
p cmdproc.parse_list_cmd("#{__FILE__} #{__LINE__}", 10)
|
119
|
+
p '-' * 40
|
120
|
+
p cmdproc.parse_list_cmd("cmdproc.errmsg", 10)
|
121
|
+
p cmdproc.parse_list_cmd("cmdproc.errmsg:@0", 10)
|
122
|
+
p cmdproc.parse_list_cmd("cmdproc.errmsg:@0", -10)
|
123
|
+
end
|
@@ -0,0 +1,253 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
# Copyright (C) 2010-2011, 2013 Rocky Bernstein <rockyb@rubyforge.net>
|
3
|
+
require 'tmpdir'
|
4
|
+
|
5
|
+
# Part of Trepan::CmdProcess that loads up debugger commands from
|
6
|
+
# builtin and user directories.
|
7
|
+
# Sets @commands, @aliases, @macros
|
8
|
+
require 'rubygems'; require 'require_relative'
|
9
|
+
require_relative '../app/complete'
|
10
|
+
require_relative 'virtual'
|
11
|
+
class Trepan
|
12
|
+
class CmdProcessor < VirtualCmdProcessor
|
13
|
+
|
14
|
+
attr_reader :aliases # Hash[String] of command names
|
15
|
+
# indexed by alias name
|
16
|
+
attr_reader :commands # Hash[String] of command objects
|
17
|
+
# indexed by name
|
18
|
+
attr_reader :macros # Hash[String] of Proc objects
|
19
|
+
# indexed by macro name.
|
20
|
+
attr_reader :leading_str # leading part of string. Used in
|
21
|
+
# command completion
|
22
|
+
|
23
|
+
# "initialize" for multi-file class. Called from main.rb's "initialize".
|
24
|
+
def load_cmds_initialize
|
25
|
+
@commands = {}
|
26
|
+
@aliases = {}
|
27
|
+
@macros = {}
|
28
|
+
|
29
|
+
cmd_dirs = [ File.join(File.dirname(__FILE__), 'command') ]
|
30
|
+
cmd_dirs << @settings[:user_cmd_dir] if @settings[:user_cmd_dir]
|
31
|
+
cmd_dirs.each do |cmd_dir|
|
32
|
+
load_debugger_commands(cmd_dir) if File.directory?(cmd_dir)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# Loads in debugger commands by require'ing each ruby file in the
|
37
|
+
# 'command' directory. Then a new instance of each class of the
|
38
|
+
# form Trepan::xxCommand is added to @commands and that array
|
39
|
+
# is returned.
|
40
|
+
def load_debugger_commands(file_or_dir)
|
41
|
+
if File.directory?(file_or_dir)
|
42
|
+
dir = File.expand_path(file_or_dir)
|
43
|
+
# Change $0 so it doesn't get in the way of __FILE__ = $0.
|
44
|
+
# In rubinius 2.0.0.rc1 (1.8.7 93c75658...) $0 is nil
|
45
|
+
# and this can cause an error when one restores $0 below.
|
46
|
+
# See https://github.com/rubinius/rubinius/issues/2450
|
47
|
+
old_dollar0 = $0 || '' #
|
48
|
+
$0 = ''
|
49
|
+
Dir.glob(File.join(dir, '*.rb')).each do |rb|
|
50
|
+
# We use require so that multiple calls have no effect.
|
51
|
+
require rb
|
52
|
+
end
|
53
|
+
$0 = old_dollar0
|
54
|
+
elsif File.readable?(file_or_dir)
|
55
|
+
# We use load in case we are reloading.
|
56
|
+
# 'require' would not be effective here
|
57
|
+
load file_or_dir
|
58
|
+
else
|
59
|
+
return false
|
60
|
+
end
|
61
|
+
# Instantiate each Command class found by the above require(s).
|
62
|
+
Trepan::Command.constants.grep(/.Command$/).each do |name|
|
63
|
+
klass = Trepan::Command.const_get(name)
|
64
|
+
cmd = klass.send(:new, self)
|
65
|
+
|
66
|
+
# Add to list of commands and aliases.
|
67
|
+
cmd_name = klass.const_get(:NAME)
|
68
|
+
if klass.constants.member?('ALIASES')
|
69
|
+
aliases= klass.const_get('ALIASES')
|
70
|
+
aliases.each {|a| @aliases[a] = cmd_name}
|
71
|
+
end
|
72
|
+
@commands[cmd_name] = cmd
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
# Instantiate a Trepan::Command and extract info: the NAME, ALIASES
|
77
|
+
# and store the command in @commands.
|
78
|
+
def setup_command(command)
|
79
|
+
# Note: there is probably a non-eval way to instantiate the
|
80
|
+
# command, but I don't know it. And eval works.
|
81
|
+
klass = self.instance_eval("Trepan::Command::#{command}")
|
82
|
+
cmd = klass.send(:new, self)
|
83
|
+
|
84
|
+
# Add to list of commands and aliases.
|
85
|
+
cmd_name = klass.const_get(:NAME)
|
86
|
+
if klass.constants.member?(:ALIASES)
|
87
|
+
aliases= klass.const_get(:ALIASES)
|
88
|
+
aliases.each {|a| @aliases[a] = cmd_name}
|
89
|
+
end
|
90
|
+
@commands[cmd_name] = cmd
|
91
|
+
end
|
92
|
+
|
93
|
+
# Looks up cmd_array[0] in @commands and runs that. We do lots of
|
94
|
+
# validity testing on cmd_array.
|
95
|
+
def run_cmd(cmd_array)
|
96
|
+
unless cmd_array.is_a?(Array)
|
97
|
+
errmsg "run_cmd argument should be an Array, got: #{cmd_array.class}"
|
98
|
+
return
|
99
|
+
end
|
100
|
+
if cmd_array.detect{|item| !item.is_a?(String)}
|
101
|
+
errmsg "run_cmd argument Array should only contain strings. " +
|
102
|
+
"Got #{cmd_array.inspect}"
|
103
|
+
return
|
104
|
+
end
|
105
|
+
if cmd_array.empty?
|
106
|
+
errmsg "run_cmd Array should have at least one item. " +
|
107
|
+
"Got: #{cmd_array.inspect}"
|
108
|
+
return
|
109
|
+
end
|
110
|
+
cmd_name = cmd_array[0]
|
111
|
+
if @commands.member?(cmd_name)
|
112
|
+
@commands[cmd_name].run(cmd_array)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def save_commands(opts)
|
117
|
+
save_filename = opts[:filename] ||
|
118
|
+
File.join(Dir.tmpdir, "trepanning-save-#{$$}.txt")
|
119
|
+
begin
|
120
|
+
save_file = File.open(save_filename, 'w')
|
121
|
+
rescue => exc
|
122
|
+
errmsg("Can't open #{save_filename} for writing.")
|
123
|
+
errmsg("System reports: #{exc.inspect}")
|
124
|
+
return nil
|
125
|
+
end
|
126
|
+
save_file.puts "#\n# Commands to restore trepanning environment\n#\n"
|
127
|
+
@commands.each do |cmd_name, cmd_obj|
|
128
|
+
cmd_obj.save_command if cmd_obj.respond_to?(:save_command)
|
129
|
+
next unless cmd_obj.is_a?(Trepan::SubcommandMgr)
|
130
|
+
cmd_obj.subcmds.subcmds.each do |subcmd_name, subcmd_obj|
|
131
|
+
save_file.puts subcmd_obj.save_command if
|
132
|
+
subcmd_obj.respond_to?(:save_command)
|
133
|
+
next unless subcmd_obj.is_a?(Trepan::SubSubcommandMgr)
|
134
|
+
subcmd_obj.subcmds.subcmds.each do |subsubcmd_name, subsubcmd_obj|
|
135
|
+
save_file.puts subsubcmd_obj.save_command if
|
136
|
+
subsubcmd_obj.respond_to?(:save_command)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
save_file.puts "!FileUtils.rm #{save_filename.inspect}" if
|
141
|
+
opts[:erase]
|
142
|
+
save_file.close
|
143
|
+
|
144
|
+
return save_filename
|
145
|
+
end
|
146
|
+
|
147
|
+
# Handle initial completion. We draw from the commands, aliases,
|
148
|
+
# and macros for completion. However we won't include aliases which
|
149
|
+
# are prefixes of other commands.
|
150
|
+
def complete(str, last_token)
|
151
|
+
@leading_str = str
|
152
|
+
next_blank_pos, token = Trepan::Complete.next_token(str, 0)
|
153
|
+
return [''] if token.empty? && !last_token.empty?
|
154
|
+
match_pairs = Trepan::Complete.complete_token_with_next(@commands,
|
155
|
+
token)
|
156
|
+
match_hash = {}
|
157
|
+
match_pairs.each do |pair|
|
158
|
+
match_hash[pair[0]] = pair[1]
|
159
|
+
end
|
160
|
+
alias_pairs = Trepan::Complete.
|
161
|
+
complete_token_filtered_with_next(@aliases, token, match_hash,
|
162
|
+
@commands)
|
163
|
+
match_pairs += alias_pairs
|
164
|
+
if str[next_blank_pos..-1].empty?
|
165
|
+
return match_pairs.map{|pair| pair[0]}.sort
|
166
|
+
else
|
167
|
+
alias_pairs.each do |pair|
|
168
|
+
match_hash[pair[0]] = pair[1]
|
169
|
+
end
|
170
|
+
end
|
171
|
+
if match_pairs.size > 1
|
172
|
+
# FIXME: figure out what to do here.
|
173
|
+
# Matched multiple items in the middle of the string
|
174
|
+
# We can't handle this so do nothing.
|
175
|
+
return []
|
176
|
+
# return match_pairs.map do |name, cmd|
|
177
|
+
# ["#{name} #{args[1..-1].join(' ')}"]
|
178
|
+
# end
|
179
|
+
end
|
180
|
+
# match_pairs.size <= 1
|
181
|
+
next_complete(str, next_blank_pos, match_pairs[0][1], last_token)
|
182
|
+
end
|
183
|
+
|
184
|
+
def next_complete(str, next_blank_pos, cmd, last_token)
|
185
|
+
next_blank_pos, token = Trepan::Complete.next_token(str, next_blank_pos)
|
186
|
+
return [] if token.empty? && !last_token.empty?
|
187
|
+
|
188
|
+
if cmd.respond_to?(:complete_token_with_next)
|
189
|
+
match_pairs = cmd.complete_token_with_next(token)
|
190
|
+
return [] if match_pairs.empty?
|
191
|
+
if str[next_blank_pos..-1].rstrip.empty? &&
|
192
|
+
(token.empty? || token == last_token)
|
193
|
+
return match_pairs.map { |completion, junk| completion }
|
194
|
+
else
|
195
|
+
if match_pairs.size == 1
|
196
|
+
return next_complete(str, next_blank_pos, match_pairs[0][1],
|
197
|
+
last_token)
|
198
|
+
else
|
199
|
+
# FIXME: figure out what to do here.
|
200
|
+
# Matched multiple items in the middle of the string
|
201
|
+
# We can't handle this so do nothing.
|
202
|
+
return []
|
203
|
+
end
|
204
|
+
end
|
205
|
+
elsif cmd.respond_to?(:complete)
|
206
|
+
matches = cmd.complete(token)
|
207
|
+
return [] if matches.empty?
|
208
|
+
if str[next_blank_pos..-1].rstrip.empty? &&
|
209
|
+
(token.empty? || token == last_token)
|
210
|
+
return matches
|
211
|
+
else
|
212
|
+
# FIXME: figure out what to do here.
|
213
|
+
# Matched multiple items in the middle of the string
|
214
|
+
# We can't handle this so do nothing.
|
215
|
+
return []
|
216
|
+
end
|
217
|
+
else
|
218
|
+
return []
|
219
|
+
end
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|
223
|
+
if __FILE__ == $0
|
224
|
+
class Trepan::CmdProcessor
|
225
|
+
def initialize(core, settings={})
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
cmdproc = Trepan::CmdProcessor.new(nil)
|
230
|
+
cmddir = File.join(File.dirname(__FILE__), 'command')
|
231
|
+
cmdproc.instance_variable_set('@settings', {})
|
232
|
+
cmdproc.load_cmds_initialize
|
233
|
+
require 'columnize'
|
234
|
+
puts Columnize.columnize(cmdproc.commands.keys.sort)
|
235
|
+
puts '=' * 20
|
236
|
+
puts Columnize.columnize(cmdproc.aliases.keys.sort)
|
237
|
+
puts '=' * 20
|
238
|
+
|
239
|
+
def cmdproc.errmsg(mess)
|
240
|
+
puts "** #{mess}"
|
241
|
+
end
|
242
|
+
|
243
|
+
def cmdproc.msg(mess)
|
244
|
+
puts mess
|
245
|
+
end
|
246
|
+
|
247
|
+
cmdproc.run_cmd('foo') # Invalid - not an Array
|
248
|
+
cmdproc.run_cmd([]) # Invalid - empty Array
|
249
|
+
cmdproc.run_cmd(['list', 5]) # Invalid - nonstring arg
|
250
|
+
p cmdproc.complete("d", 'd')
|
251
|
+
p cmdproc.complete("sho d", 'd')
|
252
|
+
p cmdproc.complete('', '')
|
253
|
+
end
|
@@ -0,0 +1,228 @@
|
|
1
|
+
# Copyright (C) 2010-2011, 2013 Rocky Bernstein <rockyb@rubyforge.net>
|
2
|
+
require 'rubygems';
|
3
|
+
require 'pathname' # For cleanpath
|
4
|
+
require 'linecache'
|
5
|
+
require 'require_relative'
|
6
|
+
require_relative 'disassemble'
|
7
|
+
require_relative 'msg'
|
8
|
+
require_relative 'frame'
|
9
|
+
require_relative '../app/file'
|
10
|
+
require_relative 'virtual'
|
11
|
+
class Trepan::CmdProcessor < Trepan::VirtualCmdProcessor
|
12
|
+
|
13
|
+
unless defined?(EVENT2ICON)
|
14
|
+
# Event icons used in printing locations.
|
15
|
+
EVENT2ICON = {
|
16
|
+
'brkpt' => 'xx',
|
17
|
+
'tbrkpt' => 'x1',
|
18
|
+
'c-call' => 'C>',
|
19
|
+
'c-return' => '<C',
|
20
|
+
'step-call' => '->',
|
21
|
+
'call' => '->',
|
22
|
+
'class' => '::',
|
23
|
+
'coverage' => '[]',
|
24
|
+
'debugger-call' => ':o',
|
25
|
+
'end' => '-|',
|
26
|
+
'line' => '--',
|
27
|
+
'raise' => '!!',
|
28
|
+
'return' => '<-',
|
29
|
+
'start' => '>>',
|
30
|
+
'switch' => 'sw',
|
31
|
+
'trace-var' => '$V',
|
32
|
+
'unknown' => '?!',
|
33
|
+
'vm' => 'VM',
|
34
|
+
'vm-insn' => '..',
|
35
|
+
}
|
36
|
+
end
|
37
|
+
|
38
|
+
def canonic_file(filename, resolve=true)
|
39
|
+
# For now we want resolved filenames
|
40
|
+
if @settings[:basename]
|
41
|
+
return File.basename(filename)
|
42
|
+
end
|
43
|
+
if resolve
|
44
|
+
try_filename = LineCache::map_file(filename)
|
45
|
+
filename = try_filename || filename
|
46
|
+
if !File.exist?(filename)
|
47
|
+
if (try_filename = find_load_path(filename))
|
48
|
+
return try_filename
|
49
|
+
elsif (try_filename = resolve_file_with_dir(filename))
|
50
|
+
return try_filename
|
51
|
+
else
|
52
|
+
return File.expand_path(Pathname.new(filename).cleanpath.to_s).
|
53
|
+
gsub(/\.rbc$/, '.rb')
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
return filename.gsub(/\.rbc$/, '.rb')
|
58
|
+
end
|
59
|
+
|
60
|
+
# Return the text to the current source line.
|
61
|
+
# FIXME: loc_and_text should call this rather than the other
|
62
|
+
# way around.
|
63
|
+
def current_source_text
|
64
|
+
opts = {:reload_on_change => settings[:reload]}
|
65
|
+
loc, junk, text = loc_and_text(source_location_info, opts)
|
66
|
+
text
|
67
|
+
end
|
68
|
+
|
69
|
+
def resolve_file_with_dir(path_suffix)
|
70
|
+
settings[:directory].split(/:/).each do |dir|
|
71
|
+
dir =
|
72
|
+
if '$cwd' == dir
|
73
|
+
Dir.pwd
|
74
|
+
elsif '$cdir' == dir
|
75
|
+
Rubinius::OS_STARTUP_DIR
|
76
|
+
elsif '$rbx' == dir
|
77
|
+
compiler_file = '/lib/compiler/compiler.rb'
|
78
|
+
compiler_rb_path =
|
79
|
+
$LOADED_FEATURES.find{|f| f.end_with?(compiler_file)}
|
80
|
+
if compiler_rb_path
|
81
|
+
compiler_rb_path[0...-(compiler_file.size)]
|
82
|
+
else
|
83
|
+
nil
|
84
|
+
end
|
85
|
+
else
|
86
|
+
dir
|
87
|
+
end
|
88
|
+
next unless dir && File.directory?(dir)
|
89
|
+
try_file = File.join(dir, path_suffix)
|
90
|
+
return try_file if File.readable?(try_file)
|
91
|
+
end
|
92
|
+
nil
|
93
|
+
end
|
94
|
+
|
95
|
+
# Get line +line_number+ from file named +filename+. Return "\n"
|
96
|
+
# there was a problem. Leading blanks are stripped off.
|
97
|
+
def line_at(filename, line_number,
|
98
|
+
opts = {
|
99
|
+
:reload_on_change => @settings[:reload],
|
100
|
+
:output => @settings[:highlight]
|
101
|
+
})
|
102
|
+
# We use linecache first to give precidence to user-remapped
|
103
|
+
# file names
|
104
|
+
line = LineCache::getline(filename, line_number, opts)
|
105
|
+
unless line
|
106
|
+
# Try using search directories (set with command "directory")
|
107
|
+
if filename[0..0] != File::SEPARATOR
|
108
|
+
try_filename = resolve_file_with_dir(filename)
|
109
|
+
if try_filename &&
|
110
|
+
line = LineCache::getline(try_filename, line_number, opts)
|
111
|
+
LineCache::remap_file(filename, try_filename)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
return nil unless line
|
116
|
+
return line.lstrip.chomp
|
117
|
+
end
|
118
|
+
|
119
|
+
def loc_and_text(loc, opts=
|
120
|
+
{:reload_on_change => @settings[:reload],
|
121
|
+
:output => @settings[:highlight]
|
122
|
+
})
|
123
|
+
|
124
|
+
vm_location = @frame.vm_location
|
125
|
+
filename = vm_location.method.active_path
|
126
|
+
line_no = @frame.line
|
127
|
+
static = vm_location.constant_scope
|
128
|
+
opts[:compiled_method] = top_scope(@frame.method)
|
129
|
+
|
130
|
+
if @frame.eval?
|
131
|
+
file = LineCache::map_script(static.script)
|
132
|
+
text = LineCache::getline(static.script, line_no, opts)
|
133
|
+
loc += " remapped #{canonic_file(file)}:#{line_no}"
|
134
|
+
else
|
135
|
+
text = line_at(filename, line_no, opts)
|
136
|
+
map_file, map_line = LineCache::map_file_line(filename, line_no)
|
137
|
+
if [filename, line_no] != [map_file, map_line]
|
138
|
+
loc += " remapped #{canonic_file(map_file)}:#{map_line}"
|
139
|
+
end
|
140
|
+
end
|
141
|
+
[loc, line_no, text]
|
142
|
+
end
|
143
|
+
|
144
|
+
def format_location(event=@event, frame=@frame, frame_index=@frame_index)
|
145
|
+
text = nil
|
146
|
+
ev = if event.nil? || 0 != frame_index
|
147
|
+
' '
|
148
|
+
else
|
149
|
+
(EVENT2ICON[event] || event)
|
150
|
+
end
|
151
|
+
|
152
|
+
@line_no = frame.line
|
153
|
+
|
154
|
+
loc = source_location_info
|
155
|
+
loc, @line_no, text = loc_and_text(loc)
|
156
|
+
ip_str = frame.method ? " @#{frame.next_ip}" : ''
|
157
|
+
|
158
|
+
"#{ev} (#{loc}#{ip_str})"
|
159
|
+
end
|
160
|
+
|
161
|
+
# FIXME: Use above format_location routine
|
162
|
+
def print_location
|
163
|
+
text = nil
|
164
|
+
ev = if @event.nil? || 0 != @frame_index
|
165
|
+
' '
|
166
|
+
else
|
167
|
+
(EVENT2ICON[@event] || @event)
|
168
|
+
end
|
169
|
+
|
170
|
+
@line_no = @frame.line
|
171
|
+
|
172
|
+
loc = source_location_info
|
173
|
+
loc, @line_no, text = loc_and_text(loc)
|
174
|
+
ip_str = frame.method ? " @#{frame.next_ip}" : ''
|
175
|
+
|
176
|
+
msg "#{ev} (#{loc}#{ip_str})"
|
177
|
+
|
178
|
+
# if %w(return c-return).member?(@core.event)
|
179
|
+
# retval = Trepan::Frame.value_returned(@frame, @core.event)
|
180
|
+
# msg 'R=> %s' % retval.inspect
|
181
|
+
# end
|
182
|
+
|
183
|
+
if text && !text.strip.empty?
|
184
|
+
old_maxstring = @settings[:maxstring]
|
185
|
+
@settings[:maxstring] = -1
|
186
|
+
msg text
|
187
|
+
@settings[:maxstring] = old_maxstring
|
188
|
+
@line_no -= 1
|
189
|
+
else
|
190
|
+
show_bytecode
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
def source_location_info
|
195
|
+
filename = @frame.vm_location.method.active_path
|
196
|
+
canonic_filename =
|
197
|
+
if @frame.eval?
|
198
|
+
'eval ' + safe_repr(@frame.eval_string.gsub("\n", ';').inspect, 20)
|
199
|
+
else
|
200
|
+
canonic_file(filename, false)
|
201
|
+
end
|
202
|
+
loc = "#{canonic_filename}:#{@frame.line}"
|
203
|
+
return loc
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
if __FILE__ == $0 && caller.size == 0
|
208
|
+
# Demo it.
|
209
|
+
require_relative './mock'
|
210
|
+
dbgr = MockDebugger::MockDebugger.new
|
211
|
+
proc = Trepan::CmdProcessor.new(dbgr)
|
212
|
+
proc.settings = {:directory => '$rbx:$cdir:$cwd'}
|
213
|
+
proc.frame_initialize
|
214
|
+
frame = Trepan::Frame.new(self, 1, Rubinius::VM.backtrace(0)[0])
|
215
|
+
proc.instance_variable_set('@frame', frame)
|
216
|
+
|
217
|
+
puts proc.canonic_file(__FILE__)
|
218
|
+
puts proc.canonic_file('lib/compiler/ast.rb')
|
219
|
+
proc.settings[:basename] = true
|
220
|
+
puts proc.canonic_file(__FILE__)
|
221
|
+
puts proc.current_source_text
|
222
|
+
xx = eval <<-END
|
223
|
+
proc.frame_initialize
|
224
|
+
frame = Trepan::Frame.new(self, 1, Rubinius::VM.backtrace(0)[0])
|
225
|
+
proc.instance_variable_set('@frame', frame)
|
226
|
+
puts proc.current_source_text
|
227
|
+
END
|
228
|
+
end
|