trepanning 0.1.2 → 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|