rbx-trepanning 0.0.1-universal-rubinius

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.
Files changed (205) hide show
  1. data/ChangeLog +376 -0
  2. data/LICENSE +25 -0
  3. data/NEWS +2 -0
  4. data/README.textile +28 -0
  5. data/Rakefile +165 -0
  6. data/THANKS +14 -0
  7. data/app/breakpoint.rb +218 -0
  8. data/app/breakpoint.rbc +3564 -0
  9. data/app/brkptmgr.rb +138 -0
  10. data/app/brkptmgr.rbc +2827 -0
  11. data/app/default.rb +61 -0
  12. data/app/default.rbc +1011 -0
  13. data/app/display.rb +35 -0
  14. data/app/display.rbc +968 -0
  15. data/app/frame.rb +98 -0
  16. data/app/frame.rbc +1808 -0
  17. data/app/irb.rb +112 -0
  18. data/app/irb.rbc +2111 -0
  19. data/app/iseq.rb +95 -0
  20. data/app/iseq.rbc +1801 -0
  21. data/app/method.rb +173 -0
  22. data/app/method.rbc +2492 -0
  23. data/app/mock.rb +13 -0
  24. data/app/mock.rbc +398 -0
  25. data/app/options.rb +123 -0
  26. data/app/options.rbc +2183 -0
  27. data/app/run.rb +86 -0
  28. data/app/run.rbc +1244 -0
  29. data/app/util.rb +49 -0
  30. data/app/util.rbc +1144 -0
  31. data/app/validate.rb +30 -0
  32. data/app/validate.rbc +676 -0
  33. data/bin/trepan.compiled.rbc +1043 -0
  34. data/bin/trepanx +63 -0
  35. data/bin/trepanx.compiled.rbc +985 -0
  36. data/interface/base_intf.rb +95 -0
  37. data/interface/base_intf.rbc +1742 -0
  38. data/interface/script.rb +104 -0
  39. data/interface/script.rbc +1642 -0
  40. data/interface/user.rb +91 -0
  41. data/interface/user.rbc +1418 -0
  42. data/io/base_io.rb +94 -0
  43. data/io/base_io.rbc +1404 -0
  44. data/io/input.rb +112 -0
  45. data/io/input.rbc +1979 -0
  46. data/io/null_output.rb +42 -0
  47. data/io/null_output.rbc +730 -0
  48. data/io/string_array.rb +156 -0
  49. data/io/string_array.rbc +2466 -0
  50. data/lib/trepanning.rb +398 -0
  51. data/lib/trepanning.rbc +6661 -0
  52. data/processor/breakpoint.rb +161 -0
  53. data/processor/command/alias.rb +55 -0
  54. data/processor/command/backtrace.rb +46 -0
  55. data/processor/command/base/cmd.rb +124 -0
  56. data/processor/command/base/subcmd.rb +213 -0
  57. data/processor/command/base/submgr.rb +179 -0
  58. data/processor/command/base/subsubcmd.rb +103 -0
  59. data/processor/command/base/subsubmgr.rb +184 -0
  60. data/processor/command/break.rb +100 -0
  61. data/processor/command/continue.rb +82 -0
  62. data/processor/command/delete.rb +30 -0
  63. data/processor/command/directory.rb +43 -0
  64. data/processor/command/disassemble.rb +103 -0
  65. data/processor/command/down.rb +54 -0
  66. data/processor/command/eval.rb +31 -0
  67. data/processor/command/exit.rb +58 -0
  68. data/processor/command/finish.rb +78 -0
  69. data/processor/command/frame.rb +89 -0
  70. data/processor/command/help.rb +146 -0
  71. data/processor/command/info.rb +28 -0
  72. data/processor/command/info_subcmd/breakpoints.rb +75 -0
  73. data/processor/command/info_subcmd/file.rb +153 -0
  74. data/processor/command/info_subcmd/method.rb +71 -0
  75. data/processor/command/info_subcmd/program.rb +59 -0
  76. data/processor/command/info_subcmd/variables.rb +40 -0
  77. data/processor/command/irb.rb +96 -0
  78. data/processor/command/kill.rb +70 -0
  79. data/processor/command/list.rb +296 -0
  80. data/processor/command/next.rb +66 -0
  81. data/processor/command/nexti.rb +59 -0
  82. data/processor/command/pr.rb +38 -0
  83. data/processor/command/ps.rb +40 -0
  84. data/processor/command/restart.rb +60 -0
  85. data/processor/command/set.rb +47 -0
  86. data/processor/command/set_subcmd/auto.rb +28 -0
  87. data/processor/command/set_subcmd/auto_subcmd/dis.rb +33 -0
  88. data/processor/command/set_subcmd/auto_subcmd/eval.rb +54 -0
  89. data/processor/command/set_subcmd/auto_subcmd/irb.rb +34 -0
  90. data/processor/command/set_subcmd/auto_subcmd/list.rb +34 -0
  91. data/processor/command/set_subcmd/basename.rb +26 -0
  92. data/processor/command/set_subcmd/debug.rb +27 -0
  93. data/processor/command/set_subcmd/debug_subcmd/dbgr.rb +36 -0
  94. data/processor/command/set_subcmd/debug_subcmd/skip.rb +23 -0
  95. data/processor/command/set_subcmd/debug_subcmd/step.rb +23 -0
  96. data/processor/command/set_subcmd/different.rb +60 -0
  97. data/processor/command/set_subcmd/hidelevel.rb +63 -0
  98. data/processor/command/set_subcmd/kernelstep.rb +61 -0
  99. data/processor/command/set_subcmd/max.rb +29 -0
  100. data/processor/command/set_subcmd/max_subcmd/list.rb +49 -0
  101. data/processor/command/set_subcmd/max_subcmd/stack.rb +50 -0
  102. data/processor/command/set_subcmd/max_subcmd/string.rb +54 -0
  103. data/processor/command/set_subcmd/max_subcmd/width.rb +49 -0
  104. data/processor/command/set_subcmd/substitute.rb +25 -0
  105. data/processor/command/set_subcmd/substitute_subcmd/path.rb +56 -0
  106. data/processor/command/set_subcmd/trace.rb +37 -0
  107. data/processor/command/set_subcmd/trace_subcmd/print.rb +57 -0
  108. data/processor/command/show.rb +27 -0
  109. data/processor/command/show_subcmd/alias.rb +43 -0
  110. data/processor/command/show_subcmd/args.rb +26 -0
  111. data/processor/command/show_subcmd/auto.rb +28 -0
  112. data/processor/command/show_subcmd/auto_subcmd/dis.rb +37 -0
  113. data/processor/command/show_subcmd/auto_subcmd/eval.rb +28 -0
  114. data/processor/command/show_subcmd/auto_subcmd/irb.rb +23 -0
  115. data/processor/command/show_subcmd/auto_subcmd/list.rb +22 -0
  116. data/processor/command/show_subcmd/basename.rb +22 -0
  117. data/processor/command/show_subcmd/debug.rb +27 -0
  118. data/processor/command/show_subcmd/debug_subcmd/dbgr.rb +21 -0
  119. data/processor/command/show_subcmd/debug_subcmd/skip.rb +22 -0
  120. data/processor/command/show_subcmd/debug_subcmd/step.rb +22 -0
  121. data/processor/command/show_subcmd/different.rb +27 -0
  122. data/processor/command/show_subcmd/hidelevel.rb +42 -0
  123. data/processor/command/show_subcmd/kernelstep.rb +37 -0
  124. data/processor/command/show_subcmd/max.rb +30 -0
  125. data/processor/command/show_subcmd/max_subcmd/list.rb +38 -0
  126. data/processor/command/show_subcmd/max_subcmd/stack.rb +36 -0
  127. data/processor/command/show_subcmd/max_subcmd/string.rb +42 -0
  128. data/processor/command/show_subcmd/max_subcmd/width.rb +37 -0
  129. data/processor/command/show_subcmd/trace.rb +29 -0
  130. data/processor/command/show_subcmd/trace_subcmd/print.rb +38 -0
  131. data/processor/command/source.rb +83 -0
  132. data/processor/command/step.rb +41 -0
  133. data/processor/command/tbreak.rb +19 -0
  134. data/processor/command/unalias.rb +44 -0
  135. data/processor/command/up.rb +87 -0
  136. data/processor/default.rb +56 -0
  137. data/processor/disassemble.rb +32 -0
  138. data/processor/eval.rb +96 -0
  139. data/processor/frame.rb +211 -0
  140. data/processor/help.rb +72 -0
  141. data/processor/hook.rb +133 -0
  142. data/processor/load_cmds.rb +101 -0
  143. data/processor/location.rb +128 -0
  144. data/processor/main.rb +394 -0
  145. data/processor/mock.rb +137 -0
  146. data/processor/msg.rb +28 -0
  147. data/processor/running.rb +230 -0
  148. data/processor/stepping.rb +115 -0
  149. data/processor/subcmd.rb +160 -0
  150. data/processor/validate.rb +355 -0
  151. data/test/data/enable.right +36 -0
  152. data/test/data/fname-with-blank.cmd +6 -0
  153. data/test/data/fname-with-blank.right +1 -0
  154. data/test/data/quit-Xdebug.right +3 -0
  155. data/test/data/quit.cmd +5 -0
  156. data/test/data/quit.right +0 -0
  157. data/test/example/fname with blank.rb +1 -0
  158. data/test/example/gcd-xx.rb +18 -0
  159. data/test/example/gcd.rb +19 -0
  160. data/test/example/gcd1.rb +24 -0
  161. data/test/example/null.rb +1 -0
  162. data/test/example/thread1.rb +3 -0
  163. data/test/functional/fn_helper.rb +112 -0
  164. data/test/functional/test-break-name.rb +52 -0
  165. data/test/functional/test-break.rb +51 -0
  166. data/test/functional/test-finish.rb +70 -0
  167. data/test/functional/test-fn_helper.rb +43 -0
  168. data/test/functional/test-list.rb +55 -0
  169. data/test/functional/test-next-bug.rb +49 -0
  170. data/test/functional/test-next.rb +101 -0
  171. data/test/functional/test-step.rb +272 -0
  172. data/test/functional/test-step2.rb +35 -0
  173. data/test/functional/test-tbreak.rb +41 -0
  174. data/test/integration/file-diff.rb +89 -0
  175. data/test/integration/helper.rb +78 -0
  176. data/test/integration/test-fname-with-blank.rb +12 -0
  177. data/test/integration/test-quit.rb +25 -0
  178. data/test/unit/cmd-helper.rb +46 -0
  179. data/test/unit/test-app-brkpt.rb +30 -0
  180. data/test/unit/test-app-brkptmgr.rb +51 -0
  181. data/test/unit/test-app-iseq.rb +49 -0
  182. data/test/unit/test-app-method.rb +54 -0
  183. data/test/unit/test-app-options.rb +61 -0
  184. data/test/unit/test-app-run.rb +16 -0
  185. data/test/unit/test-app-util.rb +28 -0
  186. data/test/unit/test-app-validate.rb +18 -0
  187. data/test/unit/test-base-subcmd.rb +61 -0
  188. data/test/unit/test-bin-trepanx.rb +48 -0
  189. data/test/unit/test-cmd-alias.rb +49 -0
  190. data/test/unit/test-cmd-break.rb +23 -0
  191. data/test/unit/test-cmd-exit.rb +27 -0
  192. data/test/unit/test-cmd-help.rb +101 -0
  193. data/test/unit/test-cmd-kill.rb +48 -0
  194. data/test/unit/test-intf-user.rb +46 -0
  195. data/test/unit/test-io-input.rb +27 -0
  196. data/test/unit/test-proc-eval.rb +37 -0
  197. data/test/unit/test-proc-frame.rb +79 -0
  198. data/test/unit/test-proc-help.rb +16 -0
  199. data/test/unit/test-proc-hook.rb +30 -0
  200. data/test/unit/test-proc-load_cmds.rb +41 -0
  201. data/test/unit/test-proc-location.rb +48 -0
  202. data/test/unit/test-proc-main.rb +96 -0
  203. data/test/unit/test-proc-validate.rb +91 -0
  204. data/test/unit/test-subcmd-help.rb +51 -0
  205. metadata +337 -0
@@ -0,0 +1,161 @@
1
+ # Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
2
+ require 'rubygems'; require 'require_relative'
3
+ require_relative '../app/brkptmgr'
4
+ class Trepan
5
+
6
+ class CmdProcessor
7
+
8
+ attr_reader :brkpts # BreakpointManager.
9
+
10
+ attr_reader :brkpt # Breakpoint. If we are stopped at a
11
+ # breakpoint this is the one we
12
+ # found. (There may be other
13
+ # breakpoints that would have caused a stop
14
+ # as well; this is just one of them).
15
+ # If no breakpoint stop this is nil.
16
+
17
+ def breakpoint_initialize
18
+ @brkpts = BreakpointMgr.new
19
+ @brkpt = nil
20
+ end
21
+
22
+ def breakpoint?
23
+ @brkpt = @dbgr.breakpoint
24
+ return !!@brkpt && %w(tbrkpt brkpt).member?(@brkpt.event)
25
+ end
26
+
27
+ def breakpoint_find(bpnum, show_errmsg = true)
28
+ if 0 == @brkpts.size
29
+ errmsg('No breakpoints set.') if show_errmsg
30
+ return nil
31
+ elsif bpnum > brkpts.size || bpnum < 1
32
+ errmsg('Breakpoint number %d is out of range 1..%d' %
33
+ [bpnum, brkpts.size]) if show_errmsg
34
+ return nil
35
+ end
36
+ bp = @brkpts[bpnum]
37
+ unless bp
38
+ errmsg "Unknown breakpoint '#{bpnum}'" if show_errmsg
39
+ return nil
40
+ end
41
+ bp
42
+ end
43
+
44
+ def set_breakpoint_method(descriptor, meth, line=nil, ip=nil,
45
+ opts={:event => 'brkpt',:temp => false})
46
+ cm =
47
+ if meth.kind_of?(Method) || meth.kind_of?(UnboundMethod)
48
+ meth.executable
49
+ else
50
+ meth
51
+ end
52
+
53
+ unless cm.kind_of?(Rubinius::CompiledMethod)
54
+ errmsg "Unsupported method type: #{cm.class}"
55
+ return nil
56
+ end
57
+
58
+ if line
59
+ ip = cm.first_ip_on_line(line)
60
+
61
+ if ip == -1
62
+ errmsg "Unknown line '#{line}' in method '#{cm.name}'"
63
+ return nil
64
+ end
65
+ elsif !ip
66
+ line = cm.first_line
67
+ ip = 0
68
+ end
69
+
70
+ bp = @brkpts.add(descriptor, cm, ip, line, @brkpts.max+1, opts)
71
+ bp.activate
72
+ msg("Set %sbreakpoint #{bp.id}: #{meth.name}() at #{bp.location}" %
73
+ (opts[:temp] ? 'temporary ' : ''))
74
+ return bp
75
+ end
76
+
77
+ # MRI 1.9.2 code
78
+ # def breakpoint_find(bpnum, show_errmsg = true)
79
+ # if 0 == @brkpts.size
80
+ # errmsg('No breakpoints set.') if show_errmsg
81
+ # return nil
82
+ # elsif bpnum > @brkpts.max || bpnum < 1
83
+ # errmsg('Breakpoint number %d is out of range 1..%d' %
84
+ # [bpnum, @brkpts.max]) if show_errmsg
85
+ # return nil
86
+ # end
87
+ # bp = @brkpts[bpnum]
88
+ # if bp
89
+ # return bp
90
+ # else
91
+ # errmsg('Breakpoint number %d previously deleted.' %
92
+ # bpnum) if show_errmsg
93
+ # return nil
94
+ # end
95
+ # end
96
+
97
+ # # Does whatever needs to be done to set a breakpoint
98
+ # def breakpoint_line(line_number, iseq, temp=false)
99
+ # # FIXME: handle breakpoint conditions.
100
+ # iseq = iseq.child_iseqs.detect do |iseq|
101
+ # iseq.lineoffsets.keys.member?(line_number)
102
+ # end
103
+ # offset =
104
+ # if iseq
105
+ # # FIXME
106
+ # iseq.line2offsets(line_number)[1] || iseq.line2offsets(line_number)[0]
107
+ # else
108
+ # nil
109
+ # end
110
+ # unless offset
111
+ # place = "in #{iseq.source_container.join(' ')} " if iseq
112
+ # errmsg("No line #{line_number} found #{place}for breakpoint.")
113
+ # return nil
114
+ # end
115
+ # @brkpts.add(iseq, offset, :temp => temp)
116
+ # end
117
+
118
+ # def breakpoint_offset(offset, iseq, temp=false)
119
+ # # FIXME: handle breakpoint conditions.
120
+ # unless iseq.offsetlines.keys.member?(offset)
121
+ # errmsg("Offset #{offset} not found in #{iseq.name} for breakpoint.")
122
+ # return nil
123
+ # end
124
+ # @brkpts.add(iseq, offset, :temp => temp, :type => 'offset')
125
+ # end
126
+
127
+ # Delete a breakpoint given its breakpoint number.
128
+ # FIXME: use do_enable
129
+ def delete_breakpoint_by_number(bpnum, do_enable=true)
130
+ bp = breakpoint_find(bpnum)
131
+ return false unless bp
132
+ delete_breakpoint(bp)
133
+ end
134
+
135
+ def delete_breakpoint(bp)
136
+ @brkpts.delete_by_brkpt(bp)
137
+ return true
138
+ end
139
+
140
+ # MRI 1.9.2 code
141
+ # # Enable or disable a breakpoint given its breakpoint number.
142
+ # def en_disable_breakpoint_by_number(bpnum, do_enable=true)
143
+ # bp = breakpoint_find(bpnum)
144
+ # return false unless bp
145
+
146
+ # enable_disable = do_enable ? 'en' : 'dis'
147
+ # if bp.enabled? == do_enable
148
+ # errmsg('Breakpoint %d previously %sabled.' %
149
+ # [bpnum, enable_disable])
150
+ # return false
151
+ # end
152
+ # bp.enabled = do_enable
153
+ # return true
154
+ # end
155
+ end
156
+ end
157
+
158
+ if __FILE__ == $0
159
+ cmdproc = Trepan::CmdProcessor.new
160
+ cmdproc.breakpoint_initialize
161
+ end
@@ -0,0 +1,55 @@
1
+ # Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
2
+ require 'rubygems'; require 'require_relative'
3
+ require_relative 'base/cmd'
4
+
5
+ class Trepan::Command::AliasCommand < Trepan::Command
6
+
7
+ unless defined?(HELP)
8
+ NAME = File.basename(__FILE__, '.rb')
9
+ HELP = <<-HELP
10
+ #{NAME} ALIAS COMMAND
11
+
12
+ Add an alias for a COMMAND
13
+
14
+ See also 'unalias'.
15
+ HELP
16
+
17
+ CATEGORY = 'support'
18
+ MAX_ARGS = 2 # Need at most this many
19
+ NAME = File.basename(__FILE__, '.rb')
20
+ NEED_STACK = true
21
+ SHORT_HELP = 'Add an alias for a debugger command'
22
+ end
23
+
24
+ # Run command.
25
+ def run(args)
26
+ if args.size == 1
27
+ @proc.commands['show'].run(%w(show alias))
28
+ elsif args.size == 2
29
+ @proc.commands['show'].run(%W(show alias #{args[1]}))
30
+ else
31
+ junk, al, command = args
32
+ old_command = @proc.aliases[al]
33
+ if @proc.commands.member?(command)
34
+ @proc.aliases[al] = command
35
+ if old_command
36
+ msg("Alias '#{al}' for command '#{command}' replaced old " +
37
+ "alias for '#{old_command}'.")
38
+ else
39
+ msg "New alias '#{al}' for command '#{command}' created."
40
+ end
41
+ else
42
+ errmsg "You must alias to a command name, and '#{command}' isn't one."
43
+ end
44
+ end
45
+ end
46
+ end
47
+
48
+ if __FILE__ == $0
49
+ # Demo it.
50
+ require_relative '../mock'
51
+ dbgr, cmd = MockDebugger::setup
52
+ cmd.run %W(#{cmd.name} yy foo)
53
+ cmd.run [cmd.name]
54
+ cmd.run %W(cmd.name yy next)
55
+ end
@@ -0,0 +1,46 @@
1
+ require 'rubygems'; require 'require_relative'
2
+ require_relative './base/cmd'
3
+
4
+ class Trepan::Command::BacktraceCommand < Trepan::Command
5
+ ALIASES = %w(bt where)
6
+ CATEGORY = 'stack'
7
+ NAME = File.basename(__FILE__, '.rb')
8
+ HELP = <<-HELP
9
+ Show the call stack as a simple list.
10
+
11
+ Passing "-v" will also show the values of all locals variables
12
+ in each frame.
13
+ HELP
14
+ NEED_STACK = true
15
+ SHORT_HELP = 'Show the current call stack'
16
+
17
+ def run(args)
18
+ arg_str = args[1..-1].join(' ')
19
+ verbose = (arg_str =~ /-v/)
20
+
21
+ count =
22
+ if m = /(\d+)/.match(arg_str)
23
+ m[1].to_i
24
+ else
25
+ proc.stack_size
26
+ end
27
+
28
+ msg "Backtrace:"
29
+
30
+ @proc.dbgr.each_frame(@proc.top_frame) do |frame|
31
+ return if count and frame.number >= count
32
+
33
+
34
+ prefix = (frame == @proc.frame) ? '-->' : ' '
35
+ msg "%s #%d %s" % [prefix, frame.number,
36
+ frame.describe(:show_ip => verbose)]
37
+
38
+ if verbose
39
+ frame.local_variables.each do |local|
40
+ msg " #{local} = #{frame.run(local.to_s).inspect}"
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+
@@ -0,0 +1,124 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
3
+ # Base class of all commands. Code common to all commands is here.
4
+ # Note: don't end classname with Command (capital C) since main
5
+ # will think this a command name like QuitCommand
6
+ require 'rubygems'
7
+ require 'columnize'
8
+
9
+ class Trepan
10
+ class Command
11
+ attr_accessor :core, :proc
12
+
13
+ unless defined?(MIN_ARGS)
14
+ MIN_ARGS = 0 # run()'s args array must be at least this many
15
+ MAX_ARGS = nil # run()'s args array must be at least this many
16
+ NEED_STACK = false # We'll say that commands which need a stack
17
+ # to run have to declare that and those that
18
+ # don't don't have to mention it.
19
+ end
20
+
21
+ def initialize(proc)
22
+ @name = my_const(:NAME)
23
+ @proc = proc
24
+ end
25
+
26
+ def category
27
+ my_const(:CATEGORY)
28
+ end
29
+
30
+ # List commands arranged in an aligned columns
31
+ def columnize_commands(commands)
32
+ width = settings[:maxwidth]
33
+ Columnize::columnize(commands, width, ' ' * 4,
34
+ true, true, ' ' * 2).chomp
35
+ end
36
+
37
+ def columnize_numbers(commands)
38
+ width = settings[:maxwidth]
39
+ Columnize::columnize(commands, width, ', ',
40
+ false, false, ' ' * 2).chomp
41
+ end
42
+
43
+ # FIXME: probably there is a way to do the delegation to proc methods
44
+ # without having type it all out.
45
+
46
+ def confirm(message, default)
47
+ @proc.confirm(message, default)
48
+ end
49
+
50
+ def errmsg(message)
51
+ @proc.errmsg(message)
52
+ end
53
+
54
+ def obj_const(obj, name)
55
+ obj.class.const_get(name)
56
+ end
57
+
58
+ def msg(message)
59
+ @proc.msg(message)
60
+ end
61
+
62
+ # Convenience short-hand for @dbgr.intf[-1].msg_nocr
63
+ def msg_nocr(msg)
64
+ @proc.msg_nocr(msg)
65
+ end
66
+
67
+ def my_const(name)
68
+ # Set class constant SHORT_HELP to be the first line of HELP
69
+ # unless it has been defined in the class already.
70
+ # The below was the simplest way I could find to do this since
71
+ # we are the super class but want to set the subclass's constant.
72
+ # defined? didn't seem to work here.
73
+ c = self.class.constants
74
+ if c.member?('HELP') and !c.member?('SHORT_HELP')
75
+ short_help = self.class.const_get(:HELP).split("\n")[0].chomp('.')
76
+ self.class.const_set(:SHORT_HELP, short_help)
77
+ end
78
+ self.class.const_get(name)
79
+ end
80
+
81
+ def name
82
+ self.class.const_get(:NAME)
83
+ end
84
+
85
+ # The method that implements the debugger command.
86
+ def run(*args)
87
+ raise RuntimeError, 'You need to define this method elsewhere'
88
+ end
89
+
90
+ def settings
91
+ @proc.settings
92
+ end
93
+
94
+ def short_help
95
+ help_constant_sym = if self.class.constants.member?('SHORT_HELP')
96
+ :SHORT_HELP
97
+ else :HELP
98
+ end
99
+ my_const(help_constant_sym)
100
+ end
101
+
102
+ # From reference debugger
103
+ def run_code(str)
104
+ @proc.dbgr.current_frame.run(str)
105
+ end
106
+
107
+ def current_method
108
+ @proc.frame.method
109
+ end
110
+
111
+ def current_frame
112
+ @proc.frame
113
+ end
114
+
115
+ def variables
116
+ @proc.variables
117
+ end
118
+
119
+ def listen(step=false)
120
+ @proc.listen(step)
121
+ end
122
+
123
+ end
124
+ end
@@ -0,0 +1,213 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
3
+ # A base class for debugger subcommands.
4
+ #
5
+ # Note: don't end classname with Command (capital C) since main
6
+ # will think this a command name like QuitCommand
7
+ # ^
8
+
9
+ # Base Class for Trepan subcommands. We pull in some helper
10
+ # functions for command from module cmdfns.
11
+
12
+ require 'rubygems'; require 'require_relative'
13
+ require_relative 'cmd'
14
+
15
+ class Trepan
16
+
17
+ class Subcommand < Command
18
+
19
+ NotImplementedMessage =
20
+ "This method must be overridden in a subclass" unless
21
+ defined?(NotImplementedMessage)
22
+
23
+ attr_reader :name
24
+
25
+ unless defined?(IN_LIST)
26
+ IN_LIST = true # Show item in help list of commands
27
+ RUN_CMD = true # Run subcommand for those subcommands like "show"
28
+ # which append current settings to list output.
29
+ MIN_ABBREV = 1
30
+ NEED_STACK = false
31
+ NAME = 'your_command_name'
32
+ end
33
+
34
+
35
+ # cmd contains the command object that this
36
+ # command is invoked through. A debugger field gives access to
37
+ # the stack frame and I/O.
38
+ def initialize(cmd)
39
+ @cmd = cmd
40
+
41
+ # Convenience class access. We don't expect that any of these
42
+ # will change over the course of the program execution like
43
+ # errmsg(), msg(), and msg_nocr() might. (See the note below
44
+ # on these latter 3 methods.)
45
+ #
46
+ @core = cmd.core
47
+ @proc = cmd.proc
48
+ # @dbgr = cmd.dbgr
49
+
50
+ # By default the name of the subcommand will be the name of the
51
+ # last part of module (e.g. "args" in "info.args" or "basename"
52
+ # in "shows.basename"). However it *is* possible for one to change
53
+ # that -- perhaps one may want to put several subcommands into
54
+ # a single file. So in those cases, one will have to set @name
55
+ # accordingly by other means.
56
+ @name = my_const(:NAME).to_sym
57
+
58
+ end
59
+
60
+ # Convenience short-hand for @proc.confirm
61
+ def confirm(msg, default=false)
62
+ return(@proc.confirm(msg, default))
63
+ end
64
+
65
+ def prefix
66
+ my_const('PREFIX')
67
+ end
68
+
69
+ # Set a Boolean-valued debugger setting.
70
+ def run_set_bool(args, default=true)
71
+ onoff_arg = args.size < 3 ? 'on' : args[2]
72
+ begin
73
+ settings[subcmd_setting_key] = @proc.get_onoff(onoff_arg)
74
+ run_show_bool
75
+ rescue NameError, TypeError
76
+ end
77
+ end
78
+
79
+ # set an Integer-valued debugger setting.
80
+ def run_set_int(arg, msg_on_error, min_value=nil, max_value=nil)
81
+ if arg.strip.empty?
82
+ errmsg('You need to supply a number.')
83
+ return
84
+ end
85
+ val = @proc.get_an_int(arg,
86
+ :max_value => max_value,
87
+ :min_value => min_value,
88
+ :msg_on_error => msg_on_error
89
+ )
90
+ if val
91
+ settings[subcmd_setting_key] = val
92
+ run_show_int
93
+ end
94
+ end
95
+
96
+ # Generic subcommand showing a boolean-valued debugger setting.
97
+ def run_show_bool(what=nil)
98
+ val = show_onoff(settings[subcmd_setting_key])
99
+ what = @name unless what
100
+ msg("%s is %s." % [what, val])
101
+ end
102
+
103
+ # Generic subcommand integer value display
104
+ def run_show_int(what=nil)
105
+ val = settings[subcmd_setting_key]
106
+ what = self.class.const_get(:PREFIX)[1..-1].join(' ') unless what
107
+ msg("%s is %d." % [what, val])
108
+ end
109
+
110
+ # Generic subcommand value display. Pass in a hash which may
111
+ # which optionally contain:
112
+ #
113
+ # :name - the String name of key in settings to use. If :value
114
+ # (described below) is set, then setting :name does
115
+ # nothing.
116
+ #
117
+ # :what - the String name of what we are showing. If none is
118
+ # given, then we use the part of the SHORT_HELP string.
119
+ #
120
+ # :value - a String value associated with "what" above. If none
121
+ # is given, then we pick up the value from settings.
122
+ #
123
+ def run_show_val(opts={})
124
+ what = opts.member?(:what) ? opts[:what] : string_in_show
125
+ name = opts.member?(:name) ? opts[:name] : @name
126
+ val = opts.member?(:value) ? opts[:value] : settings[name]
127
+ msg("%s is %s." % [what, val])
128
+ end
129
+
130
+ def save_command_from_settings
131
+ ["#{subcmd_prefix_string} #{settings[subcmd_setting_key]}"]
132
+ end
133
+
134
+ def settings
135
+ @proc.settings
136
+ end
137
+
138
+ def subcmd_prefix_string
139
+ self.class.const_get(:PREFIX).join(' ')
140
+ end
141
+
142
+ def subcmd_setting_key
143
+ self.class.const_get(:PREFIX)[1..-1].join('').to_sym
144
+ end
145
+
146
+ # Return 'on' for true and 'off' for false, and ?? for anything else.
147
+ def show_onoff(bool)
148
+ case(bool)
149
+ when true; return 'on'
150
+ when false; return 'off'
151
+ when nil; return 'unset'
152
+ else return '??'
153
+ end
154
+ end
155
+
156
+ def string_in_show
157
+ my_const(:SHORT_HELP)['Show '.size .. -1].capitalize
158
+ end
159
+
160
+ def summary_help(subcmd_name)
161
+ msg_nocr("%-12s: %s" % [subcmd_name, my_const(:SHORT_HELP)])
162
+ end
163
+
164
+ end
165
+
166
+ class SetBoolSubcommand < Subcommand
167
+ def run(args)
168
+ run_set_bool(args)
169
+ end
170
+
171
+ def save_command
172
+ val = settings[subcmd_setting_key] ? 'on' : 'off'
173
+ ["#{subcmd_prefix_string} #{val}"]
174
+ end
175
+ end
176
+
177
+ class ShowBoolSubcommand < Subcommand
178
+ def run(args)
179
+ run_show_bool(string_in_show)
180
+ end
181
+ end
182
+
183
+ class ShowIntSubcommand < Subcommand
184
+ def run(args)
185
+ doc =
186
+ if self.respond_to?(:short_help)
187
+ short_help
188
+ else
189
+ my_const(:HELP)[5..-2].capitalize
190
+ end
191
+ run_show_int(doc)
192
+ end
193
+ end
194
+
195
+ end
196
+
197
+ if __FILE__ == $0
198
+ # Demo it.
199
+ require_relative '../../mock'
200
+ dbgr = MockDebugger::MockDebugger.new
201
+ # cmds = dbgr.core.processor.commands
202
+ # p cmds.keys
203
+ # subcmd = Trepan::Subcommand.new(cmds['exit'])
204
+ # def subcmd.msg(message)
205
+ # puts message
206
+ # end
207
+ # def subcmd.errmsg(message)
208
+ # puts message
209
+ # end
210
+ # p subcmd.settings
211
+ # p subcmd.show_onoff(subcmd.settings[:autoeval])
212
+ # subcmd.run_set_int('', 'Just a test')
213
+ end