trepanning 1.93.35 → 2.15.33
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.
- checksums.yaml +7 -0
- data/ChangeLog +491 -55
- data/LICENSE +1 -1
- data/NEWS +18 -14
- data/README.md +5 -22
- data/Rakefile +22 -1
- data/app/breakpoint.rb +5 -3
- data/app/core.rb +147 -179
- data/app/default.rb +47 -46
- data/app/file.rb +6 -7
- data/app/frame.rb +183 -176
- data/app/markdown.rb +2 -9
- data/app/options.rb +1 -1
- data/app/run.rb +71 -37
- data/interface/script.rb +8 -8
- data/io.rb +19 -20
- data/lib/trepanning.rb +292 -297
- data/processor.rb +332 -344
- data/processor/breakpoint.rb +98 -96
- data/processor/command/base/submgr.rb +9 -9
- data/processor/command/break.rb +40 -38
- data/processor/command/continue.rb +15 -10
- data/processor/command/debug.rb +6 -25
- data/processor/command/delete.rb +21 -12
- data/processor/command/directory.rb +15 -13
- data/processor/command/disable.rb +12 -9
- data/processor/command/disassemble.rb +80 -74
- data/processor/command/display.rb +15 -12
- data/processor/command/down.rb +8 -3
- data/processor/command/edit.rb +37 -23
- data/processor/command/enable.rb +11 -8
- data/processor/command/eval.rb +24 -22
- data/processor/command/finish.rb +50 -48
- data/processor/command/help.rb +1 -1
- data/processor/command/info_subcmd/breakpoints.rb +7 -7
- data/processor/command/info_subcmd/files.rb +195 -196
- data/processor/command/info_subcmd/frame.rb +7 -4
- data/processor/command/info_subcmd/locals.rb +29 -12
- data/processor/command/info_subcmd/program.rb +48 -39
- data/processor/command/info_subcmd/registers_subcmd/ep.rb +46 -0
- data/processor/command/info_subcmd/registers_subcmd/helper.rb +32 -35
- data/processor/command/info_subcmd/registers_subcmd/sp.rb +29 -23
- data/processor/command/info_subcmd/return.rb +28 -10
- data/processor/command/info_subcmd/variables_subcmd/class.rb +3 -3
- data/processor/command/info_subcmd/variables_subcmd/constants.rb +77 -0
- data/processor/command/info_subcmd/variables_subcmd/globals.rb +7 -7
- data/processor/command/info_subcmd/variables_subcmd/instance.rb +68 -22
- data/processor/command/info_subcmd/variables_subcmd/locals.rb +148 -67
- data/processor/command/list.rb +14 -8
- data/processor/command/macro.rb +1 -1
- data/processor/command/next.rb +1 -0
- data/processor/command/set_subcmd/auto.rb +3 -3
- data/processor/command/set_subcmd/different.rb +30 -29
- data/processor/command/set_subcmd/events.rb +74 -48
- data/processor/command/set_subcmd/max_subcmd/list.rb +12 -5
- data/processor/command/set_subcmd/max_subcmd/width.rb +28 -19
- data/processor/command/set_subcmd/register.rb +37 -0
- data/processor/command/set_subcmd/register_subcmd/pc.rb +67 -0
- data/processor/command/set_subcmd/register_subcmd/sp.rb +75 -0
- data/processor/command/set_subcmd/reload.rb +12 -10
- data/processor/command/set_subcmd/return.rb +68 -44
- data/processor/command/shell.rb +3 -2
- data/processor/command/show_subcmd/different.rb +17 -14
- data/processor/command/show_subcmd/events.rb +25 -25
- data/processor/default.rb +1 -1
- data/processor/eval.rb +14 -15
- data/processor/frame.rb +43 -36
- data/processor/help.rb +5 -5
- data/processor/hook.rb +26 -29
- data/processor/location.rb +54 -51
- data/processor/mock.rb +4 -3
- data/processor/running.rb +113 -103
- data/processor/validate.rb +401 -373
- data/test/data/debug.cmd +8 -0
- data/test/data/debug.right +13 -0
- data/test/data/debugger-stop.right +6 -4
- data/test/data/fname-with-blank.cmd +1 -1
- data/test/data/fname-with-blank.right +5 -0
- data/test/data/pc.cmd +8 -0
- data/test/data/pc.right +10 -0
- data/test/data/quit.right +3 -1
- data/test/data/trace.cmd +2 -2
- data/test/data/trace.right +41 -20
- data/test/example/assign.rb +6 -0
- data/test/functional/fn_helper.rb +11 -17
- data/test/functional/test-break-long.rb +15 -16
- data/test/functional/test-break.rb +6 -8
- data/test/functional/test-condition.rb +8 -10
- data/test/functional/test-debugger-call-bug.rb +21 -22
- data/test/functional/test-delete.rb +57 -59
- data/test/functional/test-eval.rb +101 -103
- data/test/functional/test-finish.rb +24 -33
- data/test/functional/test-immediate-step-bug.rb +6 -10
- data/test/functional/test-next.rb +64 -65
- data/test/functional/test-raise.rb +63 -64
- data/test/functional/test-recursive-bt.rb +81 -76
- data/test/functional/test-remap.rb +6 -7
- data/test/functional/test-return.rb +44 -38
- data/test/functional/test-step.rb +55 -53
- data/test/functional/test-stepbug.rb +6 -9
- data/test/functional/test-watchg.rb +40 -39
- data/test/integration/test-debug.rb +12 -0
- data/test/integration/test-debugger-stop.rb +7 -7
- data/test/integration/test-pc.rb +24 -0
- data/test/integration/test-trace.rb +1 -1
- data/test/unit/cmd-helper.rb +0 -1
- data/test/unit/test-app-brkpt.rb +21 -21
- data/test/unit/test-app-brkptmgr.rb +7 -8
- data/test/unit/test-app-display.rb +3 -4
- data/test/unit/test-app-frame.rb +4 -5
- data/test/unit/test-base-subsubcmd.rb +2 -2
- data/test/unit/test-cmd-break.rb +6 -6
- data/test/unit/test-cmd-endisable.rb +7 -6
- data/test/unit/test-cmd-parse_list_cmd.rb +24 -24
- data/test/unit/test-io-tcpserver.rb +39 -35
- data/test/unit/test-proc-default.rb +23 -22
- data/test/unit/test-proc-eval.rb +1 -2
- data/test/unit/test-proc-frame.rb +8 -9
- data/test/unit/test-proc-list.rb +1 -1
- data/test/unit/test-proc-location.rb +2 -2
- data/test/unit/test-proc-main.rb +10 -10
- data/test/unit/test-proc-validate.rb +11 -13
- data/test/unit/test-subcmd-help.rb +1 -2
- data/trepanning.gemspec +8 -13
- metadata +44 -95
- data/COPYING +0 -57
- data/data/custom_require.rb +0 -44
- data/data/perldb.bindings +0 -17
- data/data/prelude.rb +0 -38
- data/processor/command/info_subcmd/variables_subcmd/constant.rb +0 -41
- data/processor/command/raise.rb +0 -48
- data/processor/command/set_subcmd/pc.rb +0 -62
- data/processor/command/set_subcmd/sp.rb +0 -67
- data/processor/eventbuf.rb +0 -133
data/app/default.rb
CHANGED
@@ -7,61 +7,62 @@ class Trepan
|
|
7
7
|
|
8
8
|
# Default settings for a Trepan class object
|
9
9
|
DEFAULT_SETTINGS = {
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
10
|
+
:cmdproc_opts => {}, # Default Trepan::CmdProcessor settings
|
11
|
+
:core_opts => {}, # Default Trepan::Core settings
|
12
|
+
:delete_restore => true, # Delete restore profile after reading?
|
13
|
+
:initial_dir => nil, # If --cd option was given, we save it here.
|
14
|
+
:nx => false, # Don't run user startup file (e.g. .trepanrc)
|
15
|
+
:cmdloop_on_exit => true, # Stay in debugger after program finishes
|
15
16
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
17
|
+
# Default values used only when 'server' or 'client'
|
18
|
+
# (out-of-process debugging)
|
19
|
+
:port => 1955,
|
20
|
+
:post_mortem => false,
|
21
|
+
:host => 'localhost',
|
21
22
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
23
|
+
:restart_argv => RubyVM::OS_ARGV,
|
24
|
+
# Command run when "restart" is given.
|
25
|
+
:server => false, # Out-of-process debugging?
|
26
|
+
} unless defined?(DEFAULT_SETTINGS)
|
26
27
|
|
27
28
|
# Default settings for Trepan run from the command line.
|
28
29
|
DEFAULT_CMDLINE_SETTINGS = {
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
30
|
+
:basename => false,
|
31
|
+
:cmdfiles => [], # Initialization command files to run
|
32
|
+
:client => false, # Attach to out-of-process program?
|
33
|
+
:nx => false, # Don't run user startup file (e.g. .trepanrc)
|
34
|
+
:output => nil,
|
35
|
+
:port => DEFAULT_SETTINGS[:port],
|
36
|
+
:host => DEFAULT_SETTINGS[:host],
|
37
|
+
:server => false, # Out-of-process debugging?
|
38
|
+
:readline => true, # Try to use GNU Readline?
|
39
|
+
# Note that at most one of :server or :client can be true.
|
40
|
+
} unless defined?(DEFAULT_CMDLINE_SETTINGS)
|
40
41
|
|
41
42
|
DEFAULT_DEBUG_STR_SETTINGS = {
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
43
|
+
:core_opts => {
|
44
|
+
:cmdproc_opts => {:different => true, :highlight => true}},
|
45
|
+
:hide_stack => true,
|
46
|
+
} unless defined?(DEFAULT_DEBUG_STR_SETTINGS)
|
46
47
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
48
|
+
CMD_INITFILE_BASE =
|
49
|
+
if RUBY_PLATFORM =~ /mswin/
|
50
|
+
# Of course MS Windows has to be different
|
51
|
+
HOME_DIR = (ENV['HOME'] ||
|
52
|
+
ENV['HOMEDRIVE'].to_s + ENV['HOMEPATH'].to_s).to_s
|
53
|
+
'trepan.ini'
|
54
|
+
else
|
55
|
+
HOME_DIR = ENV['HOME'].to_s
|
56
|
+
'.trepanrc'
|
57
|
+
end unless defined?(CMD_INITFILE_BASE)
|
58
|
+
CMD_INITFILE = File.join(HOME_DIR, CMD_INITFILE_BASE) unless
|
59
|
+
defined?(CMD_INITFILE)
|
59
60
|
end
|
60
61
|
|
61
62
|
if __FILE__ == $0
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
63
|
+
# Show it:
|
64
|
+
require 'pp'
|
65
|
+
PP.pp(Trepan::DEFAULT_SETTINGS)
|
66
|
+
puts '=' * 30
|
67
|
+
PP.pp(Trepan::DEFAULT_CMDLINE_SETTINGS)
|
67
68
|
end
|
data/app/file.rb
CHANGED
@@ -1,17 +1,16 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
# Copyright (C) 2010, 2011 Rocky Bernstein <rockyb@rubyforge.net>
|
3
3
|
# Things related to file/module status
|
4
|
-
require 'thread_frame'
|
5
4
|
require_relative 'iseq'
|
6
5
|
|
7
|
-
SCRIPT_ISEQS__ = {} unless
|
6
|
+
SCRIPT_ISEQS__ = {} unless
|
8
7
|
defined?(SCRIPT_ISEQS__) && SCRIPT_ISEQS__.is_a?(Hash)
|
9
|
-
ISEQS__ = {} unless
|
8
|
+
ISEQS__ = {} unless
|
10
9
|
defined?(ISEQS__) && ISEQS__.is_a?(Hash)
|
11
10
|
|
12
11
|
module Trepanning
|
13
12
|
def file_match_pat(filename)
|
14
|
-
prefix =
|
13
|
+
prefix =
|
15
14
|
if filename[0..0] == File::SEPARATOR
|
16
15
|
# An absolute filename has to match at the beginning and
|
17
16
|
# the end.
|
@@ -30,7 +29,7 @@ module Trepanning
|
|
30
29
|
match_block = Proc.new{|filename, iseq| filename =~ /^#{dirname}/}
|
31
30
|
scripts = SCRIPT_ISEQS__.select(&match_block)
|
32
31
|
SCRIPT_ISEQS__.delete_if(&match_block)
|
33
|
-
match_block = Proc.new{|iseq|
|
32
|
+
match_block = Proc.new{|iseq|
|
34
33
|
iseq.source_container[1] =~ /^#{dirname}/
|
35
34
|
}
|
36
35
|
rejected = {}
|
@@ -55,7 +54,7 @@ module Trepanning
|
|
55
54
|
filename_pat = file_match_pat(filename)
|
56
55
|
iseqs.select{|iseq| iseq.source_container[1] =~ /#{filename_pat}/}
|
57
56
|
else
|
58
|
-
return iseqs
|
57
|
+
return iseqs
|
59
58
|
end
|
60
59
|
end
|
61
60
|
|
@@ -85,7 +84,7 @@ if __FILE__ == $0
|
|
85
84
|
SCRIPT_LINES__ = {}
|
86
85
|
ARGV[0..-1] = ['noload']
|
87
86
|
load(__FILE__)
|
88
|
-
else
|
87
|
+
else
|
89
88
|
load 'tmpdir.rb'
|
90
89
|
tmpdir_dir = File.dirname(find_scripts('tmpdir.rb')[0])
|
91
90
|
p tmpdir_dir
|
data/app/frame.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
# Copyright (C) 2010,
|
1
|
+
# Copyright (C) 2010-2011, 2015 Rocky Bernstein <rockyb@rubyforge.net>
|
2
2
|
require_relative 'util'
|
3
3
|
|
4
4
|
class Trepan
|
5
|
-
|
5
|
+
|
6
6
|
# Call-Stack frame methods
|
7
7
|
module Frame
|
8
8
|
|
@@ -22,48 +22,50 @@ class Trepan
|
|
22
22
|
return '' unless iseq
|
23
23
|
params = param_names(iseq, 0, iseq.argc-1, '')
|
24
24
|
if iseq.arg_opts > 0
|
25
|
-
opt_params = param_names(iseq, iseq.argc,
|
25
|
+
opt_params = param_names(iseq, iseq.argc,
|
26
26
|
iseq.argc + iseq.arg_opts-2, '')
|
27
27
|
opt_params[0] = "optional: #{opt_params[0]}" if delineate
|
28
28
|
params += opt_params
|
29
29
|
end
|
30
|
-
params += param_names(iseq, iseq.arg_rest, iseq.arg_rest, '*') if
|
30
|
+
params += param_names(iseq, iseq.arg_rest, iseq.arg_rest, '*') if
|
31
31
|
iseq.arg_rest != -1
|
32
32
|
if iseq.arg_post_len > 0
|
33
33
|
# Manditory arguments after optional ones - new in Ruby 1.9
|
34
|
-
post_params = param_names(iseq, iseq.arg_post_start,
|
34
|
+
post_params = param_names(iseq, iseq.arg_post_start,
|
35
35
|
iseq.post_start + iseq.arg_post_len, '')
|
36
36
|
post_params[0] = "post: #{post_params[0]}" if delineate
|
37
37
|
params += post_params
|
38
38
|
end
|
39
|
-
params += param_names(iseq, iseq.arg_block, iseq.arg_block, '&') if
|
39
|
+
params += param_names(iseq, iseq.arg_block, iseq.arg_block, '&') if
|
40
40
|
iseq.arg_block != -1
|
41
41
|
|
42
42
|
return params
|
43
43
|
end
|
44
44
|
|
45
45
|
def c_params(frame, maxstring=20)
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
46
|
+
argc = frame.argc
|
47
|
+
# FIXME should figure out why exception is raised.
|
48
|
+
begin
|
49
|
+
args =
|
50
|
+
if 0 == argc
|
51
|
+
''
|
52
|
+
elsif frame
|
53
|
+
1.upto(argc).map do
|
54
|
+
|i|
|
55
|
+
# FIXME: figure out why
|
56
|
+
# Trepan::Frame:Module throws an error
|
57
|
+
safe_repr(frame.sp(argc-i+3).inspect, 10) rescue ''
|
58
|
+
end.join(', ')
|
59
|
+
else
|
60
|
+
'??'
|
61
|
+
end
|
62
|
+
safe_repr(args, maxstring) rescue ''
|
63
|
+
rescue NotImplementedError
|
58
64
|
'??'
|
59
|
-
|
60
|
-
safe_repr(args, maxstring)
|
61
|
-
rescue NotImplementedError
|
62
|
-
'??'
|
63
|
-
end
|
65
|
+
end
|
64
66
|
end
|
65
67
|
|
66
|
-
# Return the eval string. We get this as the
|
68
|
+
# Return the eval string. We get this as the
|
67
69
|
# parameter to the eval C call. A bit of checking is done
|
68
70
|
# to make sure everything is okay:
|
69
71
|
# - we have to be in an EVAL type frame which has an iseq
|
@@ -73,7 +75,7 @@ class Trepan
|
|
73
75
|
return nil unless 'EVAL' == frame.type && frame.iseq
|
74
76
|
prev = frame.prev
|
75
77
|
return nil unless prev && 'CFUNC' == prev.type && 'eval' == prev.method
|
76
|
-
retval = prev.sp 3
|
78
|
+
retval = prev.sp 3
|
77
79
|
retval = $1 if retval =~ /^\(eval "(.+)"\)/
|
78
80
|
retval
|
79
81
|
end
|
@@ -83,84 +85,86 @@ class Trepan
|
|
83
85
|
end
|
84
86
|
|
85
87
|
def format_stack_call(frame, opts)
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
obj = eval('self', frame.binding)
|
93
|
-
rescue
|
94
|
-
''
|
88
|
+
# FIXME: prettify
|
89
|
+
s = "#{frame.type}"
|
90
|
+
# FIXME: Figure why frame.class can throw a NoMethodError
|
91
|
+
# on to_s.
|
92
|
+
s += if opts[:class]
|
93
|
+
" #{opts[:class]}#"
|
95
94
|
else
|
96
|
-
|
97
|
-
" #{obj.class}#"
|
98
|
-
else
|
99
|
-
''
|
100
|
-
end
|
95
|
+
" #{frame.klass}#" rescue ''
|
101
96
|
end
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
97
|
+
meth = frame.method
|
98
|
+
if meth and frame.type != 'IFUNC'
|
99
|
+
iseq = frame.iseq
|
100
|
+
args = if 'CFUNC' == frame.type
|
101
|
+
c_params(frame)
|
102
|
+
elsif iseq
|
103
|
+
all_param_names(iseq).join(', ')
|
104
|
+
end
|
105
|
+
s += meth
|
106
|
+
if %w(CFUNC METHOD).member?(frame.type)
|
107
|
+
s += "(#{args})"
|
108
|
+
elsif %w(BLOCK LAMBDA TOP EVAL).member?(frame.type)
|
109
|
+
s += " |#{args}|" unless args.nil? || args.empty?
|
110
|
+
else
|
111
|
+
s += "(#{all_param_names(iseq)})"
|
112
|
+
end
|
118
113
|
end
|
119
|
-
|
120
|
-
s
|
121
|
-
rescue ThreadFrameError
|
122
|
-
'invalid frame'
|
114
|
+
s
|
123
115
|
end
|
124
116
|
|
125
117
|
def format_stack_entry(frame, opts={})
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
if
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
118
|
+
return 'invalid frame' unless frame.valid?
|
119
|
+
container_type = frame.source_container[0]
|
120
|
+
s = format_stack_call(frame, opts)
|
121
|
+
s += " in #{container_type}"
|
122
|
+
sep = if opts[:maxwidth] && s.size > opts[:maxwidth]
|
123
|
+
"\n\t"
|
124
|
+
else
|
125
|
+
' '
|
126
|
+
end
|
127
|
+
s +=
|
128
|
+
if (eval_str = eval_string(frame))
|
129
|
+
sep + safe_repr(eval_str.inspect, 15)
|
130
|
+
else
|
131
|
+
if 'file' == container_type && opts[:basename]
|
132
|
+
sep + File.basename(frame.source_container[1])
|
133
|
+
elsif 'binary' == container_type
|
134
|
+
''
|
135
|
+
else
|
136
|
+
sep + frame.source_container[1]
|
137
|
+
end
|
138
|
+
end
|
140
139
|
if frame.source_location
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
s +=
|
152
|
-
|
140
|
+
loc = ''
|
141
|
+
loc +=
|
142
|
+
if container_type == 'binary'
|
143
|
+
"at address 0x%x" % frame.source_location[0]
|
144
|
+
elsif frame.source_location.size == 1
|
145
|
+
frame.source_location[0] != 0 ?
|
146
|
+
"at line #{frame.source_location[0]}" : ''
|
147
|
+
else
|
148
|
+
"at lines #{frame.source_location}"
|
149
|
+
end
|
150
|
+
s +=
|
151
|
+
if opts[:maxwidth] && s.size + loc.size > opts[:maxwidth]
|
152
|
+
"\n\t"
|
153
|
+
else
|
154
|
+
' '
|
155
|
+
end
|
156
|
+
s += loc
|
153
157
|
end
|
154
|
-
|
155
|
-
|
156
|
-
|
158
|
+
s += ", pc: #{frame.pc_offset}" if
|
159
|
+
frame.pc_offset > 0 && opts[:show_pc]
|
160
|
+
return s
|
157
161
|
end
|
158
162
|
|
159
163
|
# Return true if frame1 and frame2 are at the same place.
|
160
164
|
# We use this for example in detecting tail recursion.
|
161
165
|
def location_equal(frame1, frame2)
|
162
166
|
frame1 && frame2 && frame1.source_location == frame2.source_location &&
|
163
|
-
frame1.pc_offset == frame2.pc_offset &&
|
167
|
+
frame1.pc_offset == frame2.pc_offset &&
|
164
168
|
frame1.source_container == frame2.source_container
|
165
169
|
end
|
166
170
|
|
@@ -172,7 +176,7 @@ class Trepan
|
|
172
176
|
end
|
173
177
|
|
174
178
|
def param_names(iseq, start, stop, prefix='')
|
175
|
-
start.upto(stop).map do |i|
|
179
|
+
start.upto(stop).map do |i|
|
176
180
|
begin
|
177
181
|
prefix + iseq.local_name(i)
|
178
182
|
rescue
|
@@ -187,40 +191,41 @@ class Trepan
|
|
187
191
|
end
|
188
192
|
|
189
193
|
def print_stack_trace_from_to(from, to, frame, opts)
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
194
|
+
last_frame = nil
|
195
|
+
# TODO: handle indirect recursion.
|
196
|
+
direct_recursion_count = 0
|
197
|
+
from.upto(to) do |i|
|
198
|
+
if location_equal(last_frame, frame)
|
199
|
+
direct_recursion_count += 1
|
200
|
+
else
|
201
|
+
if direct_recursion_count > 0
|
202
|
+
msg("... above line repeated #{direct_recursion_count} times")
|
203
|
+
direct_recursion_count = 0
|
204
|
+
end
|
205
|
+
prefix = (i == opts[:current_pos]) ? '-->' : ' '
|
206
|
+
prefix += ' #%d ' % [i]
|
207
|
+
print_stack_entry(frame, i, prefix, opts)
|
208
|
+
end
|
209
|
+
last_frame = frame
|
210
|
+
frame = frame.prev
|
204
211
|
end
|
205
|
-
last_frame
|
206
|
-
frame = frame.prev
|
207
|
-
end
|
212
|
+
return last_frame
|
208
213
|
end
|
209
214
|
|
210
215
|
# Print `count' frame entries
|
211
216
|
def print_stack_trace(frame, opts={})
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
217
|
+
opts = DEFAULT_STACK_TRACE_SETTINGS.merge(opts)
|
218
|
+
halfstack = (opts[:maxstack]+1) / 2
|
219
|
+
n = frame.stack_size
|
220
|
+
n = [n, opts[:count]].min if opts[:count]
|
221
|
+
if n > (halfstack * 2)
|
222
|
+
print_stack_trace_from_to(0, halfstack-1, frame, opts)
|
223
|
+
msg "... %d levels ..." % (n - halfstack*2)
|
224
|
+
last_frame = print_stack_trace_from_to(n - halfstack, n-1, frame, opts)
|
225
|
+
else
|
226
|
+
last_frame = print_stack_trace_from_to(0, n-1, frame, opts)
|
227
|
+
end
|
228
|
+
msg "(More stack frames follow...)" if last_frame.type != 'TOP'
|
224
229
|
end
|
225
230
|
|
226
231
|
def set_return_value(frame, event, value)
|
@@ -236,67 +241,69 @@ class Trepan
|
|
236
241
|
end
|
237
242
|
|
238
243
|
if __FILE__ == $0
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
244
|
+
# Demo it.
|
245
|
+
include Trepan::Frame
|
246
|
+
def msg(msg)
|
247
|
+
puts msg
|
248
|
+
end
|
249
|
+
width = (ENV['COLUMNS'] || `tput cols &2>/dev/null`).to_i rescue 80
|
250
|
+
opts = {:maxwidth => width}
|
251
|
+
print_stack_trace(RubyVM::Frame.get,
|
252
|
+
:basename => true, :maxwidth => width)
|
253
|
+
def foo(width)
|
254
|
+
puts '=' * 10
|
255
|
+
print_stack_trace(RubyVM::Frame.get,
|
256
|
+
:show_pc => true, :maxwidth => width)
|
257
|
+
end
|
258
|
+
foo(width)
|
251
259
|
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
bar(1, 2, 3)
|
260
|
+
def bar(a, b, opts)
|
261
|
+
puts '=' * 10
|
262
|
+
print_stack_trace(RubyVM::Frame.get, opts)
|
263
|
+
end
|
264
|
+
bar(1, 2, opts)
|
258
265
|
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
266
|
+
def baz(a, opts, c=5)
|
267
|
+
puts '=' * 10
|
268
|
+
print_stack_trace(RubyVM::Frame.get, opts)
|
269
|
+
end
|
270
|
+
baz(1, opts)
|
264
271
|
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
bat(1,
|
272
|
+
def bat(a, opts, &block)
|
273
|
+
puts '=' * 10
|
274
|
+
print_stack_trace(RubyVM::Frame.get, opts)
|
275
|
+
end
|
276
|
+
bat(1, opts)
|
270
277
|
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
278
|
+
def babe(a, b, *rest)
|
279
|
+
puts '=' * 10
|
280
|
+
print_stack_trace(RubyVM::Frame.get)
|
281
|
+
end
|
282
|
+
babe(1, 2)
|
276
283
|
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
284
|
+
puts '=' * 10
|
285
|
+
x = lambda { |a,b| print_stack_trace(RubyVM::Frame::get, opts) }
|
286
|
+
x.call(1,2)
|
287
|
+
puts '=' * 10
|
288
|
+
x = Proc.new do |a|
|
289
|
+
print_stack_trace(RubyVM::Frame::get, opts)
|
290
|
+
end
|
291
|
+
x.call(1,2)
|
292
|
+
class C # :nodoc
|
293
|
+
def initialize(opts)
|
294
|
+
print_stack_trace(RubyVM::Frame::get, opts)
|
295
|
+
end
|
296
|
+
end
|
297
|
+
puts '=' * 30
|
298
|
+
C.new(opts)
|
299
|
+
puts '=' * 30
|
300
|
+
eval("print_stack_trace(RubyVM::Frame.get, opts)")
|
301
|
+
puts '=' * 30
|
302
|
+
eval("eval('print_stack_trace(RubyVM::Frame.get, opts)')")
|
303
|
+
puts '=' * 30
|
304
|
+
eval("eval('print_stack_trace(RubyVM::Frame.get, :maxstack => 2)')")
|
305
|
+
puts '=' * 30
|
306
|
+
1.upto(1) do |a; b|
|
307
|
+
print_stack_trace(RubyVM::Frame::get)
|
288
308
|
end
|
289
|
-
end
|
290
|
-
puts '=' * 30
|
291
|
-
C.new('Hi')
|
292
|
-
puts '=' * 30
|
293
|
-
eval("print_stack_trace(RubyVM::Frame.current)")
|
294
|
-
puts '=' * 30
|
295
|
-
eval("eval('print_stack_trace(RubyVM::Frame.current)')")
|
296
|
-
puts '=' * 30
|
297
|
-
eval("eval('print_stack_trace(RubyVM::Frame.current, :maxstack => 2)')")
|
298
|
-
puts '=' * 30
|
299
|
-
1.times do |a; b|
|
300
|
-
print_stack_trace(RubyVM::Frame::current)
|
301
|
-
end
|
302
309
|
end
|