trepanning 0.0.6 → 0.0.8
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog +214 -0
- data/NEWS +12 -0
- data/README.textile +1 -7
- data/Rakefile +13 -0
- data/app/default.rb +5 -4
- data/app/disassemble.rb +25 -3
- data/app/run.rb +0 -18
- data/bin/trepan +4 -6
- data/data/irbrc +3 -17
- data/io/base_io.rb +3 -1
- data/io/null_output.rb +41 -0
- data/lib/trepanning.rb +10 -13
- data/processor/command/backtrace.rb +7 -6
- data/processor/command/base/subcmd.rb +4 -0
- data/processor/command/base/submgr.rb +1 -1
- data/processor/command/base/subsubmgr.rb +1 -1
- data/processor/command/break.rb +12 -4
- data/processor/command/continue.rb +2 -2
- data/processor/command/delete.rb +1 -1
- data/processor/command/disable.rb +1 -1
- data/processor/command/disassemble.rb +1 -1
- data/processor/command/finish.rb +3 -3
- data/processor/command/info_subcmd/iseq.rb +9 -0
- data/processor/command/info_subcmd/registers_subcmd/dfp.rb +7 -16
- data/processor/command/info_subcmd/registers_subcmd/lfp.rb +5 -17
- data/processor/command/info_subcmd/registers_subcmd/pc.rb +6 -19
- data/processor/command/info_subcmd/registers_subcmd/sp.rb +14 -24
- data/processor/command/list.rb +34 -19
- data/processor/command/reload.rb +1 -1
- data/processor/command/restart.rb +8 -9
- data/processor/command/set_subcmd/auto.rb +1 -2
- data/processor/command/set_subcmd/auto_subcmd/eval.rb +6 -19
- data/processor/command/set_subcmd/auto_subcmd/irb.rb +7 -23
- data/processor/command/set_subcmd/auto_subcmd/list.rb +5 -22
- data/processor/command/set_subcmd/basename.rb +6 -20
- data/processor/command/set_subcmd/debug.rb +1 -1
- data/processor/command/set_subcmd/debug_subcmd/dbgr.rb +9 -22
- data/processor/command/set_subcmd/debug_subcmd/except.rb +8 -20
- data/processor/command/set_subcmd/debug_subcmd/macro.rb +7 -19
- data/processor/command/set_subcmd/debug_subcmd/skip.rb +5 -18
- data/processor/command/set_subcmd/debug_subcmd/stack.rb +5 -18
- data/processor/command/set_subcmd/hidelevel.rb +60 -0
- data/processor/command/set_subcmd/max.rb +1 -1
- data/processor/command/set_subcmd/max_subcmd/list.rb +12 -23
- data/processor/command/set_subcmd/max_subcmd/stack.rb +8 -31
- data/processor/command/set_subcmd/substitute.rb +1 -1
- data/processor/command/set_subcmd/substitute_subcmd/eval.rb +1 -1
- data/processor/command/set_subcmd/substitute_subcmd/path.rb +1 -1
- data/processor/command/set_subcmd/substitute_subcmd/string.rb +6 -18
- data/processor/command/set_subcmd/timer.rb +1 -1
- data/processor/command/set_subcmd/trace.rb +1 -1
- data/processor/command/set_subcmd/trace_subcmd/buffer.rb +1 -1
- data/processor/command/set_subcmd/trace_subcmd/print.rb +5 -21
- data/processor/command/set_subcmd/trace_subcmd/var.rb +1 -1
- data/processor/command/show_subcmd/args.rb +9 -27
- data/processor/command/show_subcmd/auto_subcmd/eval.rb +3 -15
- data/processor/command/show_subcmd/auto_subcmd/irb.rb +3 -15
- data/processor/command/show_subcmd/auto_subcmd/list.rb +3 -18
- data/processor/command/show_subcmd/basename.rb +3 -1
- data/processor/command/show_subcmd/hidelevel.rb +41 -0
- data/processor/command/show_subcmd/max.rb +1 -1
- data/processor/command/show_subcmd/trace_subcmd/buffer.rb +1 -1
- data/processor/command/show_subcmd/trace_subcmd/print.rb +1 -1
- data/processor/command/source.rb +6 -5
- data/processor/command/undisplay.rb +0 -1
- data/processor/default.rb +6 -2
- data/processor/frame.rb +2 -21
- data/processor/location.rb +44 -18
- data/processor/main.rb +0 -11
- data/processor/mock.rb +25 -0
- data/processor/validate.rb +34 -18
- data/test/functional/fn_helper.rb +14 -4
- data/test/functional/test-break.rb +35 -73
- data/test/functional/test-condition.rb +9 -10
- data/test/functional/test-delete.rb +5 -3
- data/test/unit/test-app-disassemble.rb +15 -3
- data/test/unit/test-app-run.rb +0 -4
- data/test/unit/test-cmd-break.rb +3 -0
- metadata +15 -11
data/io/null_output.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
# Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
|
3
|
+
|
4
|
+
# Nukes output. Used for example in sourcing where you don't want
|
5
|
+
# to see output.
|
6
|
+
#
|
7
|
+
|
8
|
+
require_relative 'base_io'
|
9
|
+
|
10
|
+
class Trepan
|
11
|
+
class OutputNull < Trepan::OutputBase
|
12
|
+
def initialize(out, opts={})
|
13
|
+
super
|
14
|
+
end
|
15
|
+
|
16
|
+
def close
|
17
|
+
end
|
18
|
+
|
19
|
+
def flush
|
20
|
+
end
|
21
|
+
|
22
|
+
# Use this to set where to write to. output can be a
|
23
|
+
# file object or a string. This code raises IOError on error.
|
24
|
+
def write(*args)
|
25
|
+
end
|
26
|
+
|
27
|
+
# used to write to a debugger that is connected to this
|
28
|
+
# `str' written will have a newline added to it
|
29
|
+
#
|
30
|
+
def writeline( msg)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# Demo it
|
36
|
+
if __FILE__ == $0
|
37
|
+
output = Trepan::OutputNull.new(nil)
|
38
|
+
p output
|
39
|
+
output.write("Invisible")
|
40
|
+
output.writeline("Invisible")
|
41
|
+
end
|
data/lib/trepanning.rb
CHANGED
@@ -20,7 +20,7 @@ ISEQS__ = {} unless
|
|
20
20
|
defined?(ISEQS__) && ISEQS__.is_a?(Hash)
|
21
21
|
|
22
22
|
class Trepan
|
23
|
-
VERSION = '0.0.
|
23
|
+
VERSION = '0.0.8'
|
24
24
|
|
25
25
|
attr_accessor :core # access to Trepan::Core instance
|
26
26
|
attr_accessor :intf # Array. The way the outside world
|
@@ -91,8 +91,6 @@ class Trepan
|
|
91
91
|
# needs to be done first:
|
92
92
|
# require 'trepanning'
|
93
93
|
# mydbg = Trepan.new()
|
94
|
-
# or if you haven't mucked around with $0 and ARGV, you might try:
|
95
|
-
# mydbg = Trepan.new(:set_restart=>true))
|
96
94
|
# which will tell the debugger how to "restart" the program.
|
97
95
|
#
|
98
96
|
# If you want a synchronous stop in your program call to the
|
@@ -136,8 +134,7 @@ class Trepan
|
|
136
134
|
th = Thread.current
|
137
135
|
if block
|
138
136
|
start
|
139
|
-
|
140
|
-
ret = yield # Not: block.call(self) ?
|
137
|
+
ret = block.call
|
141
138
|
stop
|
142
139
|
return ret
|
143
140
|
elsif opts[:immediate]
|
@@ -154,7 +151,7 @@ class Trepan
|
|
154
151
|
Trace.event_masks[0] |= @core.step_events
|
155
152
|
|
156
153
|
# Set to stop on the next event after this returns.
|
157
|
-
@core.step_count = 0
|
154
|
+
@core.step_count = opts[:step_count] || 0
|
158
155
|
end
|
159
156
|
end
|
160
157
|
|
@@ -217,7 +214,7 @@ class Trepan
|
|
217
214
|
# Likewise for mydbg.debugger{ ... }
|
218
215
|
|
219
216
|
def self.debug(opts={}, &block)
|
220
|
-
opts = {:hide_stack =>
|
217
|
+
opts = {:hide_stack => false}.merge(opts)
|
221
218
|
unless defined?($trepanning) && $trepanning.is_a?(Trepan)
|
222
219
|
$trepanning = Trepan.new(opts)
|
223
220
|
$trepanning.trace_filter << self.method(:debug)
|
@@ -237,13 +234,13 @@ end
|
|
237
234
|
module Kernel
|
238
235
|
# Same as Trepan.debug.
|
239
236
|
# FIXME figure out a way to remove duplication.
|
240
|
-
def
|
241
|
-
opts = {:hide_stack =>
|
237
|
+
def debugger(opts={}, &block)
|
238
|
+
opts = {:hide_stack => false}.merge(opts)
|
242
239
|
unless defined?($trepanning) && $trepanning.is_a?(Trepan)
|
243
|
-
$trepanning = Trepan.new
|
244
|
-
$trepanning.trace_filter << self.method(:
|
240
|
+
$trepanning = Trepan.new(opts)
|
241
|
+
$trepanning.trace_filter << self.method(:debugger)
|
245
242
|
end
|
246
|
-
$trepanning.debugger(opts
|
243
|
+
$trepanning.debugger(opts)
|
247
244
|
end
|
248
245
|
end
|
249
246
|
|
@@ -254,7 +251,7 @@ if __FILE__ == $0
|
|
254
251
|
puts 'block debugging...'
|
255
252
|
# It is imagined that there are all sorts of command-line options here.
|
256
253
|
# (I have a good imagination.)
|
257
|
-
Trepan.debug
|
254
|
+
Trepan.debug {
|
258
255
|
a = 2
|
259
256
|
b = square(a)
|
260
257
|
p "square of #{a} is #{b}"
|
@@ -39,17 +39,18 @@ Examples:
|
|
39
39
|
return false
|
40
40
|
end
|
41
41
|
hide_level =
|
42
|
-
if !settings[:
|
42
|
+
if (!settings[:hidelevel] || settings[:hidelevel] < 0) &&
|
43
|
+
@proc.hidelevels[Thread.current]
|
43
44
|
@proc.hidelevels[Thread.current]
|
44
|
-
else
|
45
|
+
else settings[:hidelevel]
|
45
46
|
end
|
46
47
|
stack_size = @proc.top_frame.stack_size - hide_level
|
47
48
|
opts = {
|
48
|
-
:basename =>
|
49
|
+
:basename => settings[:basename],
|
49
50
|
:current_pos => @proc.frame_index,
|
50
|
-
:maxstack =>
|
51
|
-
:maxwidth =>
|
52
|
-
:show_pc =>
|
51
|
+
:maxstack => settings[:maxstack],
|
52
|
+
:maxwidth => settings[:maxwidth],
|
53
|
+
:show_pc => settings[:show_pc]
|
53
54
|
}
|
54
55
|
opts[:count] =
|
55
56
|
if args.size > 1
|
@@ -180,7 +180,7 @@ if __FILE__ == $0
|
|
180
180
|
puts cmd.help(%w(help set))
|
181
181
|
puts '=' * 40
|
182
182
|
# require_relative '../../../lib/trepanning)
|
183
|
-
# Trepan.debug
|
183
|
+
# Trepan.debug
|
184
184
|
puts cmd.help(%w(help set *))
|
185
185
|
puts '=' * 40
|
186
186
|
puts cmd.help(%w(help set d.*))
|
data/processor/command/break.rb
CHANGED
@@ -7,16 +7,24 @@ class Trepan::Command::BreakCommand < Trepan::Command
|
|
7
7
|
unless defined?(HELP)
|
8
8
|
NAME = File.basename(__FILE__, '.rb')
|
9
9
|
HELP = <<-HELP
|
10
|
-
#{NAME} [
|
10
|
+
#{NAME} [LINE-NUMBER|OFFSET]
|
11
|
+
#{NAME} METHOD [LINE-NUMBER|OFFSET]
|
11
12
|
|
12
|
-
|
13
|
-
|
14
|
-
set a breakpoint at that
|
13
|
+
Set a breakpoint. If a line number is given, a breakpoint is set in
|
14
|
+
that line number of the current instruction sequence. If an offset is
|
15
|
+
given, a number prefaced with an "O", set a breakpoint at that
|
16
|
+
instruction offset.
|
17
|
+
|
18
|
+
With method name, a breakpoint it set at the beginning of the method.
|
19
|
+
current instruction sequence. Currently you can add a module name in
|
20
|
+
front of the method name, like FileUtils.cp, but not a class name like
|
21
|
+
Dir.pwd.
|
15
22
|
|
16
23
|
Examples:
|
17
24
|
#{NAME}
|
18
25
|
#{NAME} 10 # set breakpoint on line 10
|
19
26
|
#{NAME} o20 # set breakpoint VM Instruction Sequence offset 20
|
27
|
+
#{NAME} Kernel.pp # Set a breakpoint at the beginning of Kernel.pp
|
20
28
|
HELP
|
21
29
|
|
22
30
|
ALIASES = %w(b)
|
@@ -14,7 +14,7 @@ the debugger however may occur via breakpoints or explicit calls, or
|
|
14
14
|
exceptions.
|
15
15
|
|
16
16
|
If a parameter is given, a temporary breakpoint is set at that position
|
17
|
-
before continuing. Offset are numbers
|
17
|
+
before continuing. Offset are numbers prefixed with an "O" otherwise
|
18
18
|
the parameter is taken as a line number.
|
19
19
|
|
20
20
|
Examples:
|
@@ -23,7 +23,7 @@ Examples:
|
|
23
23
|
#{NAME} o20 # continue to VM Instruction Sequence offset 20
|
24
24
|
HELP
|
25
25
|
|
26
|
-
ALIASES = %w(c)
|
26
|
+
ALIASES = %w(c cont)
|
27
27
|
CATEGORY = 'running'
|
28
28
|
MAX_ARGS = 1 # Need at most this many
|
29
29
|
NEED_RUNNING = true
|
data/processor/command/delete.rb
CHANGED
data/processor/command/finish.rb
CHANGED
@@ -18,7 +18,7 @@ reduce the number of stack frames. Also, if a thread is switched, we
|
|
18
18
|
stop ignoring levels.
|
19
19
|
|
20
20
|
'next>' is similar in that it stops at a return, but it doesn't
|
21
|
-
|
21
|
+
guarantee the stack level is the same as or less than the current
|
22
22
|
one.
|
23
23
|
|
24
24
|
See the break command if you want to stop at a particular point in a
|
@@ -32,7 +32,7 @@ while 'break' will have less overhead.
|
|
32
32
|
# Need at most this many.
|
33
33
|
MAX_ARGS = 1
|
34
34
|
NEED_STACK = true
|
35
|
-
SHORT_HELP = 'Step
|
35
|
+
SHORT_HELP = 'Step to end of current method (step out)'
|
36
36
|
end
|
37
37
|
|
38
38
|
# This method runs the command
|
@@ -45,7 +45,7 @@ while 'break' will have less overhead.
|
|
45
45
|
count_str = args[1]
|
46
46
|
opts = {
|
47
47
|
:msg_on_error =>
|
48
|
-
"The '
|
48
|
+
"The '#{NAME}' command argument must eval to an integer. Got: %s" %
|
49
49
|
count_str,
|
50
50
|
:min_value => 1
|
51
51
|
}
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
# Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
|
3
3
|
require_relative '../base/subcmd'
|
4
|
+
require 'pp'
|
4
5
|
|
5
6
|
class Trepan::Subcommand::InfoIseq < Trepan::Subcommand
|
6
7
|
unless defined?(HELP)
|
@@ -54,6 +55,14 @@ Examples:
|
|
54
55
|
else
|
55
56
|
msg("Breakpoints have not been allocated.")
|
56
57
|
end
|
58
|
+
if iseq.compile_options
|
59
|
+
msg "\nCompile options:"
|
60
|
+
msg iseq.compile_options.pretty_inspect
|
61
|
+
end
|
62
|
+
if iseq.source
|
63
|
+
msg "Source string:"
|
64
|
+
msg @proc.safe_rep(iseq.source.inspect)
|
65
|
+
end
|
57
66
|
else
|
58
67
|
mess = "Can't find instruction sequence"
|
59
68
|
mess += " for #{args.join(' ')}" unless args.empty?
|
@@ -6,10 +6,10 @@ require_relative 'helper'
|
|
6
6
|
class Trepan::Subcommand::InfoRegistersDfp < Trepan::SubSubcommand
|
7
7
|
unless defined?(HELP)
|
8
8
|
HELP = 'Show the value of the VM dynamic frame pointer (DFP)'
|
9
|
-
MIN_ABBREV = '
|
9
|
+
MIN_ABBREV = 'df'.size
|
10
10
|
NAME = File.basename(__FILE__, '.rb')
|
11
11
|
NEED_STACK = true
|
12
|
-
PREFIX = %
|
12
|
+
PREFIX = %W(info registers #{NAME})
|
13
13
|
end
|
14
14
|
|
15
15
|
include Registers
|
@@ -21,18 +21,9 @@ end
|
|
21
21
|
if __FILE__ == $0
|
22
22
|
# Demo it.
|
23
23
|
require_relative '../../../mock'
|
24
|
-
require_relative '
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
testcmdMgr = Trepan::Subcmd.new(info_cmd)
|
30
|
-
cmd_name = Trepan::SubSubcommand::InfoRegistersDfp::PREFIX.join('')
|
31
|
-
infox_cmd = Trepan::SubSubcommand::InfoRegistersDfp.new(info_cmd.proc,
|
32
|
-
info_cmd,
|
33
|
-
cmd_name)
|
34
|
-
infox_cmd.run([])
|
35
|
-
|
36
|
-
# name = File.basename(__FILE__, '.rb')
|
37
|
-
# subcommand.summary_help(name)
|
24
|
+
require_relative '../registers'
|
25
|
+
cmd = MockDebugger::subsub_setup(Trepan::SubSubcommand::InfoRegisters,
|
26
|
+
Trepan::SubSubcommand::InfoRegistersDfp,
|
27
|
+
false)
|
28
|
+
cmd.run(['0'])
|
38
29
|
end
|
@@ -34,21 +34,9 @@ end
|
|
34
34
|
if __FILE__ == $0
|
35
35
|
# Demo it.
|
36
36
|
require_relative '../../../mock'
|
37
|
-
require_relative '
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
testcmdMgr = Trepan::Subcmd.new(info_cmd)
|
43
|
-
cmd_name = Trepan::SubSubcommand::InfoRegistersSp::PREFIX.join('')
|
44
|
-
infox_cmd = Trepan::SubSubcommand::InfoRegistersSp.new(info_cmd.proc,
|
45
|
-
info_cmd,
|
46
|
-
cmd_name)
|
47
|
-
# require_relative '../../../../lib/trepanning'
|
48
|
-
# dbgr = Trepan.new(:set_restart => true)
|
49
|
-
# dbgr.debugger
|
50
|
-
infox_cmd.run([])
|
51
|
-
|
52
|
-
# name = File.basename(__FILE__, '.rb')
|
53
|
-
# subcommand.summary_help(name)
|
37
|
+
require_relative '../registers'
|
38
|
+
cmd = MockDebugger::subsub_setup(Trepan::SubSubcommand::InfoRegisters,
|
39
|
+
Trepan::SubSubcommand::InfoRegistersLfp,
|
40
|
+
false)
|
41
|
+
cmd.run([])
|
54
42
|
end
|
@@ -13,7 +13,7 @@ See also "info disassemble" and "info registers".'
|
|
13
13
|
MIN_ABBREV = 'pc'.size
|
14
14
|
NAME = File.basename(__FILE__, '.rb')
|
15
15
|
NEED_STACK = true
|
16
|
-
PREFIX = %
|
16
|
+
PREFIX = %W(info registers #{NAME})
|
17
17
|
end
|
18
18
|
|
19
19
|
def run(args)
|
@@ -22,23 +22,10 @@ See also "info disassemble" and "info registers".'
|
|
22
22
|
end
|
23
23
|
|
24
24
|
if __FILE__ == $0
|
25
|
-
# Demo it.
|
26
25
|
require_relative '../../../mock'
|
27
|
-
require_relative '
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
testcmdMgr = Trepan::Subcmd.new(info_cmd)
|
33
|
-
cmd_name = Trepan::SubSubcommand::InfoRegistersPc::PREFIX.join('')
|
34
|
-
infox_cmd = Trepan::SubSubcommand::InfoRegistersPc.new(info_cmd.proc,
|
35
|
-
info_cmd,
|
36
|
-
cmd_name)
|
37
|
-
# require_relative '../../../../trepanning'
|
38
|
-
# dbgr = Trepan.new(:set_restart => true)
|
39
|
-
# dbgr.debugger
|
40
|
-
infox_cmd.run([])
|
41
|
-
|
42
|
-
# name = File.basename(__FILE__, '.rb')
|
43
|
-
# subcommand.summary_help(name)
|
26
|
+
require_relative '../registers'
|
27
|
+
cmd = MockDebugger::subsub_setup(Trepan::SubSubcommand::InfoRegisters,
|
28
|
+
Trepan::SubSubcommand::InfoRegistersPc,
|
29
|
+
false)
|
30
|
+
cmd.run([])
|
44
31
|
end
|
@@ -5,10 +5,10 @@ require_relative 'helper'
|
|
5
5
|
|
6
6
|
class Trepan::Subcommand::InfoRegistersSp < Trepan::SubSubcommand
|
7
7
|
unless defined?(HELP)
|
8
|
-
|
9
|
-
|
8
|
+
NAME = File.basename(__FILE__, '.rb')
|
9
|
+
HELP = <<EOH
|
10
10
|
usage:
|
11
|
-
info register
|
11
|
+
info register #{NAME} [NUMBER NUMBER ...|size]
|
12
12
|
|
13
13
|
With no arguments, all SP values for the current frame of the debugged
|
14
14
|
program are shown. If a number is given, then the entry at that
|
@@ -21,12 +21,12 @@ a stack pointed to by SP. Just before the addition is perofrmed, sp(1)
|
|
21
21
|
will have the value "a" contians and sp(2) will contain the value of
|
22
22
|
"b"
|
23
23
|
|
24
|
-
See also "info register LFP"
|
24
|
+
See also "info register LFP"
|
25
|
+
EOH
|
25
26
|
|
26
27
|
MIN_ABBREV = 'sp'.size
|
27
|
-
NAME = File.basename(__FILE__, '.rb')
|
28
28
|
NEED_STACK = true
|
29
|
-
PREFIX = %
|
29
|
+
PREFIX = %W(info registers #{NAME})
|
30
30
|
end
|
31
31
|
|
32
32
|
include Registers
|
@@ -48,28 +48,18 @@ end
|
|
48
48
|
if __FILE__ == $0
|
49
49
|
# Demo it.
|
50
50
|
require_relative '../../../mock'
|
51
|
-
require_relative '
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
dbgr, info_cmd = MockDebugger::setup('info')
|
56
|
-
testcmdMgr = Trepan::Subcmd.new(info_cmd)
|
57
|
-
cmd_name = Trepan::SubSubcommand::InfoRegistersSp::PREFIX.join('')
|
58
|
-
infox_cmd = Trepan::SubSubcommand::InfoRegistersSp.new(info_cmd.proc,
|
59
|
-
info_cmd,
|
60
|
-
cmd_name)
|
61
|
-
infox_cmd.summary_help(name)
|
62
|
-
puts
|
51
|
+
require_relative '../registers'
|
52
|
+
cmd = MockDebugger::subsub_setup(Trepan::SubSubcommand::InfoRegisters,
|
53
|
+
Trepan::SubSubcommand::InfoRegistersSp,
|
54
|
+
false)
|
63
55
|
# require_relative '../../../../lib/trepanning'
|
64
|
-
# dbgr = Trepan.new
|
56
|
+
# dbgr = Trepan.new
|
65
57
|
# dbgr.debugger
|
66
|
-
|
58
|
+
cmd.run([])
|
67
59
|
puts
|
68
60
|
%w(0 1 10).each do |val|
|
69
|
-
|
61
|
+
cmd.run([val])
|
70
62
|
puts '-' * 40
|
71
63
|
end
|
72
|
-
|
73
|
-
|
74
|
-
name = File.basename(__FILE__, '.rb')
|
64
|
+
cmd.run(['size'])
|
75
65
|
end
|