trepanning 0.1.2 → 0.1.3
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 +354 -0
- data/NEWS +21 -0
- data/Rakefile +27 -20
- data/app/cmd_parse.kpeg +20 -4
- data/app/cmd_parse.rb +11 -10
- data/app/cmd_parser.rb +119 -55
- data/app/complete.rb +1 -0
- data/app/core.rb +3 -3
- data/app/disassemble.rb +13 -3
- data/app/file.rb +2 -1
- data/app/frame.rb +3 -1
- data/app/mock.rb +3 -0
- data/app/options.rb +48 -31
- data/app/util.rb +50 -0
- data/interface/base_intf.rb +4 -0
- data/interface/client.rb +4 -0
- data/interface/script.rb +1 -1
- data/interface/server.rb +4 -0
- data/interface/user.rb +5 -0
- data/io/input.rb +3 -2
- data/io/null_output.rb +7 -1
- data/processor/breakpoint.rb +3 -2
- data/processor/command/base/subcmd.rb +1 -1
- data/processor/command/base/submgr.rb +4 -1
- data/processor/command/base/subsubcmd.rb +2 -2
- data/processor/command/base/subsubmgr.rb +1 -1
- data/processor/command/break.rb +7 -3
- data/processor/command/complete.rb +1 -0
- data/processor/command/continue.rb +1 -1
- data/processor/command/disassemble.rb +1 -1
- data/processor/command/edit.rb +35 -14
- data/processor/command/enable.rb +5 -3
- data/processor/command/eval.rb +35 -14
- data/processor/command/exit.rb +2 -0
- data/processor/command/help.rb +0 -9
- data/processor/command/help/command.txt +37 -27
- data/processor/command/help/examples.txt +16 -0
- data/processor/command/help/suffixes.txt +17 -0
- data/processor/command/info.rb +1 -1
- data/processor/command/info_subcmd/args.rb +7 -13
- data/processor/command/info_subcmd/breakpoints.rb +8 -2
- data/processor/command/info_subcmd/frame.rb +2 -0
- data/processor/command/info_subcmd/globals.rb +63 -0
- data/processor/command/info_subcmd/iseq.rb +3 -1
- data/processor/command/info_subcmd/locals.rb +16 -15
- data/processor/command/{show_subcmd → info_subcmd}/macro.rb +7 -7
- data/processor/command/info_subcmd/program.rb +2 -0
- data/processor/command/info_subcmd/registers.rb +5 -1
- data/processor/command/info_subcmd/registers_subcmd/dfp.rb +2 -3
- data/processor/command/info_subcmd/registers_subcmd/helper.rb +8 -9
- data/processor/command/info_subcmd/registers_subcmd/lfp.rb +10 -5
- data/processor/command/info_subcmd/registers_subcmd/pc.rb +9 -4
- data/processor/command/info_subcmd/registers_subcmd/sp.rb +4 -5
- data/processor/command/info_subcmd/ruby.rb +3 -1
- data/processor/command/info_subcmd/source.rb +78 -0
- data/processor/command/info_subcmd/stack.rb +23 -0
- data/processor/command/kill.rb +4 -6
- data/processor/command/list.rb +118 -120
- data/processor/command/macro.rb +1 -1
- data/processor/command/parsetree.rb +56 -0
- data/processor/command/pp.rb +40 -0
- data/processor/command/pr.rb +1 -2
- data/processor/command/quit.rb +2 -1
- data/processor/command/set_subcmd/abbrev.rb +24 -0
- data/processor/command/set_subcmd/auto_subcmd/eval.rb +1 -2
- data/processor/command/set_subcmd/auto_subcmd/irb.rb +2 -3
- data/processor/command/set_subcmd/auto_subcmd/list.rb +2 -3
- data/processor/command/set_subcmd/highlight.rb +8 -2
- data/processor/command/set_subcmd/reload.rb +41 -0
- data/processor/command/set_subcmd/timer.rb +8 -18
- data/processor/command/set_subcmd/trace.rb +2 -2
- data/processor/command/set_subcmd/trace_subcmd/buffer.rb +2 -2
- data/processor/command/set_subcmd/trace_subcmd/print.rb +3 -3
- data/processor/command/{irb.rb → shell.rb} +9 -6
- data/processor/command/show_subcmd/abbrev.rb +19 -0
- data/processor/command/show_subcmd/directories.rb +21 -0
- data/processor/command/show_subcmd/hidelevel.rb +1 -1
- data/processor/command/show_subcmd/highlight.rb +2 -1
- data/processor/command/show_subcmd/reload.rb +17 -0
- data/processor/command/show_subcmd/timer.rb +17 -0
- data/processor/command/show_subcmd/trace_subcmd/buffer.rb +1 -1
- data/processor/command/source.rb +15 -14
- data/processor/command/tbreak.rb +20 -0
- data/processor/command/watchg.rb +114 -0
- data/processor/default.rb +43 -41
- data/processor/display.rb +3 -2
- data/processor/eval.rb +5 -3
- data/processor/eventbuf.rb +3 -2
- data/processor/frame.rb +12 -3
- data/processor/hook.rb +3 -2
- data/processor/load_cmds.rb +186 -179
- data/processor/location.rb +154 -159
- data/processor/main.rb +44 -16
- data/processor/mock.rb +0 -11
- data/processor/msg.rb +3 -1
- data/processor/running.rb +3 -2
- data/processor/validate.rb +25 -4
- data/processor/virtual.rb +32 -0
- data/test/data/debugger-stop.right +1 -0
- data/test/data/fname-with-blank.right +1 -0
- data/test/example/gcd.rb +1 -0
- data/test/functional/{test-trace-var.rb → test-watchg.rb} +15 -4
- data/test/unit/cmd-helper.rb +0 -3
- data/test/unit/test-app-cmd_parser.rb +2 -2
- data/test/unit/test-app-file.rb +1 -0
- data/test/unit/test-app-frame.rb +1 -1
- data/test/unit/test-app-util.rb +21 -0
- data/test/unit/test-base-cmd.rb +4 -6
- data/test/unit/test-base-subcmd.rb +1 -4
- data/test/unit/test-base-submgr.rb +1 -2
- data/test/unit/test-base-subsubcmd.rb +0 -4
- data/test/unit/test-cmd-edit.rb +33 -0
- data/test/unit/test-cmd-parse_list_cmd.rb +33 -0
- data/test/unit/test-completion.rb +1 -1
- data/test/unit/test-proc-frame.rb +4 -1
- data/test/unit/test-proc-load_cmds.rb +2 -1
- data/test/unit/test-proc-location.rb +9 -26
- data/test/unit/test-proc-main.rb +1 -4
- data/test/unit/test-proc-validate.rb +28 -18
- data/test/unit/test-subcmd-help.rb +0 -4
- data/trepanning.gemspec +1 -1
- metadata +27 -10
- data/processor/command/set_subcmd/trace_subcmd/var.rb +0 -57
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
require_relative '../base/subcmd'
|
|
4
4
|
require_relative '../../../app/complete'
|
|
5
5
|
|
|
6
|
-
class Trepan::Subcommand::
|
|
6
|
+
class Trepan::Subcommand::InfoMacro < Trepan::Subcommand
|
|
7
7
|
unless defined?(HELP)
|
|
8
8
|
Trepanning::Subcommand.set_name_prefix(__FILE__, self)
|
|
9
9
|
HELP = <<-HELP
|
|
@@ -18,8 +18,8 @@ In the second form, all macro names and their definitions are show.
|
|
|
18
18
|
|
|
19
19
|
In the last form the only definitions of the given macro names is shown.
|
|
20
20
|
HELP
|
|
21
|
-
SHORT_HELP = "
|
|
22
|
-
MIN_ABBREV = '
|
|
21
|
+
SHORT_HELP = "Info defined macros"
|
|
22
|
+
MIN_ABBREV = 'mac'.size
|
|
23
23
|
end
|
|
24
24
|
|
|
25
25
|
def complete(prefix)
|
|
@@ -40,11 +40,11 @@ In the last form the only definitions of the given macro names is shown.
|
|
|
40
40
|
string = @proc.macros[macro_name][1]
|
|
41
41
|
msg " #{@proc.ruby_format(string)}", {:unlimited => true}
|
|
42
42
|
else
|
|
43
|
-
errmsg
|
|
43
|
+
errmsg '%s is not a defined macro' % macro_name
|
|
44
44
|
end
|
|
45
45
|
end
|
|
46
46
|
elsif @proc.macros.empty?
|
|
47
|
-
msg
|
|
47
|
+
msg 'No macros defined.'
|
|
48
48
|
else
|
|
49
49
|
msg columnize_commands(@proc.macros.keys.sort)
|
|
50
50
|
end
|
|
@@ -54,8 +54,8 @@ end
|
|
|
54
54
|
|
|
55
55
|
if __FILE__ == $0
|
|
56
56
|
# Demo it.
|
|
57
|
-
$0 = __FILE__ + 'notagain' # So we don't run this
|
|
57
|
+
$0 = __FILE__ + 'notagain' # So we don't run this again
|
|
58
58
|
require_relative '../../mock'
|
|
59
|
-
cmd = MockDebugger::sub_setup(Trepan::Subcommand::
|
|
59
|
+
cmd = MockDebugger::sub_setup(Trepan::Subcommand::InfoMacro)
|
|
60
60
|
cmd.run(cmd.prefix + %w(u foo))
|
|
61
61
|
end
|
|
@@ -6,6 +6,8 @@ class Trepan::Subcommand::InfoProgram < Trepan::Subcommand
|
|
|
6
6
|
unless defined?(HELP)
|
|
7
7
|
Trepanning::Subcommand.set_name_prefix(__FILE__, self)
|
|
8
8
|
HELP = 'Information about debugged program and its environment'
|
|
9
|
+
MIN_ARGS = 0
|
|
10
|
+
MAX_ARGS = 0
|
|
9
11
|
MIN_ABBREV = 'pr'.size
|
|
10
12
|
NEED_STACK = true
|
|
11
13
|
end
|
|
@@ -46,7 +46,11 @@ info reg lfp # show lfp(0)
|
|
|
46
46
|
key_name = PREFIX.join('') + subcmd_name
|
|
47
47
|
remain_args = args[3..-1]
|
|
48
48
|
if all_regs.member?(key_name)
|
|
49
|
-
@subcmds.subcmds[key_name]
|
|
49
|
+
subcmd = @subcmds.subcmds[key_name]
|
|
50
|
+
if @proc.ok_for_running(subcmd, subcmd.class.const_get('CMD'),
|
|
51
|
+
remain_args.size)
|
|
52
|
+
@subcmds.subcmds[key_name].run(remain_args)
|
|
53
|
+
end
|
|
50
54
|
elsif unavailable_regs.member?(key_name)
|
|
51
55
|
msg("info registers: %s can not be displayed for frame type %s." %
|
|
52
56
|
[subcmd_name, @proc.frame.type])
|
|
@@ -5,16 +5,15 @@ require_relative 'helper'
|
|
|
5
5
|
|
|
6
6
|
class Trepan::Subcommand::InfoRegistersDfp < Trepan::SubSubcommand
|
|
7
7
|
unless defined?(HELP)
|
|
8
|
+
Trepanning::SubSubcommand.set_name_prefix(__FILE__, self)
|
|
8
9
|
HELP = 'Show the value of the VM dynamic frame pointer (DFP)'
|
|
9
10
|
MIN_ABBREV = 'df'.size
|
|
10
|
-
NAME = File.basename(__FILE__, '.rb')
|
|
11
11
|
NEED_STACK = true
|
|
12
|
-
PREFIX = %W(info registers #{NAME})
|
|
13
12
|
end
|
|
14
13
|
|
|
15
14
|
include Registers
|
|
16
15
|
def run(args)
|
|
17
|
-
register_array_index(PREFIX[-1], args)
|
|
16
|
+
register_array_index(PREFIX[-1], args[0])
|
|
18
17
|
end
|
|
19
18
|
end
|
|
20
19
|
|
|
@@ -1,18 +1,17 @@
|
|
|
1
|
-
# Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
|
|
1
|
+
# Copyright (C) 2010, 2011 Rocky Bernstein <rockyb@rubyforge.net>
|
|
2
2
|
module Registers
|
|
3
|
-
def register_array_index(name,
|
|
4
|
-
if
|
|
3
|
+
def register_array_index(name, arg, max_value=nil)
|
|
4
|
+
if !arg or arg.empty?
|
|
5
5
|
# Form is: "info xx" which means "info xx 0"
|
|
6
6
|
lookup_pos = position = 0
|
|
7
7
|
else
|
|
8
|
-
position_str = args[0]
|
|
9
8
|
opts = {
|
|
10
9
|
:msg_on_error =>
|
|
11
|
-
"The 'info registers %s' command argument must eval to an integer. Got: %s" % [name,
|
|
12
|
-
|
|
13
|
-
:max_value => max_value
|
|
10
|
+
"The 'info registers %s' command argument must eval to an integer. Got: %s" % [name, arg],
|
|
11
|
+
:min_value => -10,
|
|
12
|
+
:max_value => max_value + 10
|
|
14
13
|
}
|
|
15
|
-
position = @proc.get_an_int(
|
|
14
|
+
position = @proc.get_an_int(arg, opts)
|
|
16
15
|
return nil unless position
|
|
17
16
|
end
|
|
18
17
|
lookup_pos =
|
|
@@ -28,7 +27,7 @@ module Registers
|
|
|
28
27
|
# to do, possibly in the Ruby 1.9 interpeter, we'll handle
|
|
29
28
|
# this here. It is also conceivable to handle this in
|
|
30
29
|
# thread_frame's sp handling.
|
|
31
|
-
position +
|
|
30
|
+
position + 3
|
|
32
31
|
else
|
|
33
32
|
position
|
|
34
33
|
end
|
|
@@ -1,21 +1,26 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
|
-
# Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
|
|
2
|
+
# Copyright (C) 2010, 2011 Rocky Bernstein <rockyb@rubyforge.net>
|
|
3
3
|
require_relative '../../base/subsubcmd'
|
|
4
4
|
require_relative 'helper'
|
|
5
5
|
|
|
6
6
|
class Trepan::Subcommand::InfoRegistersLfp < Trepan::SubSubcommand
|
|
7
7
|
unless defined?(HELP)
|
|
8
|
-
|
|
8
|
+
Trepanning::SubSubcommand.set_name_prefix(__FILE__, self)
|
|
9
|
+
HELP = <<EOH
|
|
10
|
+
#{CMD} NUMBER
|
|
9
11
|
|
|
12
|
+
Show the value of the VM local frame pointer (LFP).
|
|
10
13
|
When a local variable is defined for the first time, this stack
|
|
11
14
|
is pushed and the value for local variable is assigned to this stack entry.
|
|
12
15
|
|
|
13
16
|
See also "info register sp".'
|
|
17
|
+
EOH
|
|
14
18
|
|
|
15
19
|
MIN_ABBREV = 'lf'.size
|
|
16
|
-
|
|
20
|
+
MIN_ARGS = 1
|
|
21
|
+
MAX_ARGS = 1
|
|
17
22
|
NEED_STACK = true
|
|
18
|
-
|
|
23
|
+
SHORT_HELP = "Show the value of the VM local frame pointer (LFP)."
|
|
19
24
|
end
|
|
20
25
|
|
|
21
26
|
include Registers
|
|
@@ -25,7 +30,7 @@ See also "info register sp".'
|
|
|
25
30
|
msg "local_name not available for C function"
|
|
26
31
|
else
|
|
27
32
|
iseq = frame.iseq
|
|
28
|
-
index = register_array_index(PREFIX[-1], args, iseq.local_size-1)
|
|
33
|
+
index = register_array_index(PREFIX[-1], args[0], iseq.local_size-1)
|
|
29
34
|
msg("local_name(%d)=%s" % [index, iseq.local_name(index)]) if index
|
|
30
35
|
end
|
|
31
36
|
end
|
|
@@ -1,19 +1,24 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
|
-
# Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
|
|
2
|
+
# Copyright (C) 2010, 2011 Rocky Bernstein <rockyb@rubyforge.net>
|
|
3
3
|
require_relative '../../base/subsubcmd'
|
|
4
4
|
|
|
5
5
|
class Trepan::SubSubcommand::InfoRegistersPc < Trepan::SubSubcommand
|
|
6
6
|
unless defined?(HELP)
|
|
7
|
-
|
|
7
|
+
Trepanning::SubSubcommand.set_name_prefix(__FILE__, self)
|
|
8
|
+
HELP = <<EOH
|
|
9
|
+
#{CMD}
|
|
8
10
|
|
|
11
|
+
Show the value of the VM program counter (PC).
|
|
9
12
|
The VM program is an offset into the instruction sequence for the next
|
|
10
13
|
VM instruction in the sequence to be executed.
|
|
11
14
|
|
|
12
15
|
See also "info disassemble" and "info registers".'
|
|
16
|
+
EOH
|
|
13
17
|
MIN_ABBREV = 'pc'.size
|
|
14
|
-
NAME = File.basename(__FILE__, '.rb')
|
|
15
18
|
NEED_STACK = true
|
|
16
|
-
|
|
19
|
+
MIN_ARGS = 0
|
|
20
|
+
MAX_ARGS = 0
|
|
21
|
+
SHORT_HELP = 'Show the value of the VM program counter (PC).'
|
|
17
22
|
end
|
|
18
23
|
|
|
19
24
|
def run(args)
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
|
-
# Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
|
|
2
|
+
# Copyright (C) 2010, 2011 Rocky Bernstein <rockyb@rubyforge.net>
|
|
3
3
|
require_relative '../../base/subsubcmd'
|
|
4
4
|
require_relative 'helper'
|
|
5
5
|
|
|
6
6
|
class Trepan::Subcommand::InfoRegistersSp < Trepan::SubSubcommand
|
|
7
7
|
unless defined?(HELP)
|
|
8
|
-
|
|
8
|
+
Trepanning::SubSubcommand.set_name_prefix(__FILE__, self)
|
|
9
9
|
HELP = <<EOH
|
|
10
|
-
|
|
11
|
-
info register #{NAME} [NUMBER NUMBER ...|size]
|
|
10
|
+
#{CMD} [NUMBER NUMBER ...|size]
|
|
12
11
|
|
|
13
12
|
With no arguments, all SP values for the current frame of the debugged
|
|
14
13
|
program are shown. If a number is given, then the entry at that
|
|
@@ -26,7 +25,7 @@ EOH
|
|
|
26
25
|
|
|
27
26
|
MIN_ABBREV = 'sp'.size
|
|
28
27
|
NEED_STACK = true
|
|
29
|
-
|
|
28
|
+
SHORT_HELP = "Show value(s) of the VM stack pointer (SP)."
|
|
30
29
|
end
|
|
31
30
|
|
|
32
31
|
include Registers
|
|
@@ -15,8 +15,10 @@ See also constants: RUBY_DESCRIPTION, RUBY_VERSION, and RUBY_RELEASE_DATE."
|
|
|
15
15
|
EOH
|
|
16
16
|
MIN_ABBREV = 'ru'.size
|
|
17
17
|
NEED_STACK = false
|
|
18
|
+
MIN_ARGS = 0
|
|
19
|
+
MAX_ARGS = 0
|
|
18
20
|
SHORT_HELP = 'Ruby version information'
|
|
19
|
-
|
|
21
|
+
end
|
|
20
22
|
|
|
21
23
|
# def parse_options(args) # :nodoc
|
|
22
24
|
# options = {}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Copyright (C) 2011 Rocky Bernstein <rockyb@rubyforge.net>
|
|
3
|
+
require 'pp'
|
|
4
|
+
require 'linecache'
|
|
5
|
+
require 'columnize'
|
|
6
|
+
require_relative '../base/subcmd'
|
|
7
|
+
require_relative '../../../app/file'
|
|
8
|
+
require_relative '../../../app/complete'
|
|
9
|
+
|
|
10
|
+
class Trepan::Subcommand::InfoSource < Trepan::Subcommand
|
|
11
|
+
unless defined?(HELP)
|
|
12
|
+
Trepanning::Subcommand.set_name_prefix(__FILE__, self)
|
|
13
|
+
DEFAULT_FILE_ARGS = %w(size mtime sha1)
|
|
14
|
+
|
|
15
|
+
HELP = <<-EOH
|
|
16
|
+
#{CMD}
|
|
17
|
+
|
|
18
|
+
Show information about the current source file.
|
|
19
|
+
EOH
|
|
20
|
+
MAX_ARGS = 0
|
|
21
|
+
MIN_ABBREV = 'so'.size # Note we have "info frame"
|
|
22
|
+
NEED_STACK = true
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# completion %w(all brkpts iseq sha1 size stat)
|
|
26
|
+
|
|
27
|
+
include Trepanning
|
|
28
|
+
|
|
29
|
+
# Get file information
|
|
30
|
+
def run(args)
|
|
31
|
+
if not @proc.frame
|
|
32
|
+
errmsg('No frame - no default file.')
|
|
33
|
+
return false
|
|
34
|
+
end
|
|
35
|
+
frame_file = @proc.frame.source_container[1]
|
|
36
|
+
filename = LineCache::map_file(frame_file) || File.expand_path(frame_file)
|
|
37
|
+
canonic_name = @proc.canonic_file(filename)
|
|
38
|
+
canonic_name = LineCache::map_file(canonic_name) || canonic_name
|
|
39
|
+
m = filename
|
|
40
|
+
if LineCache::cached?(canonic_name)
|
|
41
|
+
m += ' is cached in debugger'
|
|
42
|
+
if canonic_name != filename
|
|
43
|
+
m += (' as:\n ' + canonic_name)
|
|
44
|
+
end
|
|
45
|
+
m += '.'
|
|
46
|
+
msg(m)
|
|
47
|
+
end
|
|
48
|
+
max_line = LineCache::size(canonic_name)
|
|
49
|
+
msg 'File has %d lines.' % max_line if max_line
|
|
50
|
+
msg('SHA1 is %s.' % LineCache::sha1(canonic_name))
|
|
51
|
+
msg('Possible breakpoint line numbers:')
|
|
52
|
+
lines = LineCache.trace_line_numbers(canonic_name)
|
|
53
|
+
fmt_lines = columnize_numbers(lines)
|
|
54
|
+
msg(fmt_lines)
|
|
55
|
+
if SCRIPT_ISEQS__.member?(canonic_name)
|
|
56
|
+
msg("File contains instruction sequences:")
|
|
57
|
+
SCRIPT_ISEQS__[canonic_name].each do |iseq|
|
|
58
|
+
msg("\t%s %s" % [iseq, iseq.name.inspect])
|
|
59
|
+
end
|
|
60
|
+
else
|
|
61
|
+
msg("Instruction sequences not recorded; there may be some, though.")
|
|
62
|
+
end
|
|
63
|
+
msg("Stat info:\n\t%s" % LineCache::stat(canonic_name).pretty_inspect)
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
if __FILE__ == $0
|
|
68
|
+
if !(ARGV.size == 1 && ARGV[0] == 'noload')
|
|
69
|
+
ISEQS__ = {}
|
|
70
|
+
SCRIPT_ISEQS__ = {}
|
|
71
|
+
ARGV[0..-1] = ['noload']
|
|
72
|
+
load(__FILE__)
|
|
73
|
+
else
|
|
74
|
+
require_relative '../../mock'
|
|
75
|
+
cmd = MockDebugger::sub_setup(Trepan::Subcommand::InfoSource, false)
|
|
76
|
+
cmd.run(cmd.prefix)
|
|
77
|
+
end
|
|
78
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Copyright (C) 2011 Rocky Bernstein <rockyb@rubyforge.net>
|
|
3
|
+
require_relative '../base/subcmd'
|
|
4
|
+
|
|
5
|
+
class Trepan::Subcommand::InfoStack < Trepan::Subcommand
|
|
6
|
+
unless defined?(HELP)
|
|
7
|
+
Trepanning::Subcommand.set_name_prefix(__FILE__, self)
|
|
8
|
+
HELP = 'Same thing as "backtrace"'
|
|
9
|
+
MIN_ABBREV = 'st'.size
|
|
10
|
+
NEED_STACK = true
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def run(args)
|
|
14
|
+
@proc.commands['backtrace'].run(['backtrace'] + args[2..-1])
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
if __FILE__ == $0
|
|
19
|
+
# Demo it.
|
|
20
|
+
require_relative '../../mock'
|
|
21
|
+
cmd = MockDebugger::sub_setup(Trepan::Subcommand::InfoStack, false)
|
|
22
|
+
cmd.run(cmd.prefix)
|
|
23
|
+
end
|
data/processor/command/kill.rb
CHANGED
|
@@ -50,18 +50,16 @@ Examples:
|
|
|
50
50
|
errmsg("Signal name '#{sig}' is not a signal I know about.\n")
|
|
51
51
|
return false
|
|
52
52
|
end
|
|
53
|
-
if 'KILL' == sig || Signal['KILL'] == sig
|
|
54
|
-
@proc.intf.finalize
|
|
55
|
-
end
|
|
56
53
|
else
|
|
57
|
-
if
|
|
54
|
+
if unconditional || confirm('Really quit?', false)
|
|
55
|
+
sig = 'KILL'
|
|
56
|
+
else
|
|
58
57
|
msg('Kill not confirmed.')
|
|
59
58
|
return
|
|
60
|
-
else
|
|
61
|
-
sig = 'KILL'
|
|
62
59
|
end
|
|
63
60
|
end
|
|
64
61
|
begin
|
|
62
|
+
@proc.intf.finalize if 'KILL' == sig || Signal['KILL'] == sig
|
|
65
63
|
Process.kill(sig, Process.pid)
|
|
66
64
|
rescue Errno::ESRCH
|
|
67
65
|
errmsg "Unable to send kill #{sig} to process #{Process.pid}"
|
data/processor/command/list.rb
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
# -*- coding: utf-8 -*-
|
|
3
3
|
require 'linecache'
|
|
4
4
|
require_relative 'base/cmd'
|
|
5
|
+
require_relative '../../app/cmd_parse'
|
|
5
6
|
|
|
6
7
|
class Trepan::Command::ListCommand < Trepan::Command
|
|
7
8
|
unless defined?(HELP)
|
|
@@ -49,11 +50,11 @@ just something that evaluates to a positive integer.
|
|
|
49
50
|
Some examples:
|
|
50
51
|
|
|
51
52
|
#{NAME} 5 # List centered around line 5
|
|
52
|
-
#{NAME}
|
|
53
|
+
#{NAME} @5 # List lines centered around bytecode offset 5.
|
|
53
54
|
#{NAME} 5> # List starting at line 5
|
|
54
55
|
#{NAME} foo.rb:5 # List centered around line 5 of foo.rb
|
|
55
56
|
#{NAME} foo.rb 5 # Same as above.
|
|
56
|
-
#{NAME} foo.rb:5
|
|
57
|
+
#{NAME}> foo.rb:5 # List starting around line 5 of foo.rb
|
|
57
58
|
#{NAME} foo.rb 5 6 # list lines 5 and 6 of foo.rb
|
|
58
59
|
#{NAME} foo.rb 5 2 # Same as above, since 2 < 5.
|
|
59
60
|
#{NAME} foo.rb:5 2 # Same as above
|
|
@@ -63,7 +64,7 @@ Some examples:
|
|
|
63
64
|
# if . > 3. Otherwise we list from . to 3.
|
|
64
65
|
#{NAME} - # List lines previous to those just shown
|
|
65
66
|
|
|
66
|
-
The output of the #{NAME} command
|
|
67
|
+
The output of the #{NAME} command gives a line number, and some status
|
|
67
68
|
information about the line and the text of the line. Here is some
|
|
68
69
|
hypothetical #{NAME} output modeled roughly around line 251 of one
|
|
69
70
|
version of this code:
|
|
@@ -86,25 +87,19 @@ disabled.
|
|
|
86
87
|
SHORT_HELP = 'List source code'
|
|
87
88
|
end
|
|
88
89
|
|
|
90
|
+
include Trepan::CmdParser
|
|
91
|
+
|
|
89
92
|
# If last is less than first, assume last is a count rather than an
|
|
90
93
|
# end line number.
|
|
91
94
|
def adjust_last(first, last)
|
|
92
95
|
last < first ? first + last - 1 : last
|
|
93
96
|
end
|
|
94
97
|
|
|
95
|
-
|
|
96
|
-
# allow somewhat flexible parsing with either module names, files or none
|
|
97
|
-
# and optional line counts or end-line numbers.
|
|
98
|
-
|
|
99
|
-
# Parses arguments for the "list" command and returns the tuple:
|
|
100
|
-
# filename, start, last
|
|
101
|
-
# or sets these to nil if there was some problem.
|
|
102
|
-
def parse_list_cmd(args, listsize, center_correction)
|
|
103
|
-
|
|
98
|
+
def frame_filename
|
|
104
99
|
frame = @proc.frame
|
|
105
100
|
|
|
106
101
|
container = @proc.frame_container(frame, false)
|
|
107
|
-
|
|
102
|
+
|
|
108
103
|
# FIXME: put into a helper routine
|
|
109
104
|
# See also duplicate code in print_location
|
|
110
105
|
if container[0] != 'file'
|
|
@@ -115,84 +110,74 @@ disabled.
|
|
|
115
110
|
end
|
|
116
111
|
container = try_container if try_container[0] == 'file'
|
|
117
112
|
end
|
|
118
|
-
|
|
119
|
-
filename = container[1]
|
|
120
|
-
|
|
121
|
-
last = nil
|
|
122
|
-
if args.empty? and not frame
|
|
123
|
-
errmsg("No Ruby program loaded.")
|
|
124
|
-
return nil, nil, nil
|
|
125
|
-
end
|
|
126
113
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
return no_frame_msg unless @proc.line_no
|
|
130
|
-
first = [1, @proc.line_no - 2*listsize - 1].max
|
|
131
|
-
elsif args[0] == '.'
|
|
132
|
-
return no_frame_msg unless @proc.line_no
|
|
133
|
-
if args.size == 2
|
|
134
|
-
opts = {
|
|
135
|
-
:msg_on_error =>
|
|
136
|
-
"#{NAME} command last or count parameter expected, " +
|
|
137
|
-
'got: %s.' % args[2]
|
|
138
|
-
}
|
|
139
|
-
second = @proc.get_an_int(args[1], opts)
|
|
140
|
-
return nil, nil, nil unless second
|
|
141
|
-
first = @proc.frame_line
|
|
142
|
-
last = adjust_last(first, second)
|
|
143
|
-
else
|
|
144
|
-
first = [1, @proc.frame_line - center_correction].max
|
|
145
|
-
end
|
|
114
|
+
return container[1]
|
|
115
|
+
end
|
|
146
116
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
117
|
+
|
|
118
|
+
# What a f*cking mess. Necessitated I suppose because we want to
|
|
119
|
+
# allow somewhat flexible parsing with either module names, files or none
|
|
120
|
+
# and optional line counts or end-line numbers.
|
|
121
|
+
|
|
122
|
+
# Parses arguments for the "list" command and returns the tuple:
|
|
123
|
+
# filename, start, last
|
|
124
|
+
# or sets these to nil if there was some problem.
|
|
125
|
+
def parse_list_cmd(arg_str, listsize, center_correction)
|
|
126
|
+
|
|
127
|
+
iseq = nil
|
|
128
|
+
if arg_str.empty?
|
|
129
|
+
filename = frame_filename
|
|
130
|
+
first = [1, @proc.frame_line - center_correction].max
|
|
131
|
+
else
|
|
132
|
+
list_cmd_parse = parse_list(arg_str,
|
|
133
|
+
:file_exists_proc => @proc.file_exists_proc)
|
|
134
|
+
last = list_cmd_parse.num
|
|
135
|
+
position = list_cmd_parse.position
|
|
136
|
+
|
|
137
|
+
if position.is_a?(String)
|
|
138
|
+
if position == '-'
|
|
139
|
+
return no_frame_msg unless @proc.line_no
|
|
140
|
+
first = [1, @proc.line_no - 2*listsize - 1].max
|
|
141
|
+
elsif position == '.'
|
|
142
|
+
return no_frame_msg unless @proc.line_no
|
|
143
|
+
if (second = list_cmd_parse.num)
|
|
144
|
+
first = @proc.frame_line
|
|
145
|
+
last = adjust_last(first, second)
|
|
146
|
+
else
|
|
147
|
+
first = [1, @proc.frame_line - center_correction].max
|
|
148
|
+
last = first + listsize - 1
|
|
174
149
|
end
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
150
|
+
end
|
|
151
|
+
filename = frame_filename
|
|
152
|
+
else
|
|
153
|
+
meth, filename, offset, offset_type = @proc.parse_position(position)
|
|
154
|
+
iseq = meth.iseq if meth
|
|
155
|
+
return unless filename
|
|
156
|
+
if offset_type == :line
|
|
157
|
+
first = offset
|
|
158
|
+
elsif meth
|
|
159
|
+
iseq, first, vm_offset =
|
|
160
|
+
@proc.position_to_line_and_offset(meth.iseq, filename,
|
|
161
|
+
position, offset_type)
|
|
162
|
+
return [nil] * 3 unless first
|
|
163
|
+
elsif !offset
|
|
164
|
+
# Have just a filename. Go with line 1
|
|
165
|
+
first = 1
|
|
180
166
|
else
|
|
181
|
-
errmsg
|
|
182
|
-
|
|
183
|
-
return nil, nil, nil
|
|
167
|
+
errmsg "Dunno what to do here"
|
|
168
|
+
return [nil] * 3
|
|
184
169
|
end
|
|
185
170
|
end
|
|
186
|
-
|
|
187
|
-
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
if last
|
|
174
|
+
last = adjust_last(first, last)
|
|
188
175
|
else
|
|
189
|
-
first = [1,
|
|
176
|
+
first = [1, first - center_correction].max
|
|
177
|
+
last = first + listsize - 1 unless last
|
|
190
178
|
end
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
LineCache::cache(container[1]) unless
|
|
194
|
-
'file' != container[0] || LineCache::cached?(container[1])
|
|
195
|
-
return container, first, last
|
|
179
|
+
LineCache::cache(filename) unless LineCache::cached?(filename)
|
|
180
|
+
return iseq, filename, first, last
|
|
196
181
|
end
|
|
197
182
|
|
|
198
183
|
def no_frame_msg
|
|
@@ -201,6 +186,10 @@ disabled.
|
|
|
201
186
|
end
|
|
202
187
|
|
|
203
188
|
def run(args)
|
|
189
|
+
if args.empty? and not frame
|
|
190
|
+
errmsg("No Ruby program loaded.")
|
|
191
|
+
return
|
|
192
|
+
end
|
|
204
193
|
listsize = settings[:maxlist]
|
|
205
194
|
center_correction =
|
|
206
195
|
if args[0][-1..-1] == '>'
|
|
@@ -209,22 +198,22 @@ disabled.
|
|
|
209
198
|
(listsize-1) / 2
|
|
210
199
|
end
|
|
211
200
|
|
|
212
|
-
|
|
213
|
-
parse_list_cmd(
|
|
214
|
-
|
|
215
|
-
|
|
201
|
+
iseq, filename, first, last =
|
|
202
|
+
parse_list_cmd(@proc.cmd_argstr, listsize, center_correction)
|
|
203
|
+
return unless filename
|
|
204
|
+
container = iseq ? iseq.source_container : ['file', filename]
|
|
216
205
|
breaklist = @proc.brkpts.line_breaks(container)
|
|
217
206
|
|
|
218
207
|
# We now have range information. Do the listing.
|
|
219
|
-
max_line = LineCache::size(
|
|
208
|
+
max_line = LineCache::size(filename)
|
|
220
209
|
unless max_line
|
|
221
|
-
errmsg('File "%s" not found.' %
|
|
210
|
+
errmsg('File "%s" not found.' % filename)
|
|
222
211
|
return
|
|
223
212
|
end
|
|
224
213
|
|
|
225
214
|
if first > max_line
|
|
226
215
|
errmsg('Bad line range [%d...%d]; file "%s" has only %d lines' %
|
|
227
|
-
[first, last,
|
|
216
|
+
[first, last, filename, max_line])
|
|
228
217
|
return
|
|
229
218
|
end
|
|
230
219
|
|
|
@@ -235,11 +224,12 @@ disabled.
|
|
|
235
224
|
|
|
236
225
|
begin
|
|
237
226
|
opts = {
|
|
238
|
-
:reload_on_change =>
|
|
227
|
+
:reload_on_change => settings[:reload],
|
|
239
228
|
:output => settings[:highlight]
|
|
240
229
|
}
|
|
230
|
+
frame = @proc.frame
|
|
241
231
|
first.upto(last).each do |lineno|
|
|
242
|
-
line = LineCache::getline(
|
|
232
|
+
line = LineCache::getline(filename, lineno, opts)
|
|
243
233
|
unless line
|
|
244
234
|
msg('[EOF]')
|
|
245
235
|
break
|
|
@@ -256,7 +246,7 @@ disabled.
|
|
|
256
246
|
' '
|
|
257
247
|
end
|
|
258
248
|
s += (frame && lineno == @proc.frame_line &&
|
|
259
|
-
|
|
249
|
+
filename == frame.source_container[1]) ? '->' : a_pad
|
|
260
250
|
msg(s + "\t" + line, {:unlimited => true})
|
|
261
251
|
@proc.line_no = lineno
|
|
262
252
|
end
|
|
@@ -278,69 +268,77 @@ if __FILE__ == $0
|
|
|
278
268
|
require_relative '../frame'
|
|
279
269
|
dbgr, cmd = MockDebugger::setup
|
|
280
270
|
cmd.proc.send('frame_initialize')
|
|
281
|
-
LineCache::cache(__FILE__)
|
|
282
|
-
cmd.run([cmd.name])
|
|
283
|
-
cmd.run([cmd.name, __FILE__ + ':10'])
|
|
284
271
|
|
|
285
272
|
def run_cmd(cmd, args)
|
|
273
|
+
cmd.proc.instance_variable_set('@cmd_argstr', args[1..-1].join(' '))
|
|
274
|
+
cmd.run(args)
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
LineCache::cache(__FILE__)
|
|
278
|
+
run_cmd(cmd, [cmd.name])
|
|
279
|
+
run_cmd(cmd, [cmd.name, __FILE__ + ':10'])
|
|
280
|
+
|
|
281
|
+
def run_cmd2(cmd, args)
|
|
286
282
|
seps = '--' * 10
|
|
287
283
|
puts "%s %s %s" % [seps, args.join(' '), seps]
|
|
288
|
-
cmd
|
|
284
|
+
run_cmd(cmd,args)
|
|
289
285
|
end
|
|
290
286
|
|
|
291
287
|
|
|
292
288
|
load 'tmpdir.rb'
|
|
293
|
-
|
|
294
|
-
|
|
289
|
+
run_cmd2(cmd, %w(list tmpdir.rb 10))
|
|
290
|
+
run_cmd2(cmd, %w(list tmpdir.rb))
|
|
295
291
|
|
|
296
292
|
# cmd.proc.frame = sys._getframe()
|
|
297
293
|
# cmd.proc.setup()
|
|
298
|
-
#
|
|
294
|
+
# run_cmd2(['list'])
|
|
299
295
|
|
|
300
|
-
|
|
301
|
-
|
|
296
|
+
run_cmd2(cmd, %w(list .))
|
|
297
|
+
run_cmd2(cmd, %w(list 30))
|
|
302
298
|
|
|
303
|
-
#
|
|
299
|
+
# run_cmd2(['list', '9+1'])
|
|
304
300
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
301
|
+
run_cmd2(cmd, %w(list> 10))
|
|
302
|
+
run_cmd2(cmd, %w(list 3000))
|
|
303
|
+
run_cmd2(cmd, %w(list run_cmd2))
|
|
308
304
|
|
|
309
305
|
p = Proc.new do
|
|
310
306
|
|x,y| x + y
|
|
311
307
|
end
|
|
312
|
-
|
|
308
|
+
require 'thread_frame'
|
|
309
|
+
tf = RubyVM::ThreadFrame.current
|
|
310
|
+
cmd.proc.frame_setup(tf)
|
|
311
|
+
run_cmd2(cmd, %w(list p))
|
|
313
312
|
|
|
314
313
|
# Function from a file found via an instruction sequence
|
|
315
|
-
|
|
314
|
+
run_cmd2(cmd, %w(list Columnize.columnize))
|
|
316
315
|
|
|
317
316
|
# Use Class/method name. 15 isn't in the function - should this be okay?
|
|
318
|
-
|
|
317
|
+
run_cmd2(cmd, %W(#{cmd.name} Columnize.columnize 15))
|
|
319
318
|
|
|
320
319
|
# Start line and count, since 3 < 30
|
|
321
|
-
|
|
320
|
+
run_cmd2(cmd, %W(#{cmd.name} Columnize.columnize 30 3))
|
|
322
321
|
|
|
323
322
|
# Start line finish line
|
|
324
|
-
|
|
323
|
+
run_cmd2(cmd, %W(#{cmd.name} Columnize.columnize 40 50))
|
|
325
324
|
|
|
326
325
|
# puts '--' * 10
|
|
327
|
-
#
|
|
326
|
+
# run_cmd2([cmd.name, os.path.abspath(__file__)+':3', '4'])
|
|
328
327
|
# puts '--' * 10
|
|
329
|
-
#
|
|
330
|
-
#
|
|
328
|
+
# run_cmd2([cmd.name, os.path.abspath(__file__)+':3', '12-10'])
|
|
329
|
+
# run_cmd2([cmd.name, 'os.path:5'])
|
|
331
330
|
|
|
332
|
-
require 'thread_frame'
|
|
333
|
-
tf = RubyVM::ThreadFrame.current
|
|
334
|
-
cmd.proc.frame_setup(tf)
|
|
335
331
|
brkpt_cmd = cmd.proc.instance_variable_get('@commands')['break']
|
|
336
332
|
brkpt_cmd.run(['break'])
|
|
337
333
|
line = __LINE__
|
|
338
|
-
|
|
334
|
+
run_cmd2(cmd, [cmd.name, __LINE__.to_s])
|
|
339
335
|
|
|
340
336
|
disable_cmd = cmd.proc.instance_variable_get('@commands')['disable']
|
|
341
337
|
disable_cmd.run(['disable', '1'])
|
|
342
338
|
|
|
343
|
-
|
|
344
|
-
|
|
339
|
+
run_cmd2(cmd, [cmd.name, line.to_s])
|
|
340
|
+
run_cmd2(cmd, %W(#{cmd.name} run_cmd2))
|
|
341
|
+
run_cmd2(cmd, %W(#{cmd.name} run_cmd2))
|
|
342
|
+
run_cmd2(cmd, %W(#{cmd.name} @713))
|
|
345
343
|
end
|
|
346
344
|
end
|