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,179 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
3
+ require 'rubygems'; require 'require_relative'
4
+ require_relative 'cmd'
5
+ require_relative '../../subcmd'
6
+ require_relative '../../help'
7
+
8
+ class Trepan::SubcommandMgr < Trepan::Command
9
+
10
+ include Trepan::Help
11
+
12
+ unless defined?(CATEGORY)
13
+ CATEGORY = 'status'
14
+ MIN_ARGS = 0
15
+ MAX_ARGS = nil
16
+ NAME = '?' # FIXME: Need to define this, but should
17
+ # pick this up from class/file name.
18
+ NEED_STACK = false
19
+ end
20
+
21
+ attr_accessor :subcmds # Array of instaniated Trepan::Subcommand objects
22
+ attr_reader :name # Name of command
23
+ attr_reader :last_args # Last arguments seen
24
+
25
+ # Initialize show subcommands. Note: instance variable name
26
+ # has to be setcmds ('set' + 'cmds') for subcommand completion
27
+ # to work.
28
+ def initialize(proc)
29
+ @name = obj_const(self, :NAME)
30
+ @subcmds = Trepan::Subcmd.new(self)
31
+ @proc = proc
32
+ load_debugger_subcommands(self)
33
+ end
34
+
35
+ # Create an instance of each of the debugger subcommands. Commands
36
+ # are found by importing files in the directory 'name' + '_sub'. Some
37
+ # files are excluded via an array set in initialize. For each of
38
+ # the remaining files, we import them and scan for class names
39
+ # inside those files and for each class name, we will create an
40
+ # instance of that class. The set of TrepanCommand class instances
41
+ # form set of possible debugger commands.
42
+ def load_debugger_subcommands(parent)
43
+
44
+ # Initialization
45
+ cmd_names = []
46
+ subcmd_names = []
47
+ cmd_dir = File.dirname(__FILE__)
48
+ subcmd_dir = File.join(cmd_dir, '..', name + '_subcmd')
49
+ files = Dir.glob(File.join(subcmd_dir, '*.rb'))
50
+ files.each do |rb|
51
+ basename = File.basename(rb, '.rb')
52
+ if File.directory?(File.join(File.dirname(rb), basename + '_subcmd'))
53
+ subcmd_names << name.capitalize + basename.capitalize
54
+ else
55
+ cmd_names << name.capitalize + basename.capitalize
56
+ end
57
+ require rb
58
+ end if File.directory?(subcmd_dir)
59
+
60
+ subcommands = {}
61
+ cmd_names.each do |name|
62
+ next unless Trepan::Subcommand.constants.member?(name)
63
+ subcmd_class = "Trepan::Subcommand::#{name}.new(self)"
64
+ cmd = self.instance_eval(subcmd_class)
65
+ cmd_name = cmd.name
66
+ @subcmds.add(cmd)
67
+ end
68
+ subcmd_names.each do |name|
69
+ next unless Trepan::SubSubcommand.constants.member?(name)
70
+ subcmd_class = "Trepan::SubSubcommand::#{name}.new(self, parent)"
71
+ begin
72
+ cmd = self.instance_eval(subcmd_class)
73
+ rescue
74
+ puts "Subcmd #{name} is bad"
75
+ end
76
+ cmd_name = cmd.name
77
+ @subcmds.add(cmd)
78
+ end
79
+ end
80
+
81
+ # Give help for a command which has subcommands. This can be
82
+ # called in several ways:
83
+ # help cmd
84
+ # help cmd subcmd
85
+ # help cmd commands
86
+ #
87
+ # Our shtick is to give help for the overall command only if
88
+ # subcommand or 'commands' is not given. If a subcommand is given and
89
+ # found, then specific help for that is given. If 'commands' is given
90
+ # we will list the all the subcommands.
91
+ def help(args)
92
+ if args.size <= 2
93
+ # "help cmd". Give the general help for the command part.
94
+ doc = my_const(:HELP)
95
+ if doc
96
+ return doc
97
+ else
98
+ errmsg('Sorry - author mess up. ' +
99
+ 'No help registered for command' +
100
+ @name)
101
+ return nil
102
+ end
103
+ end
104
+
105
+ subcmd_name = args[2]
106
+
107
+ if '*' == subcmd_name
108
+ help_text = ["List of subcommands for command '%s':" % @name]
109
+ help_text << columnize_commands(@subcmds.list)
110
+ return help_text
111
+ end
112
+
113
+ # "help cmd subcmd". Give help specific for that subcommand.
114
+ cmd = @subcmds.lookup(subcmd_name, false)
115
+ if cmd
116
+ if cmd.respond_to?(:help)
117
+ return cmd.help(args)
118
+ else
119
+ doc = obj_const(cmd, :HELP)
120
+ if doc
121
+ return doc
122
+ else
123
+ errmsg('Sorry - author mess up. ' +
124
+ 'No help registered for subcommand: ' +
125
+ subcmd_name + ', of command: ' +
126
+ @name)
127
+ return nil
128
+ end
129
+ end
130
+ else
131
+ matches = @subcmds.list.grep(/^#{subcmd_name}/).sort
132
+ if matches.empty?
133
+ errmsg("No #{name} subcommands found matching /^#{subcmd_name}/. Try \"help\" #{@name}.")
134
+ return nil
135
+ elsif 1 == matches.size
136
+ args[-1] = matches[0].to_s
137
+ help(args)
138
+ else
139
+ help_text = ["Subcommands of \"#{@name}\" matching /^#{subcmd_name}/:"]
140
+ help_text << columnize_commands(matches.sort)
141
+ return help_text
142
+ end
143
+ end
144
+ end
145
+
146
+ def run(args)
147
+ @last_args = args
148
+ if args.size < 2 || args.size == 2 && args[-1] == '*'
149
+ summary_list(obj_const(self, :NAME), @subcmds)
150
+ return false
151
+ end
152
+
153
+ subcmd_prefix = args[1]
154
+ # We were given: cmd subcmd ...
155
+ # Run that.
156
+ subcmd = @subcmds.lookup(subcmd_prefix)
157
+ if subcmd
158
+ subcmd.run(args)
159
+ else
160
+ undefined_subcmd(@name, subcmd_prefix)
161
+ end
162
+ end
163
+ end
164
+
165
+ if __FILE__ == $0
166
+ # Demo it.
167
+ require_relative '../../mock'
168
+ dbgr = MockDebugger::MockDebugger.new
169
+ # cmds = dbgr.core.processor.commands
170
+ # cmd = cmds['set']
171
+ # Trepan::SubcommandMgr.new(dbgr.core.processor)
172
+ # puts cmd.help(%w(help set))
173
+ # puts '=' * 40
174
+ # # require_relative '../../../lib/trepanning)
175
+ # # Trepan.debug(:set_restart => true)
176
+ # puts cmd.help(%w(help set *))
177
+ # puts '=' * 40
178
+ # puts cmd.help(%w(help set d.*))
179
+ end
@@ -0,0 +1,103 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
3
+ # A base class for debugger subcommands of subcommands.
4
+ #
5
+ # Note: don't end classname with Command (capital C as in SubCommand),
6
+ # since main 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
+ require_relative 'subcmd'
15
+
16
+ class Trepan
17
+
18
+ class SubSubcommand < Subcommand
19
+ def initialize(cmd, parent, name)
20
+ @cmd = cmd
21
+ @name = name
22
+ @parent = parent
23
+ @proc = parent.proc
24
+ end
25
+
26
+ def settings
27
+ @parent.settings
28
+ end
29
+
30
+ def string_in_show
31
+ help_constant_sym = if self.class.constants.member?('SHORT_HELP')
32
+ :SHORT_HELP
33
+ else :HELP
34
+ end
35
+ str = my_const(help_constant_sym)
36
+ %w(Show Set).each do |word|
37
+ if 0 == str.index(word)
38
+ str = str[word.size+1 ..-1].capitalize
39
+ break
40
+ end
41
+ end
42
+ str
43
+ end
44
+
45
+ # Set a Boolean-valued debugger setting.
46
+ def run_set_bool(args, default=true)
47
+ set_val = args.size < 2 ? 'on' : args[1]
48
+ setting = @name.gsub(/^(set|show)/,'')
49
+ begin
50
+ settings[setting.to_sym] = @proc.get_onoff(set_val)
51
+ run_show_bool(string_in_show)
52
+ rescue NameError, TypeError
53
+ end
54
+ end
55
+
56
+ def run_show_bool(what=nil)
57
+ setting = @name.gsub(/^(set|show)/,'')
58
+ val = show_onoff(settings[setting.to_sym])
59
+ what = setting unless what
60
+ msg('%s is %s.' % [what.chomp, val])
61
+ end
62
+
63
+ end
64
+
65
+ class SetBoolSubSubcommand < SubSubcommand
66
+ def run(args)
67
+ run_set_bool(args)
68
+ end
69
+
70
+ def save_command
71
+ val = settings[subcmd_setting_key] ? 'on' : 'off'
72
+ ["#{subcmd_prefix_string} #{val}"]
73
+ end
74
+ end
75
+
76
+ class ShowBoolSubSubcommand < SubSubcommand
77
+ def run(args)
78
+ run_show_bool(string_in_show)
79
+ end
80
+ end
81
+
82
+ class ShowIntSubSubcommand < SubSubcommand
83
+ def run(args)
84
+ run_show_int
85
+ end
86
+ end
87
+ end
88
+
89
+ if __FILE__ == $0
90
+ # Demo it.
91
+ require_relative '../../mock'
92
+ require_relative '../../subcmd'
93
+ name = File.basename(__FILE__, '.rb')
94
+
95
+ # FIXME: DRY the below code
96
+ dbgr, info_cmd = MockDebugger::setup('info')
97
+ testcmdMgr = Trepan::Subcmd.new(info_cmd)
98
+ cmd_name = 'testing'
99
+ infox_cmd = Trepan::SubSubcommand.new(info_cmd.proc,
100
+ info_cmd,
101
+ cmd_name)
102
+ infox_cmd.settings
103
+ end
@@ -0,0 +1,184 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
3
+ require 'rubygems'; require 'require_relative'
4
+ require_relative 'subcmd'
5
+ require_relative '../../subcmd'
6
+ require_relative '../../help'
7
+
8
+ require 'rubygems'; require 'require_relative'
9
+ class Trepan::SubSubcommandMgr < Trepan::Subcommand
10
+
11
+ include Trepan::Help
12
+
13
+ unless defined?(CATEGORY)
14
+ CATEGORY = 'status'
15
+ MIN_ARGS = 0
16
+ MAX_ARGS = nil
17
+ NAME = '?' # FIXME: Need to define this, but should
18
+ # pick this up from class/file name.
19
+ NEED_STACK = false
20
+ end
21
+
22
+ attr_accessor :pname
23
+ attr_accessor :subcmds # Array of instantiated Trepan::Subcommand objects
24
+
25
+ # Initialize show subcommands. Note: instance variable name
26
+ # has to be setcmds ('set' + 'cmds') for subcommand completion
27
+ # to work.
28
+ # FIXME: do we need proc still?
29
+ def initialize(proc, parent)
30
+ name = obj_const(self, :NAME)
31
+ @name = name.to_sym
32
+ @subcmds = Trepan::Subcmd.new(self)
33
+ @parent = parent
34
+ @pname = parent.name
35
+ @proc = parent.proc
36
+
37
+ # Set class constant SHORT_HELP to be the first line of HELP
38
+ # unless it has been defined in the class already.
39
+ # The below was the simplest way I could find to do this since
40
+ # we are the super class but want to set the subclass's constant.
41
+ # defined? didn't seem to work here.
42
+ c = self.class.constants
43
+ self.class.const_set('SHORT_HELP',
44
+ self.class.const_get('HELP')) if
45
+ c.member?('HELP') and !c.member?('SHORT_HELP')
46
+
47
+ load_debugger_subsubcommands(name, self)
48
+ end
49
+
50
+ # Create an instance of each of the debugger subcommands. Commands
51
+ # are found by importing files in the directory 'name' + 'sub'. Some
52
+ # files are excluded via an array set in initialize. For each of
53
+ # the remaining files, we import them and scan for class names
54
+ # inside those files and for each class name, we will create an
55
+ # instance of that class. The set of TrepanCommand class instances
56
+ # form set of possible debugger commands.
57
+ def load_debugger_subsubcommands(name, obj)
58
+
59
+ # Initialization
60
+ cmd_names = []
61
+ cmd_dir = File.dirname(__FILE__)
62
+ subcmd_dir = File.join(cmd_dir, '..', @pname + '_subcmd', name + '_subcmd')
63
+ files = Dir.glob(File.join(subcmd_dir, '*.rb'))
64
+ files.each do |rb|
65
+ cmd_names << name.capitalize + File.basename(rb, '.rb').capitalize
66
+ require rb
67
+ end if File.directory?(subcmd_dir)
68
+
69
+ subcommands = {}
70
+ cmd_names.each do |subname|
71
+ cmd_name = "#{pname}#{subname.downcase}"
72
+ subclass_name = "#{@pname.capitalize}#{subname}"
73
+ next unless
74
+ Trepan::SubSubcommand.constants.member?(subclass_name)
75
+ cmd = self.instance_eval("Trepan::SubSubcommand::" + subclass_name +
76
+ ".new(self, @parent, '#{cmd_name}')")
77
+ @subcmds.add(cmd, cmd_name)
78
+ end
79
+ end
80
+
81
+ # Give help for a command which has subcommands. This can be
82
+ # called in several ways:
83
+ # help cmd
84
+ # help cmd subcmd
85
+ # help cmd commands
86
+ #
87
+ # Our shtick is to give help for the overall command only if
88
+ # subcommand or 'commands' is not given. If a subcommand is given and
89
+ # found, then specific help for that is given. If 'commands' is given
90
+ # we will list the all the subcommands.
91
+ def help(args)
92
+ if args.size <= 3
93
+ # "help cmd". Give the general help for the command part.
94
+ doc = self.class.const_get(:HELP)
95
+ if doc
96
+ return doc
97
+ else
98
+ errmsg('Sorry - author mess up. ' +
99
+ 'No help registered for command' +
100
+ @name)
101
+ return nil
102
+ end
103
+ end
104
+
105
+ prefix = my_const(:PREFIX)
106
+ subcmd_name = args[prefix.size+1]
107
+ prefix_str = prefix.join(' ')
108
+
109
+ if '*' == subcmd_name
110
+ help_text = ["List of subcommands for '%s':" % prefix_str]
111
+ cmd_names = @subcmds.list.map{|c| c[prefix_str.size-1..-1]}
112
+ help_text << columnize_commands(cmd_names)
113
+ return help_text
114
+ end
115
+
116
+ # "help cmd subcmd". Give help specific for that subcommand if
117
+ # the command matches uniquely, or show a list of matching
118
+ # subcommands
119
+ keyprefix_str = prefix.join('')
120
+ key_str = keyprefix_str + subcmd_name
121
+ cmd = @subcmds.lookup(key_str, false)
122
+ if cmd
123
+ doc = obj_const(cmd, :HELP)
124
+ if doc
125
+ return doc
126
+ else
127
+ errmsg('Sorry - author mess up. ' +
128
+ 'No help registered for subcommand: ' +
129
+ subcmd_name + ', of command: ' +
130
+ @name)
131
+ return nil
132
+ end
133
+ else
134
+ matches = @subcmds.list.grep(/^#{key_str}/).sort
135
+ if matches.empty?
136
+ errmsg("No #{name} subcommands found matching /^#{subcmd_name}/. Try \"help #{@name}\".")
137
+ return nil
138
+ elsif 1 == matches.size
139
+ args[-1] = matches[0].to_s[keyprefix_str.size..-1]
140
+ help(args)
141
+ else
142
+ help_text = ["Subcommands of \"#{@name}\" matching /^#{subcmd_name}/:"]
143
+ help_text << columnize_commands(matches.sort)
144
+ return help_text
145
+ end
146
+ end
147
+ end
148
+
149
+ def run(args)
150
+ args = @parent.last_args if args.size == 0
151
+ if args.size < 3 || args.size == 3 && args[-1] == '*'
152
+ summary_list(obj_const(self, :NAME), @subcmds)
153
+ return false
154
+ end
155
+
156
+ subcmd_prefix = args[0..2].join('')
157
+ # We were given: cmd subcmd ...
158
+ # Run that.
159
+ subcmd = @subcmds.lookup(subcmd_prefix)
160
+ if subcmd
161
+ subcmd.run(args[2..-1])
162
+ else
163
+ undefined_subcmd(obj_const(self, :PREFIX).join(' '), args[-1])
164
+ end
165
+ end
166
+
167
+ end
168
+
169
+ if __FILE__ == $0
170
+ # Demo it.
171
+ require_relative '../../mock'
172
+ dbgr = MockDebugger::MockDebugger.new
173
+ # cmds = dbgr.core.processor.commands
174
+ # cmd = cmds['info']
175
+ # Trepan::SubSubcommandMgr.new(dbgr.core.processor, cmd)
176
+ # puts cmd.help(%w(help info registers))
177
+ # puts '=' * 40
178
+ # puts cmd.help(%w(help info registers *))
179
+ # puts '=' * 40
180
+ # FIXME
181
+ # require_relative '../../lib/trepanning'
182
+ # Trepan.debug(:set_restart => true)
183
+ # puts cmd.help(%w(help info registers p.*))
184
+ end
@@ -0,0 +1,100 @@
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::SetBreakpointCommand < Trepan::Command
6
+
7
+ ALIASES = %w(b brk)
8
+ CATEGORY = 'breakpoints'
9
+ NAME = File.basename(__FILE__, '.rb')
10
+ HELP = <<-HELP
11
+ #{NAME}
12
+ #{NAME} [line number|offset]
13
+ #{NAME} Class[.#]method[:line-or-offset]
14
+
15
+ Sets a breakpoint. In the first form, a breakpoint is set at the
16
+ current line you are stopped at. In the second form, you give a line
17
+ number or an offset. An offset is a number that is prefaced with 'O'
18
+ or 'o' and represents a Rubinius VM PC offset.
19
+
20
+ The current method name is used for the start of the search. If a line
21
+ number is given and the line number is not found in that method,
22
+ enclosing scopes are searched for the line.
23
+
24
+ The last form is the most explicit. Use '#' to specify an instance
25
+ method and '.' to specify a class method. If a line number or offset
26
+ is omitted, we use the first line of the method.
27
+
28
+ Examples:
29
+
30
+ #{NAME} # set breakpoint at the current line
31
+ #{NAME} 5 # set breakpoint on line 5
32
+ #{NAME} O5 # set breakpoint at offset 5
33
+ #{NAME} o5 # same as above
34
+ #{NAME} Array#pop::3 # Set break at instance method 'pop' in Array, line 3
35
+ #{NAME} Trepan.start:3 # Set break in class method 'start' of Trepan, line 3
36
+ #{NAME} Trepan.start:o3 # Same as above but at offset 3, not line 3.
37
+ #{NAME} Trepan.start # Set break in class method 'start' of Trepan
38
+
39
+ See also 'tbreak', 'info breakpoint', and 'delete'.
40
+ HELP
41
+ SHORT_HELP = 'Set a breakpoint at a point in a method'
42
+
43
+ def run(args, temp=false)
44
+ arg_str = args[1..-1].join(' ')
45
+
46
+ describe, klass_name, which, name, line, ip =
47
+ @proc.breakpoint_position(args[1..-1])
48
+ event = temp ? 'tbrkpt' : 'brkpt'
49
+ opts={:event => event, :temp => temp}
50
+ if name.kind_of?(Rubinius::CompiledMethod)
51
+ bp = @proc.set_breakpoint_method(describe, name, line, ip, opts)
52
+ else
53
+ return unless klass_name
54
+
55
+ begin
56
+ klass = @proc.debug_eval(klass_name, settings[:maxstring])
57
+ rescue NameError
58
+ errmsg "Unable to find class/module: #{klass_name}"
59
+ ask_deferred klass_name, which, name, line
60
+ return
61
+ end
62
+
63
+ begin
64
+ if which == "#"
65
+ method = klass.instance_method(name)
66
+ else
67
+ method = klass.method(name)
68
+ end
69
+ rescue NameError
70
+ errmsg "Unable to find method '#{name}' in #{klass}"
71
+ ask_deferred klass_name, which, name, line
72
+ return
73
+ end
74
+
75
+ bp = @proc.set_breakpoint_method(arg_str.strip, method, line, ip, opts)
76
+ end
77
+
78
+ bp.set_temp! if temp
79
+ return bp
80
+ end
81
+
82
+ def ask_deferred(klass_name, which, name, line)
83
+ if confirm('Would you like to defer this breakpoint to later?', false)
84
+ @proc.dbgr.add_deferred_breakpoint(klass_name, which, name, line)
85
+ msg 'Deferred breakpoint created.'
86
+ else
87
+ msg 'Not confirmed.'
88
+ end
89
+ end
90
+ end
91
+
92
+ if __FILE__ == $0
93
+ require_relative '../mock'
94
+ dbgr, cmd = MockDebugger::setup
95
+ cmd.run([cmd.name])
96
+ # require 'trepanning'
97
+ # Trepan.start(:set_restart => true)
98
+ cmd.run([cmd.name, __LINE__.to_s])
99
+ cmd.run([cmd.name, 'foo'])
100
+ end
@@ -0,0 +1,82 @@
1
+ require 'rubygems'; require 'require_relative'
2
+ require_relative 'base/cmd'
3
+ require_relative '../stepping'
4
+
5
+ class Trepan::Command::ContinueCommand < Trepan::Command
6
+ NAME = File.basename(__FILE__, '.rb')
7
+ HELP = <<-HELP
8
+ #{NAME} [breakpoint position]
9
+
10
+ Leave the debugger loop and continue execution. Subsequent entry to
11
+ the debugger however may occur via breakpoints or explicit calls, or
12
+ exceptions.
13
+
14
+ If a parameter is given, a temporary breakpoint is set at that position
15
+ before continuing.
16
+
17
+ Examples:
18
+ #{NAME}
19
+ #{NAME} 10 # continue to line 10
20
+
21
+ See also 'step', 'next', and 'nexti' commands.
22
+ HELP
23
+ ALIASES = %w(c cont)
24
+ CATEGORY = 'running'
25
+ MAX_ARGS = 1
26
+ NEED_RUNNING = true
27
+ SHORT_HELP = 'Continue execution of the debugged program'
28
+
29
+ # This is the method that runs the command
30
+ def run(args)
31
+
32
+ ## FIXME: DRY this code, tbreak and break.
33
+ unless args.size == 1
34
+ describe, klass_name, which, name, line, ip =
35
+ @proc.breakpoint_position(args[1..-1])
36
+ unless describe
37
+ errmsg "Can't parse temporary breakpoint location"
38
+ return
39
+ end
40
+ if name.kind_of?(Rubinius::CompiledMethod)
41
+ bp = @proc.set_breakpoint_method(describe, name, line, ip,
42
+ {:temp=>true, :event =>'tbrkpt'})
43
+ unless bp
44
+ errmsg "Trouble setting temporary breakpoint"
45
+ return
46
+ end
47
+ else
48
+ return unless klass_name
49
+ begin
50
+ klass = @proc.debug_eval(klass_name, settings[:maxstring])
51
+ rescue NameError
52
+ errmsg "Unable to find class/module: #{klass_name}"
53
+ return
54
+ end
55
+
56
+ begin
57
+ if which == "#"
58
+ method = klass.instance_method(name)
59
+ else
60
+ method = klass.method(name)
61
+ end
62
+ rescue NameError
63
+ errmsg "Unable to find method '#{name}' in #{klass}"
64
+ return
65
+ end
66
+ arg_str = args[1..-1].join(' ')
67
+ bp = @proc.set_breakpoint_method(arg_str.strip, method, line, nil,
68
+ {:temp=>true, :event =>'tbrkpt'})
69
+ unless bp
70
+ errmsg "Trouble setting temporary breakpoint"
71
+ return
72
+ end
73
+ end
74
+ end
75
+ @proc.continue('continue')
76
+ end
77
+ end
78
+
79
+ if __FILE__ == $0
80
+ require_relative '../mock'
81
+ dbgr, cmd = MockDebugger::setup
82
+ end
@@ -0,0 +1,30 @@
1
+ require 'rubygems'; require 'require_relative'
2
+ require_relative './base/cmd'
3
+
4
+ class Trepan::Command::DeleteBreakpontCommand < Trepan::Command
5
+ CATEGORY = 'breakpoints'
6
+ NAME = File.basename(__FILE__, '.rb')
7
+ SHORT_HELP = 'Delete a breakpoint'
8
+ HELP = <<-HELP
9
+ Specify the breakpoint by number, use 'info break' to see the numbers
10
+ HELP
11
+
12
+ def run(args)
13
+ if args.size != 2
14
+ errmsg 'Please specify which breakpoint by number'
15
+ return
16
+ end
17
+
18
+ begin
19
+ i = Integer(args[1])
20
+ rescue ArgumentError
21
+ errmsg "'#{args}' is not a number"
22
+ return
23
+ end
24
+
25
+ if @proc.delete_breakpoint_by_number(i)
26
+ msg('Deleted breakpoint %d.' % i)
27
+ end
28
+ end
29
+ end
30
+