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,128 @@
1
+ # Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
2
+ require 'rubygems'
3
+ require 'linecache'
4
+ require_relative 'disassemble'
5
+ require_relative 'msg'
6
+ require_relative 'frame'
7
+ class Trepan
8
+ class CmdProcessor
9
+ attr_accessor :reload_on_change
10
+
11
+ def location_initialize
12
+ @reload_on_change = nil
13
+ end
14
+
15
+ def resolve_file_with_dir(path_suffix)
16
+ settings[:directory].split(/:/).each do |dir|
17
+ dir =
18
+ if '$cwd' == dir
19
+ Dir.pwd
20
+ elsif '$cdir' == dir
21
+ Rubinius::OS_STARTUP_DIR
22
+ else
23
+ dir
24
+ end
25
+ next unless dir && File.directory?(dir)
26
+ try_file = File.join(dir, path_suffix)
27
+ return try_file if File.readable?(try_file)
28
+ end
29
+ nil
30
+ end
31
+
32
+ # Get line +line_number+ from file named +filename+. Return "\n"
33
+ # there was a problem. Leading blanks are stripped off.
34
+ def line_at(filename, line_number)
35
+ # We use linecache first to give precidence to user-remapped
36
+ # file names
37
+ line = LineCache::getline(filename, line_number, @reload_on_change)
38
+ unless line
39
+ # Try using search directories (set with command "directory")
40
+ if filename[0..0] != File::SEPARATOR
41
+ try_filename = resolve_file_with_dir(filename)
42
+ if try_filename &&
43
+ line = LineCache::getline(try_filename, line_number,
44
+ @reload_on_change)
45
+ LineCache::remap_file(filename, try_filename)
46
+ end
47
+ end
48
+ end
49
+ return nil unless line
50
+ return line.lstrip.chomp
51
+ end
52
+
53
+ def loc_and_text(loc)
54
+ vm_location = @frame.vm_location
55
+ filename = vm_location.method.active_path
56
+ line_no = vm_location.line
57
+ static = vm_location.static_scope
58
+
59
+ if @frame.eval?
60
+ file = LineCache::map_script(static.script)
61
+ text = LineCache::getline(static.script, line_no)
62
+ loc += " remapped #{canonic_file(file)}:#{line_no}"
63
+ else
64
+ text = line_at(filename, line_no)
65
+ map_file, map_line = LineCache::map_file_line(filename, line_no)
66
+ if [filename, line_no] != [map_file, map_line]
67
+ loc += " remapped #{canonic_file(map_file)}:#{map_line}"
68
+ end
69
+ end
70
+
71
+ [loc, line_no, text]
72
+ end
73
+
74
+ def print_location
75
+ # if %w(c-call call).member?(@event)
76
+ # # FIXME: Fix Ruby so we don't need this workaround?
77
+ # # See also where.rb
78
+ # opts = {}
79
+ # opts[:class] = @core.hook_arg if
80
+ # 'CFUNC' == @frame.type && @core.hook_arg && 0 == @frame_index
81
+ # msg format_stack_call(@frame, opts)
82
+ # elsif 'raise' == @core.event
83
+ # msg @core.hook_arg.inspect if @core.hook_arg # Exception object
84
+ # end
85
+
86
+ text = nil
87
+ # source_container = frame_container(@frame, false)
88
+ ev = if @event.nil? || 0 != @frame_index
89
+ ' '
90
+ else
91
+ (EVENT2ICON[@event] || @event)
92
+ end
93
+
94
+ @line_no = @frame.vm_location.line
95
+
96
+ loc = source_location_info
97
+ loc, @line_no, text = loc_and_text(loc)
98
+ ip_str = frame.method ? " @#{frame.next_ip}" : ''
99
+
100
+ msg "#{ev} (#{loc}#{ip_str})"
101
+
102
+ # if %w(return c-return).member?(@core.event)
103
+ # retval = Trepan::Frame.value_returned(@frame, @core.event)
104
+ # msg 'R=> %s' % retval.inspect
105
+ # end
106
+
107
+ if text && !text.strip.empty?
108
+ msg text
109
+ @line_no -= 1
110
+ else
111
+ show_bytecode
112
+ end
113
+ end
114
+
115
+ def source_location_info
116
+ filename = @frame.vm_location.method.active_path
117
+ canonic_filename =
118
+ if @frame.eval?
119
+ 'eval ' + safe_repr(@frame.eval_string.gsub("\n", ';').inspect, 20)
120
+ else
121
+ canonic_file(filename)
122
+ end
123
+ loc = "#{canonic_filename}:#{@frame.vm_location.line}"
124
+ return loc
125
+ end
126
+
127
+ end
128
+ end
data/processor/main.rb ADDED
@@ -0,0 +1,394 @@
1
+ # Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
2
+ # The main "driver" class for a command processor. Other parts of the
3
+ # command class and debugger command objects are pulled in from here.
4
+
5
+ require 'set'
6
+ require 'pathname' # For cleanpath
7
+
8
+ require 'rubygems'; require 'require_relative'
9
+ ## %w(default display eventbuf eval load_cmds location frame hook msg
10
+ ## validate).each do
11
+ %w(default breakpoint disassemble eval load_cmds location frame hook msg
12
+ running stepping validate).each do
13
+ |mod_str|
14
+ require_relative mod_str
15
+ end
16
+ ## require_relative '../app/brkptmgr'
17
+
18
+ class Trepan
19
+ class CmdProcessor
20
+
21
+ # SEE ALSO attr's in require_relative's of loop above.
22
+
23
+ attr_reader :cmd_name # command name before alias or macro resolution
24
+ attr_reader :cmd_argstr # Current command args, a String.
25
+ # This is current_command with the command
26
+ # name removed from the beginning.
27
+ ## attr_reader :core # Trepan core object
28
+ attr_reader :current_command # Current command getting run, a String.
29
+ attr_accessor :dbgr # Trepan instance (via
30
+ # Trepan::Core instance)
31
+ ## FIXME 1.9.2 has attr_reader !
32
+ attr_accessor :debug_nest # Number of nested debugs. Used in showing
33
+ # prompt.
34
+ attr_accessor :different_pos # Same type as settings[:different]
35
+ # this is the temporary value for the
36
+ # next stop while settings is the default
37
+ # value to use.
38
+ attr_accessor :event # Stop event
39
+ attr_accessor :leave_cmd_loop # Commands set this to signal to leave
40
+ # the command loop (which often continues to
41
+ # run the debugged program).
42
+ attr_accessor :line_no # Last line shown in "list" command
43
+ attr_accessor :next_thread # Thread. If non-nil then in
44
+ # stepping the thread has to be
45
+ # this thread.
46
+ attr_accessor :pass_exception # Pass an exception back
47
+ attr_accessor :prompt # String print before requesting input
48
+ attr_reader :settings # Hash[:symbol] of command
49
+ # processor settings
50
+ attr_reader :step_bp
51
+
52
+ # The following are used in to force stopping at a different line
53
+ # number. FIXME: could generalize to a position object.
54
+ attr_accessor :last_pos # Last position. 6-Tuple: of
55
+ # [location, container, stack_size,
56
+ # current_thread, pc_offset]
57
+
58
+
59
+ unless defined?(EVENT2ICON)
60
+ # Event icons used in printing locations.
61
+ EVENT2ICON = {
62
+ 'brkpt' => 'xx',
63
+ 'tbrkpt' => 'x1',
64
+ 'c-call' => 'C>',
65
+ 'c-return' => '<C',
66
+ 'step-call' => '->',
67
+ 'call' => '->',
68
+ 'class' => '::',
69
+ 'coverage' => '[]',
70
+ 'debugger-call' => ':o',
71
+ 'end' => '-|',
72
+ 'line' => '--',
73
+ 'raise' => '!!',
74
+ 'return' => '<-',
75
+ 'start' => '>>',
76
+ 'start' => '>>',
77
+ 'switch' => 'sw',
78
+ 'trace-var' => '$V',
79
+ 'unknown' => '?!',
80
+ 'vm' => 'VM',
81
+ 'vm-insn' => '..',
82
+ }
83
+ # These events are important enough event that we always want to
84
+ # stop on them.
85
+ UNMASKABLE_EVENTS = Set.new(['end', 'raise', 'unknown'])
86
+ end
87
+
88
+ def initialize(dbgr, settings={})
89
+ @dbgr = dbgr
90
+ @debug_nest = 1
91
+ @hidelevels = {}
92
+ @last_command = nil
93
+ @last_pos = [nil, nil, nil, nil, nil, nil]
94
+ @next_thread = nil
95
+ @user_variables = 0
96
+
97
+
98
+ start_cmds = settings.delete(:start_cmds)
99
+ start_file = settings.delete(:start_file)
100
+
101
+ @settings = settings.merge(DEFAULT_SETTINGS)
102
+ @different_pos = @settings[:different]
103
+
104
+ # FIXME: Rework using a general "set substitute file" command and
105
+ # a global default profile which gets read.
106
+ prelude_file = File.expand_path(File.join(File.dirname(__FILE__),
107
+ %w(.. data prelude.rb)))
108
+
109
+ ## Start with empty thread and frame info.
110
+ frame_teardown
111
+
112
+ # Run initialization routines for each of the "submodule"s.
113
+ # load_cmds has to come first.
114
+ ## %w(load_cmds breakpoint display eventbuf frame running validate
115
+ ## ).each do |submod|
116
+ %w(load_cmds breakpoint frame running validate).each do |submod|
117
+ self.send("#{submod}_initialize")
118
+ end
119
+ hook_initialize(commands)
120
+ end
121
+
122
+ def canonic_container(container)
123
+ [container[0], canonic_file(container[1])]
124
+ end
125
+
126
+ def canonic_file(filename)
127
+ # For now we want resolved filenames
128
+ @settings[:basename] ? File.basename(filename) :
129
+ # Cache this?
130
+ Pathname.new(filename).cleanpath.to_s
131
+ end
132
+
133
+ def compute_prompt
134
+ th = @current_thread
135
+ thread_str =
136
+ if 2 == Thread.list.size
137
+ ''
138
+ elsif th == Thread.main
139
+ '@main'
140
+ else
141
+ "@#{th.current.object_id}"
142
+ end
143
+ "%s#{settings[:prompt]}%s%s: " %
144
+ ['(' * @debug_nest, thread_str, ')' * @debug_nest]
145
+
146
+ end
147
+
148
+ # Check that we meed the criteria that cmd specifies it needs
149
+ def ok_for_running(cmd, name, nargs)
150
+ # TODO check execution_set against execution status.
151
+ # Check we have frame is not null
152
+ min_args = cmd.class.const_get(:MIN_ARGS)
153
+ if nargs < min_args
154
+ errmsg(("Command '%s' needs at least %d argument(s); " +
155
+ "got %d.") % [name, min_args, nargs])
156
+ return false
157
+ end
158
+ max_args = cmd.class.const_get(:MAX_ARGS)
159
+ if max_args and nargs > max_args
160
+ errmsg(("Command '%s' needs at most %d argument(s); " +
161
+ "got %d.") % [name, max_args, nargs])
162
+ return false
163
+ end
164
+ # if cmd.class.const_get(:NEED_RUNNING) && !...
165
+ # errmsg "Command '%s' requires a running program." % name
166
+ # return false
167
+ # end
168
+
169
+ if cmd.class.const_get(:NEED_STACK) && !@frame
170
+ errmsg "Command '%s' requires a running stack frame." % name
171
+ return false
172
+ end
173
+
174
+ return true
175
+ end
176
+
177
+ # Run one debugger command. True is returned if we want to quit.
178
+ def process_command_and_quit?()
179
+ intf = @dbgr.intf
180
+ return true if intf[-1].input.eof? && intf.size == 1
181
+ while !intf[-1].input.eof? || intf.size > 1
182
+ begin
183
+ @current_command = read_command().strip
184
+ if @current_command.empty?
185
+ if @last_command && intf[-1].interactive?
186
+ @current_command = @last_command
187
+ else
188
+ next
189
+ end
190
+ end
191
+ next if @current_command[0..0] == '#' # Skip comment lines
192
+ break
193
+ rescue IOError, Errno::EPIPE
194
+ if @dbgr.intf.size > 1
195
+ @dbgr.intf.pop
196
+ @last_command = nil
197
+ print_location
198
+ else
199
+ msg "That's all folks..."
200
+ ## FIXME: think of something better.
201
+ quit('exit!')
202
+ return true
203
+ end
204
+ end
205
+ end
206
+ leave_cmdloop = run_command(@current_command)
207
+
208
+ # Save it to the history.
209
+ @dbgr.history_io.puts @last_command
210
+ end
211
+
212
+ def after_cmdloop
213
+ @cmdloop_posthooks.run
214
+ end
215
+
216
+ def before_cmdloop
217
+
218
+ frame_setup
219
+
220
+ @unconditional_prehooks.run
221
+ if breakpoint?
222
+ delete_breakpoint(@brkpt) if @brkpt.temp?
223
+ @last_pos = [@frame.vm_location, @stack_size, @current_thread, @event]
224
+ else
225
+ if stepping_skip? # || @stack_size <= @hide_level
226
+ step(@return_to_program, @step_count)
227
+ return true
228
+ elsif @event == 'start'
229
+ step('step', 0)
230
+ return true
231
+ end
232
+ end
233
+
234
+ @prompt = "(#{@settings[:prompt]}): " # compute_prompt
235
+
236
+ @leave_cmd_loop = false
237
+ print_location unless @settings[:traceprint]
238
+ # if 'trace-var' == @event
239
+ # msg "Note: we are stopped *after* the above location."
240
+ # end
241
+
242
+ # @eventbuf.add_mark if @settings[:tracebuffer]
243
+
244
+ @return_to_program = false
245
+ @cmdloop_prehooks.run
246
+ return false
247
+ end
248
+
249
+
250
+ # This is the main entry point.
251
+ def process_commands
252
+ skip_command = before_cmdloop
253
+ while not @leave_cmd_loop do
254
+ begin
255
+ if !skip_command
256
+ break if process_command_and_quit?()
257
+ end
258
+ if @return_to_program
259
+ after_cmdloop
260
+ if @step_count >= 0
261
+ @step_bp = step_over_by(1)
262
+ run_command('disassemble') if settings[:debugstep]
263
+ dbgr.listen('step' == @return_to_program)
264
+ else
265
+ @step_bp = nil
266
+ dbgr.listen
267
+ end
268
+ skip_command = before_cmdloop
269
+ end
270
+ rescue SystemExit
271
+ ## @dbgr.stop
272
+ raise
273
+ rescue Exception => exc
274
+ errmsg("Internal debugger error: #{exc.inspect}")
275
+ exception_dump(exc, @settings[:debugexcept], $!.backtrace)
276
+ end
277
+ end
278
+ after_cmdloop
279
+ end
280
+
281
+ # Run current_command, a String. @last_command is set after the
282
+ # command is run if it is a command.
283
+ def run_command(current_command)
284
+ eval_command =
285
+ if current_command[0..0] == '!'
286
+ current_command[0] = ''
287
+ else
288
+ false
289
+ end
290
+
291
+ unless eval_command
292
+ # Expand macros. FIXME: put in a procedure
293
+ args = current_command.split
294
+ while true do
295
+ macro_cmd_name = args[0]
296
+ return false if args.size == 0
297
+ break unless @macros.member?(macro_cmd_name)
298
+ current_command = @macros[macro_cmd_name].call(*args[1..-1])
299
+ msg current_command if settings[:debugmacro]
300
+ if current_command.is_a?(Array) &&
301
+ current_command.any {|val| !val.is_a?(String)}
302
+ args = current_command
303
+ elsif current_command.is_a?(String)
304
+ args = current_command.split
305
+ else
306
+ errmsg("macro #{macro_cmd_name} should return an Array " +
307
+ "of Strings or a String. Got #{current_command.inspect}")
308
+ return false
309
+ end
310
+ end
311
+
312
+ @cmd_name = args[0]
313
+ run_cmd_name =
314
+ if @aliases.member?(@cmd_name)
315
+ @aliases[@cmd_name]
316
+ else
317
+ @cmd_name
318
+ end
319
+
320
+ if @commands.member?(run_cmd_name)
321
+ cmd = @commands[run_cmd_name]
322
+ if ok_for_running(cmd, run_cmd_name, args.size-1)
323
+ @cmd_argstr = current_command[@cmd_name.size..-1].lstrip
324
+ cmd.run(args)
325
+ @last_command = current_command
326
+ end
327
+ return false
328
+ end
329
+ end
330
+
331
+ # Eval anything that's not a command or has been
332
+ # requested to be eval'd
333
+ if settings[:autoeval] || eval_command
334
+ eval_code(current_command, @settings[:maxstring])
335
+ else
336
+ undefined_command(cmd_name)
337
+ end
338
+ return false
339
+ end
340
+
341
+ # Error message when a command doesn't exist
342
+ def undefined_command(cmd_name)
343
+ errmsg('Undefined command: "%s". Try "help".' % cmd_name)
344
+ end
345
+
346
+ # FIXME: Allow access to both Trepan::CmdProcessor and Trepan
347
+ # for index [] and []=.
348
+ # If there is a Trepan::CmdProcessor setting that would take precidence.
349
+ # def settings
350
+ # @settings.merge(@dbgr.settings) # wrong because this doesn't allow []=
351
+ # end
352
+ end
353
+ end
354
+
355
+ if __FILE__ == $0
356
+ $0 = 'foo' # So we don't get here again
357
+ require_relative '../lib/trepanning'
358
+ dbg = Trepan.new(:nx => true)
359
+ cmdproc = dbg.instance_variable_get('@processor')
360
+ cmdproc.msg('I am main')
361
+ cmdproc.errmsg('Whoa!')
362
+ cmds = cmdproc.commands
363
+ p cmdproc.aliases
364
+ p cmdproc.commands.keys.sort
365
+ cmd_name, cmd_obj = cmds.first
366
+ puts cmd_obj.class.const_get(:HELP)
367
+ puts cmd_obj.class.const_get(:SHORT_HELP)
368
+
369
+ cmdproc.instance_variable_set('@current_thread', Thread.current)
370
+ puts cmdproc.compute_prompt
371
+ Thread.new{ puts cmdproc.compute_prompt }.join
372
+
373
+ x = Thread.new{ Thread.pass; x = 1 }
374
+ puts cmdproc.compute_prompt
375
+ x.join
376
+ cmdproc.debug_nest += 1
377
+ puts cmdproc.compute_prompt
378
+
379
+ # if ARGV.size > 0
380
+ # cmdproc.msg('Enter "q" to quit')
381
+ # cmdproc.process_commands
382
+ # else
383
+ # $input = []
384
+ # class << cmdproc
385
+ # def read_command
386
+ # $input.shift
387
+ # end
388
+ # end
389
+ # $input = ['1+2']
390
+ # cmdproc.process_command_and_quit?
391
+ # $input = ['!s = 5'] # ! means eval line
392
+ # cmdproc.process_command_and_quit?
393
+ # end
394
+ end
data/processor/mock.rb ADDED
@@ -0,0 +1,137 @@
1
+ # Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
2
+ # Mock setup for commands.
3
+ require 'rubygems'; require 'require_relative'
4
+
5
+ require_relative 'main'
6
+
7
+ # require_relative '../app/core'
8
+ require_relative '../app/default'
9
+ require_relative '../app/frame'
10
+ require_relative '../interface/user' # user interface (includes I/O)
11
+
12
+ module MockDebugger
13
+ class MockDebugger
14
+ attr_accessor :trace_filter # Procs/Methods we ignore.
15
+
16
+ attr_accessor :frame # Actually a "Rubinius::Location object
17
+ attr_accessor :core # access to Debugger::Core instance
18
+ attr_accessor :intf # The way the outside world interfaces with us.
19
+ attr_reader :initial_dir # String. Current directory when program
20
+ # started. Used in restart program.
21
+ attr_accessor :restart_argv # How to restart us, empty or nil.
22
+ # Note restart[0] is typically $0.
23
+ attr_reader :settings # Hash[:symbol] of things you can configure
24
+ attr_accessor :processor
25
+
26
+ # FIXME: move more stuff of here and into Trepan::CmdProcessor
27
+ # These below should go into Trepan::CmdProcessor.
28
+ attr_reader :cmd_argstr, :cmd_name, :vm_locations, :current_frame,
29
+ :debugee_thread
30
+
31
+ def initialize(settings={})
32
+ @before_cmdloop_hooks = []
33
+ @settings = Trepanning::DEFAULT_SETTINGS.merge(settings)
34
+ @intf = [Trepan::UserInterface.new]
35
+ @vm_locations = Rubinius::VM.backtrace(1, true)
36
+ @current_frame = Trepan::Frame.new(self, 0, @vm_locations[0])
37
+ @debugee_thread = Thread.current
38
+ @frames = []
39
+ @restart_argv = Rubinius::OS_STARTUP_DIR
40
+
41
+ ## @core = Trepan::Core.new(self)
42
+ @trace_filter = []
43
+
44
+ # Don't allow user commands in mocks.
45
+ ## @core.processor.settings[:user_cmd_dir] = nil
46
+
47
+ end
48
+
49
+ def frame(num)
50
+ @frames[num] ||= Trepan::Frame.new(self, num, @vm_locations[num])
51
+ end
52
+ end
53
+
54
+ # Common Mock debugger setup
55
+ def setup(name=nil, show_constants=true)
56
+ unless name
57
+ loc = Rubinius::VM.backtrace(1, true)[0]
58
+ name = File.basename(loc.file, '.rb')
59
+ end
60
+
61
+ if ARGV.size > 0 && ARGV[0] == 'debug'
62
+ require_relative '../lib/trepanning'
63
+ dbgr = Trepan.new
64
+ dbgr.debugger
65
+ else
66
+ dbgr = MockDebugger.new
67
+ end
68
+
69
+ cmdproc = Trepan::CmdProcessor.new(dbgr)
70
+ cmdproc.frame = dbgr.frame(0)
71
+ dbgr.processor = cmdproc
72
+
73
+ cmdproc.load_cmds_initialize
74
+ cmds = cmdproc.commands
75
+ cmd = cmds[name]
76
+ cmd.proc.frame_setup
77
+ show_special_class_constants(cmd) if show_constants
78
+
79
+ def cmd.msg(message)
80
+ puts message
81
+ end
82
+ def cmd.msg_nocr(message)
83
+ print message
84
+ end
85
+ def cmd.errmsg(message)
86
+ puts "Error: #{message}"
87
+ end
88
+ def cmd.confirm(prompt, default)
89
+ true
90
+ end
91
+
92
+ return dbgr, cmd
93
+ end
94
+ module_function :setup
95
+
96
+ def sub_setup(sub_class, run=true)
97
+ sub_name = sub_class.const_get('PREFIX')
98
+ dbgr, cmd = setup(sub_name[0], false)
99
+ sub_cmd = sub_class.new(cmd)
100
+ sub_cmd.summary_help(sub_cmd.name)
101
+ puts
102
+ sub_cmd.run([cmd.name]) if run
103
+ return sub_cmd
104
+ end
105
+ module_function :sub_setup
106
+
107
+ def subsub_setup(sub_class, subsub_class, run=true)
108
+ subsub_name = subsub_class.const_get('PREFIX')
109
+ dbgr, cmd = setup(subsub_name[0], false)
110
+ sub_cmd = sub_class.new(dbgr.processor, cmd)
111
+ subsub_cmd = subsub_class.new(cmd.proc, sub_cmd, subsub_name.join(''))
112
+ subsub_cmd.run([subsub_cmd.name]) if run
113
+ return subsub_cmd
114
+ end
115
+ module_function :subsub_setup
116
+
117
+ def show_special_class_constants(cmd)
118
+ puts 'ALIASES: %s' % [cmd.class.const_get('ALIASES').inspect] if
119
+ cmd.class.constants.member?(:ALIASES)
120
+ %w(CATEGORY MIN_ARGS MAX_ARGS
121
+ NAME NEED_STACK SHORT_HELP).each do |name|
122
+ puts '%s: %s' % [name, cmd.class.const_get(name).inspect]
123
+ end
124
+ puts '-' * 30
125
+ puts cmd.class.const_get('HELP')
126
+ puts '=' * 30
127
+ end
128
+ module_function :show_special_class_constants
129
+
130
+ end
131
+
132
+ if __FILE__ == $0
133
+ dbgr = MockDebugger::MockDebugger.new
134
+ p dbgr.settings
135
+ puts '=' * 10
136
+ # p dbgr.core.processor.settings
137
+ end
data/processor/msg.rb ADDED
@@ -0,0 +1,28 @@
1
+ # Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
2
+ # I/O related command processor methods
3
+ require 'rubygems'; require 'require_relative'
4
+ require_relative '../app/util'
5
+ class Trepan
6
+ include Util
7
+ class CmdProcessor
8
+ def errmsg(message)
9
+ @dbgr.intf[-1].errmsg(safe_rep(message))
10
+ end
11
+
12
+ def msg(message)
13
+ @dbgr.intf[-1].msg(safe_rep(message))
14
+ end
15
+
16
+ def msg_nocr(message)
17
+ @dbgr.intf[-1].msg_nocr(safe_rep(message))
18
+ end
19
+
20
+ def read_command()
21
+ @dbgr.intf[-1].read_command(@prompt)
22
+ end
23
+
24
+ def safe_rep(str)
25
+ Trepan::Util::safe_repr(str, @settings[:maxstring])
26
+ end
27
+ end
28
+ end