rbx-trepanning 0.0.8-universal-rubinius-1.2 → 0.1.0-universal-rubinius-1.2
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog +762 -238
- data/NEWS +44 -0
- data/Rakefile +61 -32
- data/app/breakpoint.rb +2 -0
- data/app/brkptmgr.rb +9 -11
- data/app/client.rb +0 -1
- data/app/cmd_parse.kpeg +21 -4
- data/app/cmd_parse.rb +10 -10
- data/app/cmd_parser.rb +1029 -840
- data/app/complete.rb +1 -1
- data/app/display.rb +38 -0
- data/app/file.rb +24 -0
- data/app/frame.rb +11 -4
- data/app/irb.rb +41 -39
- data/app/iseq.rb +71 -0
- data/app/options.rb +55 -30
- data/app/rbx-llvm.rb +0 -2
- data/app/run.rb +13 -9
- data/app/util.rb +55 -5
- data/bin/trepanx +3 -3
- data/data/irbrc +13 -13
- data/{interface/base_intf.rb → interface.rb} +5 -1
- data/interface/client.rb +4 -0
- data/interface/script.rb +13 -5
- data/interface/server.rb +5 -1
- data/interface/user.rb +8 -1
- data/{io/base_io.rb → io.rb} +0 -0
- data/io/input.rb +1 -1
- data/io/null_output.rb +28 -24
- data/io/string_array.rb +2 -3
- data/io/tcpclient.rb +1 -1
- data/io/tcpserver.rb +1 -1
- data/lib/trepanning.rb +11 -13
- data/{processor/main.rb → processor.rb} +50 -54
- data/processor/breakpoint.rb +150 -137
- data/processor/{command/base/cmd.rb → command.rb} +1 -1
- data/processor/command/alias.rb +14 -3
- data/processor/command/backtrace.rb +2 -1
- data/processor/command/base/subcmd.rb +1 -5
- data/processor/command/base/submgr.rb +5 -2
- data/processor/command/base/subsubcmd.rb +1 -1
- data/processor/command/base/subsubmgr.rb +4 -4
- data/processor/command/break.rb +1 -1
- data/processor/command/complete.rb +2 -1
- data/processor/command/condition.rb +2 -2
- data/processor/command/continue.rb +4 -4
- data/processor/command/delete.rb +34 -20
- data/processor/command/directory.rb +4 -4
- data/processor/command/disable.rb +71 -0
- data/processor/command/disassemble.rb +55 -22
- data/processor/command/display.rb +3 -1
- data/processor/command/down.rb +8 -8
- data/processor/command/edit.rb +74 -0
- data/processor/command/enable.rb +43 -0
- data/processor/command/eval.rb +37 -15
- data/processor/command/exit.rb +25 -6
- data/processor/command/finish.rb +5 -5
- data/processor/command/frame.rb +2 -2
- data/processor/command/help.rb +7 -9
- data/processor/command/help/README +10 -0
- data/processor/command/help/command.txt +37 -27
- data/processor/command/help/examples.txt +16 -0
- data/processor/command/help/filename.txt +1 -1
- data/processor/command/help/suffixes.txt +17 -0
- data/processor/command/info.rb +3 -1
- data/processor/command/info_subcmd/files.rb +3 -2
- data/processor/command/info_subcmd/frame.rb +2 -1
- data/processor/command/info_subcmd/line.rb +17 -28
- data/processor/command/info_subcmd/locals.rb +22 -0
- data/processor/command/{show_subcmd → info_subcmd}/macro.rb +4 -4
- data/processor/command/info_subcmd/program.rb +2 -0
- data/processor/command/info_subcmd/ruby.rb +2 -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 +23 -36
- 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 +8 -9
- data/processor/command/list.rb +101 -167
- data/processor/command/macro.rb +28 -10
- data/processor/command/next.rb +2 -1
- data/processor/command/nexti.rb +1 -1
- data/processor/command/parsetree.rb +51 -0
- data/processor/command/pr.rb +1 -2
- data/processor/command/ps.rb +1 -1
- data/processor/command/restart.rb +2 -2
- data/processor/command/save.rb +1 -1
- data/processor/command/server.rb +1 -1
- data/processor/command/set_subcmd/abbrev.rb +25 -0
- data/processor/command/set_subcmd/auto.rb +7 -1
- 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/different.rb +1 -1
- data/processor/command/set_subcmd/highlight.rb +7 -1
- data/processor/command/set_subcmd/reload.rb +42 -0
- data/processor/command/set_subcmd/timer.rb +58 -0
- data/processor/command/set_subcmd/trace.rb +4 -3
- data/processor/command/{irb.rb → shell.rb} +22 -19
- data/processor/command/show_subcmd/abbrev.rb +20 -0
- data/processor/command/show_subcmd/{alias.rb → aliases.rb} +2 -2
- data/processor/command/show_subcmd/auto_subcmd/eval.rb +2 -6
- data/processor/command/show_subcmd/directories.rb +22 -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 +18 -0
- data/processor/command/show_subcmd/timer.rb +18 -0
- data/processor/command/source.rb +9 -9
- data/processor/command/step.rb +1 -1
- data/processor/command/tbreak.rb +3 -2
- data/processor/command/unalias.rb +11 -6
- data/processor/command/undisplay.rb +13 -9
- data/processor/command/up.rb +13 -14
- data/processor/default.rb +47 -44
- data/processor/disassemble.rb +48 -35
- data/processor/display.rb +38 -3
- data/processor/eval.rb +54 -53
- data/processor/eventbuf.rb +69 -69
- data/processor/frame.rb +186 -187
- data/processor/help.rb +6 -4
- data/processor/hook.rb +103 -102
- data/processor/list.rb +123 -0
- data/processor/load_cmds.rb +9 -1
- data/processor/location.rb +193 -188
- data/processor/mock.rb +1 -7
- data/processor/msg.rb +56 -42
- data/processor/running.rb +26 -15
- data/processor/stepping.rb +2 -1
- data/processor/subcmd.rb +18 -43
- data/processor/validate.rb +41 -30
- data/processor/virtual.rb +33 -0
- data/rbx-trepanning.gemspec +7 -8
- data/sample/rocky-trepanx-colors.rb +0 -1
- data/test/data/fname-with-blank.right +2 -0
- data/test/data/inline-call.right +11 -10
- data/test/data/quit.right +1 -0
- data/test/example/debugger-stop.rb +1 -1
- data/test/example/goto2goto.rb +11 -0
- data/test/functional/fn_helper.rb +2 -2
- data/test/functional/test-list.rb +7 -6
- data/test/integration/helper.rb +5 -5
- data/test/unit/cmd-helper.rb +2 -6
- data/test/unit/test-app-cmd_parser.rb +3 -2
- data/test/unit/test-app-display.rb +22 -0
- data/test/unit/test-app-options.rb +14 -10
- data/test/unit/test-app-run.rb +0 -2
- data/test/unit/test-app-util.rb +21 -4
- data/test/unit/test-base-cmd.rb +5 -7
- data/test/unit/test-base-subcmd.rb +1 -5
- data/test/unit/test-base-submgr.rb +1 -1
- data/test/unit/test-base-subsubcmd.rb +0 -4
- data/test/unit/test-bin-trepanx.rb +2 -2
- data/test/unit/test-cmd-break.rb +2 -0
- data/test/unit/test-cmd-edit.rb +34 -0
- data/test/unit/test-cmd-kill.rb +11 -4
- data/test/unit/test-cmd-parse_list_cmd.rb +36 -0
- data/test/unit/test-command.rb +45 -0
- data/test/unit/test-completion.rb +1 -1
- data/test/unit/test-proc-eval.rb +1 -2
- data/test/unit/test-proc-frame.rb +5 -3
- data/test/unit/test-proc-list.rb +55 -0
- data/test/unit/test-proc-load_cmds.rb +4 -3
- data/test/unit/test-proc-location.rb +32 -29
- data/test/unit/test-proc-main.rb +1 -5
- data/test/unit/test-proc-validate.rb +14 -4
- data/test/unit/test-subcmd-help.rb +1 -5
- metadata +73 -107
@@ -0,0 +1,42 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
# Copyright (C) 2010, 2011 Rocky Bernstein <rockyb@rubyforge.net>
|
3
|
+
require 'rubygems'; require 'require_relative'
|
4
|
+
require_relative 'locals'
|
5
|
+
|
6
|
+
class Trepan::Subcommand::InfoVariablesConstant <
|
7
|
+
Trepan::Subcommand::InfoVariablesLocals
|
8
|
+
Trepan::Util.suppress_warnings {
|
9
|
+
Trepanning::Subcommand.set_name_prefix(__FILE__, self)
|
10
|
+
HELP = <<-EOH
|
11
|
+
#{CMD}
|
12
|
+
#{CMD} [names]
|
13
|
+
|
14
|
+
Show class constants of the current stack frame.
|
15
|
+
Normally for each which show both the name and value. If you just
|
16
|
+
want a list of names add parameter 'names'.
|
17
|
+
EOH
|
18
|
+
SHORT_HELP = 'Show class constants via the current stack frame'
|
19
|
+
MIN_ABBREV = 'co'.size
|
20
|
+
MIN_ARGS = 0
|
21
|
+
MAX_ARGS = 1
|
22
|
+
NEED_STACK = true
|
23
|
+
}
|
24
|
+
|
25
|
+
def get_names
|
26
|
+
@proc.debug_eval_no_errmsg('self.class.constants.sort') || []
|
27
|
+
end
|
28
|
+
|
29
|
+
def run(args)
|
30
|
+
run_for_type(args, 'constant', @proc.debug_eval('self'))
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
if __FILE__ == $0
|
35
|
+
# Demo it.
|
36
|
+
require_relative '../../mock'
|
37
|
+
cmd =
|
38
|
+
MockDebugger::subsub_setup(Trepan::Subcommand::InfoVariables,
|
39
|
+
Trepan::Subcommand::InfoVariablesConstant)
|
40
|
+
cmd.run(cmd.prefix)
|
41
|
+
cmd.run(cmd.prefix + ['name'])
|
42
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
# Copyright (C) 2010, 2011 Rocky Bernstein <rockyb@rubyforge.net>
|
3
|
+
require 'rubygems'; require 'require_relative'
|
4
|
+
require_relative 'locals'
|
5
|
+
|
6
|
+
class Trepan::SubSubcommand::InfoVariablesGlobals < Trepan::SubSubcommand
|
7
|
+
Trepan::Util.suppress_warnings {
|
8
|
+
Trepanning::Subcommand.set_name_prefix(__FILE__, self)
|
9
|
+
HELP = <<-EOH
|
10
|
+
#{CMD}
|
11
|
+
#{CMD} [names]
|
12
|
+
|
13
|
+
Show global variables.
|
14
|
+
Normally for each which show both the name and value. If you just
|
15
|
+
want a list of names add parameter 'names'.
|
16
|
+
EOH
|
17
|
+
SHORT_HELP = 'Show global variables'
|
18
|
+
MIN_ARGS = 0
|
19
|
+
MAX_ARGS = 1
|
20
|
+
NEED_STACK = true
|
21
|
+
}
|
22
|
+
|
23
|
+
def get_names
|
24
|
+
global_variables.sort
|
25
|
+
end
|
26
|
+
|
27
|
+
def run(args)
|
28
|
+
if args.size == 2
|
29
|
+
if 0 == 'names'.index(args[-1].downcase)
|
30
|
+
names = get_names()
|
31
|
+
if names.empty?
|
32
|
+
msg "No global variables defined."
|
33
|
+
else
|
34
|
+
section "Global variable names:"
|
35
|
+
width = settings[:maxwidth]
|
36
|
+
mess = Columnize::columnize(names,
|
37
|
+
@proc.settings[:maxwidth], ' ',
|
38
|
+
false, true, ' ' * 2).chomp
|
39
|
+
msg mess
|
40
|
+
end
|
41
|
+
else
|
42
|
+
errmsg("unrecognized argument: #{args[-1]}")
|
43
|
+
end
|
44
|
+
elsif args.size == 1
|
45
|
+
names = get_names
|
46
|
+
if names.empty?
|
47
|
+
msg "No global variables defined."
|
48
|
+
else
|
49
|
+
section "Global variables:"
|
50
|
+
names.each do |var_name|
|
51
|
+
s = @proc.debug_eval(var_name.to_s)
|
52
|
+
msg("#{var_name} = #{s.inspect}", :code=>true)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
else
|
56
|
+
errmsg("Wrong number of arguments #{args.size}")
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
if __FILE__ == $0
|
62
|
+
# Demo it.
|
63
|
+
require_relative '../../../mock'
|
64
|
+
require_relative '../variables'
|
65
|
+
cmd = MockDebugger::subsub_setup(Trepan::Subcommand::InfoVariables,
|
66
|
+
Trepan::SubSubcommand::InfoVariablesGlobals)
|
67
|
+
cmd.run(cmd.prefix)
|
68
|
+
cmd.run(cmd.prefix + ['name'])
|
69
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
# Copyright (C) 2010, 2011 Rocky Bernstein <rockyb@rubyforge.net>
|
3
|
+
require 'rubygems'; require 'require_relative'
|
4
|
+
require_relative 'locals'
|
5
|
+
|
6
|
+
class Trepan::Subcommand::InfoVariablesInstance <
|
7
|
+
Trepan::Subcommand::InfoVariablesLocals
|
8
|
+
Trepan::Util.suppress_warnings {
|
9
|
+
Trepanning::Subcommand.set_name_prefix(__FILE__, self)
|
10
|
+
HELP = <<-EOH
|
11
|
+
#{CMD}
|
12
|
+
#{CMD} [names]
|
13
|
+
|
14
|
+
Show instance variables of the current stack frame.
|
15
|
+
Normally for each which show both the name and value. If you just
|
16
|
+
want a list of names add parameter 'names'.
|
17
|
+
EOH
|
18
|
+
SHORT_HELP = 'Show instance variables of the current stack frame'
|
19
|
+
MIN_ARGS = 0
|
20
|
+
MAX_ARGS = 1
|
21
|
+
MIN_ABBREV = 'iv'.size
|
22
|
+
NEED_STACK = true
|
23
|
+
}
|
24
|
+
|
25
|
+
def get_names
|
26
|
+
@proc.debug_eval('self.instance_variables')
|
27
|
+
end
|
28
|
+
|
29
|
+
def run(args)
|
30
|
+
run_for_type(args, 'instance', @proc.debug_eval('self'))
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
if __FILE__ == $0
|
35
|
+
# Demo it.
|
36
|
+
require_relative '../../mock'
|
37
|
+
cmd =
|
38
|
+
MockDebugger::subsub_setup(Trepan::Subcommand::InfoVariables,
|
39
|
+
Trepan::Subcommand::InfoVariablesInstance)
|
40
|
+
cmd.run(cmd.prefix)
|
41
|
+
cmd.run(cmd.prefix + ['name'])
|
42
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
# Copyright (C) 2010, 2011 Rocky Bernstein <rockyb@rubyforge.net>
|
3
|
+
require 'rubygems'; require 'require_relative'
|
4
|
+
require 'columnize'
|
5
|
+
require_relative '../../base/subsubcmd'
|
6
|
+
require_relative '../../../../app/frame'
|
7
|
+
require_relative '../../../../app/util'
|
8
|
+
|
9
|
+
class Trepan::Subcommand::InfoVariablesLocals < Trepan::SubSubcommand
|
10
|
+
Trepan::Util.suppress_warnings {
|
11
|
+
Trepanning::Subcommand.set_name_prefix(__FILE__, self)
|
12
|
+
HELP = <<-EOH
|
13
|
+
#{CMD}
|
14
|
+
#{CMD} [names]
|
15
|
+
|
16
|
+
Show local variables including parameters of the current stack frame.
|
17
|
+
Normally for each which show both the name and value. If you just
|
18
|
+
want a list of names add parameter 'names'.
|
19
|
+
EOH
|
20
|
+
SHORT_HELP = 'Show local variables of the current stack frame'
|
21
|
+
MIN_ARGS = 0
|
22
|
+
MAX_ARGS = 1
|
23
|
+
MIN_ABBREV = 'lo'.size
|
24
|
+
NEED_STACK = true
|
25
|
+
}
|
26
|
+
|
27
|
+
def get_names
|
28
|
+
@proc.frame.local_variables
|
29
|
+
end
|
30
|
+
|
31
|
+
def run_for_type(args, type, klass=nil)
|
32
|
+
suffix = klass ? " for #{klass.to_s}" : '' rescue ''
|
33
|
+
names = get_names()
|
34
|
+
if args.size == 2
|
35
|
+
if 0 == 'names'.index(args[-1].downcase)
|
36
|
+
names = get_names()
|
37
|
+
if names.empty?
|
38
|
+
msg "No #{type} variables defined."
|
39
|
+
else
|
40
|
+
section "#{type.capitalize} variable names#{suffix}:"
|
41
|
+
|
42
|
+
width = settings[:maxwidth]
|
43
|
+
mess = Columnize::columnize(names,
|
44
|
+
@proc.settings[:maxwidth], ' ',
|
45
|
+
false, true, ' ' * 2).chomp
|
46
|
+
msg mess
|
47
|
+
end
|
48
|
+
else
|
49
|
+
errmsg("unrecognized argument: #{args[-1]}")
|
50
|
+
end
|
51
|
+
elsif args.size == 1
|
52
|
+
if names.empty?
|
53
|
+
msg "No #{type} variables defined#{suffix}."
|
54
|
+
else
|
55
|
+
section "#{type.capitalize} variables#{suffix}:"
|
56
|
+
names.each do |var_name|
|
57
|
+
var_value =
|
58
|
+
@proc.safe_rep(@proc.debug_eval_no_errmsg(var_name).inspect)
|
59
|
+
msg("#{var_name} = #{var_value}", :code =>true)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
else
|
63
|
+
errmsg("Wrong number of arguments #{args.size}")
|
64
|
+
end
|
65
|
+
end
|
66
|
+
def run(args)
|
67
|
+
run_for_type(args, 'local', @proc.debug_eval('self'))
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
if __FILE__ == $0
|
72
|
+
# Demo it.
|
73
|
+
require_relative '../../../mock'
|
74
|
+
require_relative '../variables'
|
75
|
+
cmd = MockDebugger::subsub_setup(Trepan::SubSubcommand::InfoVariables,
|
76
|
+
Trepan::SubSubcommand::InfoVariablesLocals
|
77
|
+
)
|
78
|
+
cmd.run([])
|
79
|
+
cmd.run(['name'])
|
80
|
+
end
|
data/processor/command/kill.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Copyright (C) 2010, 2011 Rocky Bernstein <rockyb@rubyforge.net>
|
2
2
|
require 'rubygems'; require 'require_relative'
|
3
|
-
require_relative '
|
3
|
+
require_relative '../command'
|
4
4
|
class Trepan::Command::KillCommand < Trepan::Command
|
5
5
|
|
6
6
|
unless defined?(HELP)
|
@@ -35,9 +35,10 @@ Examples:
|
|
35
35
|
end
|
36
36
|
|
37
37
|
def complete(prefix)
|
38
|
-
completions = Signal.list.keys +
|
38
|
+
completions = Signal.list.keys + Signal.list.keys.map{|k| k.downcase} +
|
39
39
|
Signal.list.values.map{|i| i.to_s} +
|
40
|
-
Signal.list.values.map{|i| (-i).to_s}
|
40
|
+
Signal.list.values.map{|i| (-i).to_s} +
|
41
|
+
['unconditionally']
|
41
42
|
Trepan::Complete.complete_token(completions, prefix)
|
42
43
|
end
|
43
44
|
|
@@ -50,9 +51,6 @@ Examples:
|
|
50
51
|
errmsg("Signal name '#{sig}' is not a signal I know about.\n")
|
51
52
|
return false
|
52
53
|
end
|
53
|
-
if 'KILL' == sig || Signal['KILL'] == sig
|
54
|
-
@proc.intf.finalize
|
55
|
-
end
|
56
54
|
else
|
57
55
|
if not (unconditional || confirm('Really quit?', false))
|
58
56
|
msg('Kill not confirmed.')
|
@@ -62,9 +60,10 @@ Examples:
|
|
62
60
|
end
|
63
61
|
end
|
64
62
|
begin
|
63
|
+
@proc.intf.finalize if 'KILL' == sig || Signal.list['KILL'] == sig
|
65
64
|
Process.kill(sig, Process.pid)
|
66
|
-
rescue Errno::ESRCH
|
67
|
-
errmsg "Unable to send kill #{sig} to process #{Process.pid}"
|
65
|
+
rescue Errno::ESRCH, Errno::EINVAL, Errno::EPERM, RangeError
|
66
|
+
errmsg "Unable to send kill #{sig} to process #{Process.pid}: #{$!}"
|
68
67
|
end
|
69
68
|
end
|
70
69
|
end
|
@@ -72,7 +71,7 @@ end
|
|
72
71
|
if __FILE__ == $0
|
73
72
|
require_relative '../mock'
|
74
73
|
dbgr, cmd = MockDebugger::setup
|
75
|
-
%w(fooo 1 -1 HUP -9).each do |arg|
|
74
|
+
%w(fooo 100 1 -1 HUP -9).each do |arg|
|
76
75
|
puts "#{cmd.name} #{arg}"
|
77
76
|
cmd.run([cmd.name, arg])
|
78
77
|
puts '=' * 40
|
data/processor/command/list.rb
CHANGED
@@ -3,13 +3,14 @@
|
|
3
3
|
require 'rubygems'
|
4
4
|
require 'require_relative'
|
5
5
|
require 'linecache'
|
6
|
-
require_relative '
|
6
|
+
require_relative '../command'
|
7
|
+
require_relative '../list'
|
7
8
|
|
8
9
|
class Trepan::Command::ListCommand < Trepan::Command
|
9
10
|
unless defined?(HELP)
|
10
11
|
NAME = File.basename(__FILE__, '.rb')
|
11
12
|
HELP = <<-HELP
|
12
|
-
#{NAME}[>] [FIRST [NUM]]
|
13
|
+
#{NAME}[>] [MODULE] [FIRST [NUM]]
|
13
14
|
#{NAME}[>] LOCATION [NUM]
|
14
15
|
|
15
16
|
#{NAME} source code.
|
@@ -24,7 +25,7 @@ previously shown.
|
|
24
25
|
If the command has a '>' suffix, then line centering is disabled and
|
25
26
|
listing begins at the specificed location.
|
26
27
|
|
27
|
-
The number of lines to show is controlled by the debugger "
|
28
|
+
The number of lines to show is controlled by the debugger "listsize"
|
28
29
|
setting. Use 'set max list' or 'show max list' to see or set the
|
29
30
|
value.
|
30
31
|
|
@@ -42,8 +43,9 @@ A LOCATION is a either
|
|
42
43
|
If the location form is used with a subsequent parameter, the
|
43
44
|
parameter is the starting line number. When there two numbers are
|
44
45
|
given, the last number value is treated as a stopping line unless it
|
45
|
-
is less than the start line
|
46
|
-
number of lines to list instead.
|
46
|
+
is positive and less than the start line. In this case, it is taken to
|
47
|
+
mean the number of lines to list instead. If last is negative, we start
|
48
|
+
that many lines back from first and list to first.
|
47
49
|
|
48
50
|
Wherever a number is expected, it does not need to be a constant --
|
49
51
|
just something that evaluates to a positive integer.
|
@@ -51,131 +53,49 @@ just something that evaluates to a positive integer.
|
|
51
53
|
Some examples:
|
52
54
|
|
53
55
|
#{NAME} 5 # List centered around line 5
|
54
|
-
#{NAME}
|
56
|
+
#{NAME} @5 # List lines centered around bytecode offset 5.
|
55
57
|
#{NAME} 5> # List starting at line 5
|
56
58
|
#{NAME} foo.rb:5 # List centered around line 5 of foo.rb
|
57
59
|
#{NAME} foo.rb 5 # Same as above.
|
58
|
-
#{NAME} foo.rb:5
|
60
|
+
#{NAME}> foo.rb:5 # List starting around line 5 of foo.rb
|
59
61
|
#{NAME} foo.rb 5 6 # list lines 5 and 6 of foo.rb
|
60
62
|
#{NAME} foo.rb 5 2 # Same as above, since 2 < 5.
|
61
63
|
#{NAME} foo.rb:5 2 # Same as above
|
64
|
+
#{NAME} foo.rb 15 -5 # List lines 10..15 of foo
|
62
65
|
#{NAME} FileUtils.cp # List lines around the FileUtils.cp function.
|
63
66
|
#{NAME} . # List lines centered from where we currently are stopped
|
64
67
|
#{NAME} . 3 # List 3 lines starting from where we currently are stopped
|
65
68
|
# if . > 3. Otherwise we list from . to 3.
|
66
69
|
#{NAME} - # List lines previous to those just shown
|
67
70
|
|
71
|
+
The output of the #{NAME} command gives a line number, and some status
|
72
|
+
information about the line and the text of the line. Here is some
|
73
|
+
hypothetical #{NAME} output modeled roughly around line 251 of one
|
74
|
+
version of this code:
|
75
|
+
|
76
|
+
251 cmd.proc.frame_setup(tf)
|
77
|
+
252 -> brkpt_cmd.run(['break'])
|
78
|
+
253 B01 line = __LINE__
|
79
|
+
254 b02 cmd.run(['list', __LINE__.to_s])
|
80
|
+
255 t03 puts '--' * 10
|
81
|
+
|
82
|
+
Line 251 has nothing special about it. Line 252 is where we are
|
83
|
+
currently stopped. On line 253 there is a breakpoint 1 which is
|
84
|
+
enabled, while at line 255 there is an breakpoint 2 which is
|
85
|
+
disabled.
|
68
86
|
HELP
|
69
87
|
|
70
|
-
ALIASES = %W(l #{NAME}> l>)
|
88
|
+
ALIASES = %W(l #{NAME}> l> cat)
|
71
89
|
CATEGORY = 'files'
|
72
90
|
MAX_ARGS = 3
|
73
91
|
SHORT_HELP = 'List source code'
|
74
92
|
end
|
75
93
|
|
76
|
-
# If last is less than first, assume last is a count rather than an
|
77
|
-
# end line number.
|
78
|
-
def adjust_last(first, last)
|
79
|
-
last < first ? first + last - 1 : last
|
80
|
-
end
|
81
|
-
|
82
|
-
# What a f*cking mess. Necessitated I suppose because we want to
|
83
|
-
# allow somewhat flexible parsing with either module names, files or none
|
84
|
-
# and optional line counts or end-line numbers.
|
85
|
-
|
86
|
-
# Parses arguments for the "list" command and returns the tuple:
|
87
|
-
# filename, start, last
|
88
|
-
# or sets these to nil if there was some problem.
|
89
|
-
def parse_list_cmd(args, listsize, center_correction)
|
90
|
-
|
91
|
-
last = nil
|
92
|
-
|
93
|
-
if args.size > 0
|
94
|
-
if args[0] == '-'
|
95
|
-
return no_frame_msg unless @proc.line_no
|
96
|
-
first = [1, @proc.line_no - 2*listsize - 1].max
|
97
|
-
file = @proc.frame.file
|
98
|
-
elsif args[0] == '.'
|
99
|
-
return no_frame_msg unless @proc.line_no
|
100
|
-
if args.size == 2
|
101
|
-
opts = {
|
102
|
-
:msg_on_error =>
|
103
|
-
"#{NAME} command last or count parameter expected, " +
|
104
|
-
'got: %s.' % args[2]
|
105
|
-
}
|
106
|
-
second = @proc.get_an_int(args[1], opts)
|
107
|
-
return nil, nil, nil unless second
|
108
|
-
first = @proc.frame.line
|
109
|
-
last = adjust_last(first, second)
|
110
|
-
else
|
111
|
-
first = [1, @proc.frame.line - center_correction].max
|
112
|
-
end
|
113
|
-
|
114
|
-
file = @proc.frame.file
|
115
|
-
else
|
116
|
-
modfunc, file, first = @proc.parse_position(args[0])
|
117
|
-
if first == nil and modfunc == nil
|
118
|
-
# error should have been shown previously
|
119
|
-
return nil, nil, nil
|
120
|
-
end
|
121
|
-
if args.size == 1
|
122
|
-
first = 1 if !first and modfunc
|
123
|
-
first = [1, first - center_correction].max
|
124
|
-
elsif args.size == 2 or (args.size == 3 and modfunc)
|
125
|
-
opts = {
|
126
|
-
:msg_on_error =>
|
127
|
-
"#{NAME} command starting line expected, got %s." % args[-1]
|
128
|
-
}
|
129
|
-
last = @proc.get_an_int(args[1], opts)
|
130
|
-
return nil, nil, nil unless last
|
131
|
-
if modfunc
|
132
|
-
if first
|
133
|
-
first = last
|
134
|
-
if args.size == 3 and modfunc
|
135
|
-
opts[:msg_on_error] =
|
136
|
-
("#{NAME} command last or count parameter expected, " +
|
137
|
-
'got: %s.' % args[2])
|
138
|
-
last = @proc.get_an_int(args[2], opts)
|
139
|
-
return nil, nil, nil unless last
|
140
|
-
end
|
141
|
-
end
|
142
|
-
end
|
143
|
-
last = adjust_last(first, last)
|
144
|
-
elsif not modfunc
|
145
|
-
errmsg('At most 2 parameters allowed when no module' +
|
146
|
-
' name is found/given. Saw: %d parameters' % args.size)
|
147
|
-
return nil, nil, nil
|
148
|
-
else
|
149
|
-
errmsg(('At most 3 parameters allowed when a module' +
|
150
|
-
' name is given. Saw: %d parameters') % args.size)
|
151
|
-
return nil, nil, nil
|
152
|
-
end
|
153
|
-
end
|
154
|
-
elsif !@proc.line_no and @proc.frame
|
155
|
-
first = [1, @proc.frame.line - center_correction].max
|
156
|
-
file = @proc.frame.file
|
157
|
-
else
|
158
|
-
first = [1, @proc.line_no - center_correction].max
|
159
|
-
file = @proc.frame.file
|
160
|
-
end
|
161
|
-
last = first + listsize - 1 unless last
|
162
|
-
|
163
|
-
if @proc.frame.eval?
|
164
|
-
script = @proc.frame.vm_location.static_scope.script
|
165
|
-
LineCache::cache(script)
|
166
|
-
else
|
167
|
-
LineCache::cache(file)
|
168
|
-
script = nil
|
169
|
-
end
|
170
|
-
return file, script, first, last
|
171
|
-
end
|
172
|
-
|
173
|
-
def no_frame_msg
|
174
|
-
errmsg("No Ruby program loaded.")
|
175
|
-
return nil, nil, nil
|
176
|
-
end
|
177
|
-
|
178
94
|
def run(args)
|
95
|
+
if args.empty? and not frame
|
96
|
+
errmsg("No Ruby program loaded.")
|
97
|
+
return
|
98
|
+
end
|
179
99
|
listsize = settings[:maxlist]
|
180
100
|
center_correction =
|
181
101
|
if args[0][-1..-1] == '>'
|
@@ -184,36 +104,21 @@ Some examples:
|
|
184
104
|
(listsize-1) / 2
|
185
105
|
end
|
186
106
|
|
187
|
-
|
188
|
-
parse_list_cmd(
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
cached_item = script || file
|
107
|
+
cm, filename, first, last =
|
108
|
+
@proc.parse_list_cmd(@proc.cmd_argstr, listsize, center_correction)
|
109
|
+
return unless filename
|
110
|
+
breaklist = @proc.brkpts.line_breaks(cm)
|
193
111
|
|
194
112
|
# We now have range information. Do the listing.
|
195
|
-
max_line = LineCache::size(
|
196
|
-
|
197
|
-
# FIXME: join with line_at of location.rb
|
198
|
-
unless max_line && file
|
199
|
-
# Try using search directories (set with command "directory")
|
200
|
-
if file[0..0] != File::SEPARATOR
|
201
|
-
try_filename = @proc.resolve_file_with_dir(file)
|
202
|
-
if try_filename &&
|
203
|
-
max_line = LineCache::size(try_filename)
|
204
|
-
LineCache::remap_file(file, try_filename)
|
205
|
-
end
|
206
|
-
end
|
207
|
-
end
|
208
|
-
|
113
|
+
max_line = LineCache::size(filename)
|
209
114
|
unless max_line
|
210
|
-
errmsg('File "%s" not found.' %
|
115
|
+
errmsg('File "%s" not found.' % filename)
|
211
116
|
return
|
212
117
|
end
|
213
118
|
|
214
119
|
if first > max_line
|
215
120
|
errmsg('Bad line range [%d...%d]; file "%s" has only %d lines' %
|
216
|
-
[first, last,
|
121
|
+
[first, last, filename, max_line])
|
217
122
|
return
|
218
123
|
end
|
219
124
|
|
@@ -224,11 +129,12 @@ Some examples:
|
|
224
129
|
|
225
130
|
begin
|
226
131
|
opts = {
|
227
|
-
:reload_on_change =>
|
132
|
+
:reload_on_change => settings[:reload],
|
228
133
|
:output => settings[:highlight]
|
229
134
|
}
|
135
|
+
frame = @proc.frame
|
230
136
|
first.upto(last).each do |lineno|
|
231
|
-
line = LineCache::getline(
|
137
|
+
line = LineCache::getline(filename, lineno, opts)
|
232
138
|
unless line
|
233
139
|
msg('[EOF]')
|
234
140
|
break
|
@@ -236,8 +142,16 @@ Some examples:
|
|
236
142
|
line.chomp!
|
237
143
|
s = '%3d' % lineno
|
238
144
|
s = s + ' ' if s.size < 4
|
239
|
-
s += (
|
240
|
-
|
145
|
+
s += if breaklist.member?(lineno)
|
146
|
+
bp = breaklist[lineno]
|
147
|
+
a_pad = '%02d' % bp.id
|
148
|
+
bp.icon_char
|
149
|
+
else
|
150
|
+
a_pad = ' '
|
151
|
+
' '
|
152
|
+
end
|
153
|
+
s += (frame && lineno == @proc.frame.line &&
|
154
|
+
filename == @proc.frame.file) ? '->' : a_pad
|
241
155
|
msg(s + "\t" + line, {:unlimited => true})
|
242
156
|
@proc.line_no = lineno
|
243
157
|
end
|
@@ -248,53 +162,73 @@ Some examples:
|
|
248
162
|
end
|
249
163
|
|
250
164
|
if __FILE__ == $0
|
165
|
+
# require_relative '../../lib/trepanning'; debugger
|
251
166
|
require_relative '../location'
|
252
167
|
require_relative '../mock'
|
253
168
|
require_relative '../frame'
|
254
169
|
dbgr, cmd = MockDebugger::setup
|
255
170
|
cmd.proc.send('frame_initialize')
|
256
|
-
LineCache::cache(__FILE__)
|
257
|
-
require 'trepanning'
|
258
|
-
cmd.run([cmd.name])
|
259
|
-
cmd.run([cmd.name, __FILE__ + ':10'])
|
260
171
|
|
261
172
|
def run_cmd(cmd, args)
|
262
|
-
|
263
|
-
puts "%s %s %s" % [seps, args.join(' '), seps]
|
173
|
+
cmd.proc.instance_variable_set('@cmd_argstr', args[1..-1].join(' '))
|
264
174
|
cmd.run(args)
|
265
175
|
end
|
266
176
|
|
267
|
-
|
268
|
-
|
269
|
-
run_cmd(cmd,
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
177
|
+
LineCache::cache(__FILE__)
|
178
|
+
run_cmd(cmd, [cmd.name])
|
179
|
+
run_cmd(cmd, [cmd.name, __FILE__ + ':10'])
|
180
|
+
|
181
|
+
def run_cmd2(cmd, args)
|
182
|
+
seps = '--' * 10
|
183
|
+
puts "%s %s %s" % [seps, args.join(' '), seps]
|
184
|
+
run_cmd(cmd,args)
|
185
|
+
end
|
186
|
+
|
187
|
+
require 'tmpdir.rb'
|
188
|
+
run_cmd2(cmd, %w(list tmpdir.rb 10))
|
189
|
+
run_cmd2(cmd, %w(list tmpdir.rb))
|
190
|
+
|
191
|
+
# cmd.proc.frame = sys._getframe()
|
192
|
+
# cmd.proc.setup()
|
193
|
+
# run_cmd2(['list'])
|
194
|
+
|
195
|
+
run_cmd2(cmd, %w(list .))
|
196
|
+
run_cmd2(cmd, %w(list 30))
|
197
|
+
|
198
|
+
# run_cmd2(['list', '9+1'])
|
199
|
+
|
200
|
+
run_cmd2(cmd, %w(list> 10))
|
201
|
+
run_cmd2(cmd, %w(list 3000))
|
202
|
+
run_cmd2(cmd, %w(list run_cmd2))
|
203
|
+
|
281
204
|
p = Proc.new do
|
282
205
|
|x,y| x + y
|
283
206
|
end
|
284
|
-
|
285
|
-
|
207
|
+
run_cmd2(cmd, %w(list p))
|
208
|
+
|
286
209
|
# Function from a file found via an instruction sequence
|
287
|
-
|
288
|
-
|
210
|
+
run_cmd2(cmd, %w(list Columnize.columnize))
|
211
|
+
|
289
212
|
# Use Class/method name. 15 isn't in the function - should this be okay?
|
290
|
-
|
291
|
-
|
213
|
+
run_cmd2(cmd, %W(#{cmd.name} Columnize.columnize 15))
|
214
|
+
|
292
215
|
# Start line and count, since 3 < 30
|
293
|
-
|
294
|
-
|
216
|
+
run_cmd2(cmd, %W(#{cmd.name} Columnize.columnize 30 3))
|
217
|
+
|
295
218
|
# Start line finish line
|
296
|
-
|
219
|
+
run_cmd2(cmd, %W(#{cmd.name} Columnize.columnize 40 50))
|
220
|
+
|
221
|
+
line = __LINE__
|
222
|
+
brkpt_cmd = cmd.proc.instance_variable_get('@commands')['break']
|
223
|
+
cmd.proc.instance_variable_set('@cmd_argstr', "#{__FILE__} #{line}")
|
224
|
+
brkpt_cmd.run(['break', __FILE__, line.to_s])
|
225
|
+
run_cmd2(cmd, [cmd.name, line.to_s])
|
226
|
+
|
227
|
+
# disable_cmd = cmd.proc.instance_variable_get('@commands')['disable']
|
228
|
+
# disable_cmd.run(['disable', '1'])
|
297
229
|
|
298
|
-
#
|
299
|
-
|
230
|
+
# run_cmd2(cmd, [cmd.name, line.to_s])
|
231
|
+
run_cmd2(cmd, %W(#{cmd.name} run_cmd2))
|
232
|
+
run_cmd2(cmd, %W(#{cmd.name} run_cmd2))
|
233
|
+
run_cmd2(cmd, %W(#{cmd.name} @713))
|
300
234
|
end
|